mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-18 11:36:53 +02:00
refactor(v2): add useThemeConfig hook + cleanup useless theme default values (#3394)
* refactor(theme-classic): clean default or fallback values * refactor(theme-classic): fix announcementbar undefined error * refactor(theme-classic): fixed react hook warning error * refactor(theme-classic): revert prism destruct * create useThemeConfig and use it whenever possible * validateThemeConfig => add [] as default value for almost all arrays * fix tests Co-authored-by: slorber <lorber.sebastien@gmail.com>
This commit is contained in:
parent
f5f2064656
commit
0951eef2d7
16 changed files with 154 additions and 142 deletions
|
@ -11,14 +11,19 @@ const {ThemeConfigSchema, DEFAULT_CONFIG} = require('../validateThemeConfig');
|
|||
|
||||
const {normalizeThemeConfig} = require('@docusaurus/utils-validation');
|
||||
|
||||
function testValidateThemeConfig(themeConfig) {
|
||||
return normalizeThemeConfig(ThemeConfigSchema, themeConfig);
|
||||
function testValidateThemeConfig(partialThemeConfig) {
|
||||
return normalizeThemeConfig(ThemeConfigSchema, {
|
||||
...DEFAULT_CONFIG,
|
||||
...partialThemeConfig,
|
||||
});
|
||||
}
|
||||
|
||||
function testOk(partialConfig) {
|
||||
expect(testValidateThemeConfig(partialConfig)).toEqual({
|
||||
function testOk(partialThemeConfig) {
|
||||
expect(
|
||||
testValidateThemeConfig({...DEFAULT_CONFIG, ...partialThemeConfig}),
|
||||
).toEqual({
|
||||
...DEFAULT_CONFIG,
|
||||
...partialConfig,
|
||||
...partialThemeConfig,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -101,7 +106,10 @@ describe('themeConfig', () => {
|
|||
};
|
||||
expect(testValidateThemeConfig(altTagConfig)).toEqual({
|
||||
...DEFAULT_CONFIG,
|
||||
...altTagConfig,
|
||||
navbar: {
|
||||
...DEFAULT_CONFIG.navbar,
|
||||
...altTagConfig.navbar,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -117,7 +125,7 @@ describe('themeConfig', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe.only('customCss config', () => {
|
||||
describe('customCss config', () => {
|
||||
test('should accept customCss undefined', () => {
|
||||
testOk({
|
||||
customCss: undefined,
|
||||
|
|
|
@ -7,21 +7,23 @@
|
|||
|
||||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useThemeConfig from '../../utils/useThemeConfig';
|
||||
import useUserPreferencesContext from '@theme/hooks/useUserPreferencesContext';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
|
||||
function AnnouncementBar(): JSX.Element | null {
|
||||
const {
|
||||
siteConfig: {themeConfig: {announcementBar = {}} = {}} = {},
|
||||
} = useDocusaurusContext();
|
||||
const {content, backgroundColor, textColor, isCloseable} = announcementBar;
|
||||
const {
|
||||
isAnnouncementBarClosed,
|
||||
closeAnnouncementBar,
|
||||
} = useUserPreferencesContext();
|
||||
const {announcementBar} = useThemeConfig();
|
||||
|
||||
if (!announcementBar) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {content, backgroundColor, textColor, isCloseable} = announcementBar;
|
||||
if (!content || (isCloseable && isAnnouncementBarClosed)) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -12,11 +12,11 @@ import clsx from 'clsx';
|
|||
import Highlight, {defaultProps} from 'prism-react-renderer';
|
||||
import copy from 'copy-text-to-clipboard';
|
||||
import rangeParser from 'parse-numeric-range';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import usePrismTheme from '@theme/hooks/usePrismTheme';
|
||||
import type {Props} from '@theme/CodeBlock';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
import useThemeConfig from '../../utils/useThemeConfig';
|
||||
|
||||
const highlightLinesRangeRegex = /{([\d,-]+)}/;
|
||||
const getHighlightDirectiveRegex = (
|
||||
|
@ -93,11 +93,7 @@ export default ({
|
|||
className: languageClassName,
|
||||
metastring,
|
||||
}: Props): JSX.Element => {
|
||||
const {
|
||||
siteConfig: {
|
||||
themeConfig: {prism = {}},
|
||||
},
|
||||
} = useDocusaurusContext();
|
||||
const {prism} = useThemeConfig();
|
||||
|
||||
const [showCopied, setShowCopied] = useState(false);
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
|
|
@ -24,7 +24,7 @@ import {
|
|||
} from '@theme/hooks/useDocs';
|
||||
|
||||
function DocItem(props: Props): JSX.Element {
|
||||
const {siteConfig = {}} = useDocusaurusContext();
|
||||
const {siteConfig} = useDocusaurusContext();
|
||||
const {url: siteUrl, title: siteTitle, titleDelimiter} = siteConfig;
|
||||
const {content: DocContent} = props;
|
||||
const {metadata} = DocContent;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import React, {useState, useCallback, useEffect, useRef} from 'react';
|
||||
import clsx from 'clsx';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useThemeConfig from '../../utils/useThemeConfig';
|
||||
import useUserPreferencesContext from '@theme/hooks/useUserPreferencesContext';
|
||||
import useLockBodyScroll from '@theme/hooks/useLockBodyScroll';
|
||||
import useWindowSize, {windowSizes} from '@theme/hooks/useWindowSize';
|
||||
|
@ -171,11 +172,9 @@ function DocSidebar({
|
|||
}: Props): JSX.Element | null {
|
||||
const [showResponsiveSidebar, setShowResponsiveSidebar] = useState(false);
|
||||
const {
|
||||
siteConfig: {
|
||||
themeConfig: {navbar: {title = '', hideOnScroll = false} = {}} = {},
|
||||
} = {},
|
||||
isClient,
|
||||
} = useDocusaurusContext();
|
||||
navbar: {title, hideOnScroll},
|
||||
} = useThemeConfig();
|
||||
const {isClient} = useDocusaurusContext();
|
||||
const {logoLink, logoLinkProps, logoImageUrl, logoAlt} = useLogo();
|
||||
const {isAnnouncementBarClosed} = useUserPreferencesContext();
|
||||
const {scrollY} = useScrollPosition();
|
||||
|
|
|
@ -9,7 +9,7 @@ import React from 'react';
|
|||
import clsx from 'clsx';
|
||||
|
||||
import Link from '@docusaurus/Link';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useThemeConfig from '../../utils/useThemeConfig';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import styles from './styles.module.css';
|
||||
|
||||
|
@ -40,10 +40,7 @@ const FooterLogo = ({url, alt}) => (
|
|||
);
|
||||
|
||||
function Footer(): JSX.Element | null {
|
||||
const context = useDocusaurusContext();
|
||||
const {siteConfig = {}} = context;
|
||||
const {themeConfig = {}} = siteConfig;
|
||||
const {footer} = themeConfig;
|
||||
const {footer} = useThemeConfig();
|
||||
|
||||
const {copyright, links = [], logo = {}} = footer || {};
|
||||
const logoUrl = useBaseUrl(logo.src);
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import type {HeadingType, Props} from '@theme/Heading';
|
||||
import useThemeConfig from '../../utils/useThemeConfig';
|
||||
|
||||
import './styles.css';
|
||||
import styles from './styles.module.css';
|
||||
|
@ -18,10 +18,8 @@ import styles from './styles.module.css';
|
|||
const Heading = (Tag: HeadingType): ((props: Props) => JSX.Element) =>
|
||||
function TargetComponent({id, ...props}) {
|
||||
const {
|
||||
siteConfig: {
|
||||
themeConfig: {navbar: {hideOnScroll = false} = {}} = {},
|
||||
} = {},
|
||||
} = useDocusaurusContext();
|
||||
navbar: {hideOnScroll},
|
||||
} = useThemeConfig();
|
||||
|
||||
if (!id) {
|
||||
return <Tag {...props} />;
|
||||
|
|
|
@ -13,6 +13,7 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|||
import SearchBar from '@theme/SearchBar';
|
||||
import Toggle from '@theme/Toggle';
|
||||
import useThemeContext from '@theme/hooks/useThemeContext';
|
||||
import useThemeConfig from '../../utils/useThemeConfig';
|
||||
import useHideableNavbar from '@theme/hooks/useHideableNavbar';
|
||||
import useLockBodyScroll from '@theme/hooks/useLockBodyScroll';
|
||||
import useWindowSize, {windowSizes} from '@theme/hooks/useWindowSize';
|
||||
|
@ -40,20 +41,13 @@ function splitNavItemsByPosition(items) {
|
|||
}
|
||||
|
||||
function Navbar(): JSX.Element {
|
||||
const {isClient} = useDocusaurusContext();
|
||||
|
||||
const {
|
||||
siteConfig: {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
title = '',
|
||||
items = [],
|
||||
hideOnScroll = false,
|
||||
style = undefined,
|
||||
} = {},
|
||||
colorMode: {disableSwitch: disableColorModeSwitch = false} = {},
|
||||
},
|
||||
},
|
||||
isClient,
|
||||
} = useDocusaurusContext();
|
||||
navbar: {title, items, hideOnScroll, style},
|
||||
colorMode: {disableSwitch: disableColorModeSwitch},
|
||||
} = useThemeConfig();
|
||||
|
||||
const [sidebarShown, setSidebarShown] = useState(false);
|
||||
const [isSearchBarExpanded, setIsSearchBarExpanded] = useState(false);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import React, {ComponentProps} from 'react';
|
||||
import Toggle from 'react-toggle';
|
||||
|
||||
import useThemeConfig from '../../utils/useThemeConfig';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
|
||||
import clsx from 'clsx';
|
||||
|
@ -26,20 +26,11 @@ const Light = ({icon, style}) => (
|
|||
|
||||
export default function (props: ComponentProps<typeof Toggle>): JSX.Element {
|
||||
const {
|
||||
siteConfig: {
|
||||
themeConfig: {
|
||||
colorMode: {
|
||||
switchConfig: {
|
||||
darkIcon,
|
||||
darkIconStyle,
|
||||
lightIcon,
|
||||
lightIconStyle,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
isClient
|
||||
} = useDocusaurusContext();
|
||||
colorMode: {
|
||||
switchConfig: {darkIcon, darkIconStyle, lightIcon, lightIconStyle},
|
||||
},
|
||||
} = useThemeConfig();
|
||||
const {isClient} = useDocusaurusContext();
|
||||
|
||||
return (
|
||||
<Toggle
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
*/
|
||||
|
||||
import {useState, useEffect, useCallback} from 'react';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useThemeConfig from '../../utils/useThemeConfig';
|
||||
import type {useAnnouncementBarReturns} from '@theme/hooks/useAnnoucementBar';
|
||||
|
||||
const STORAGE_DISMISS_KEY = 'docusaurus.announcement.dismiss';
|
||||
const STORAGE_ID_KEY = 'docusaurus.announcement.id';
|
||||
|
||||
const useAnnouncementBar = (): useAnnouncementBarReturns => {
|
||||
const {announcementBar} = useDocusaurusContext().siteConfig.themeConfig;
|
||||
const {announcementBar} = useThemeConfig();
|
||||
|
||||
const [isClosed, setClosed] = useState(true);
|
||||
|
||||
|
|
|
@ -5,16 +5,16 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useThemeContext from '@theme/hooks/useThemeContext';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import isInternalUrl from '@docusaurus/isInternalUrl';
|
||||
import type {LogoLinkProps, useLogoReturns} from '@theme/hooks/useLogo';
|
||||
import useThemeConfig from '../../utils/useThemeConfig';
|
||||
|
||||
const useLogo = (): useLogoReturns => {
|
||||
const {
|
||||
siteConfig: {themeConfig: {navbar: {logo = {}} = {}} = {}} = {},
|
||||
} = useDocusaurusContext();
|
||||
navbar: {logo},
|
||||
} = useThemeConfig();
|
||||
const {isDarkTheme} = useThemeContext();
|
||||
const logoLink = useBaseUrl(logo.href || '/');
|
||||
let logoLinkProps: LogoLinkProps = {};
|
||||
|
|
|
@ -6,15 +6,11 @@
|
|||
*/
|
||||
|
||||
import defaultTheme from 'prism-react-renderer/themes/palenight';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useThemeContext from '@theme/hooks/useThemeContext';
|
||||
import useThemeConfig from '../../utils/useThemeConfig';
|
||||
|
||||
const usePrismTheme = (): typeof defaultTheme => {
|
||||
const {
|
||||
siteConfig: {
|
||||
themeConfig: {prism = {}},
|
||||
},
|
||||
} = useDocusaurusContext();
|
||||
const {prism} = useThemeConfig();
|
||||
const {isDarkTheme} = useThemeContext();
|
||||
const lightModeTheme = prism.theme || defaultTheme;
|
||||
const darkModeTheme = prism.darkTheme || lightModeTheme;
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
import {useState, useCallback, useEffect} from 'react';
|
||||
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
||||
import type {useThemeReturns} from '@theme/hooks/useTheme';
|
||||
import useThemeConfig from '../../utils/useThemeConfig';
|
||||
|
||||
const themes = {
|
||||
light: 'light',
|
||||
|
@ -38,10 +38,8 @@ const storeTheme = (newTheme) => {
|
|||
|
||||
const useTheme = (): useThemeReturns => {
|
||||
const {
|
||||
siteConfig: {
|
||||
themeConfig: {colorMode: {disableSwitch = false} = {}} = {},
|
||||
} = {},
|
||||
} = useDocusaurusContext();
|
||||
colorMode: {disableSwitch = false},
|
||||
} = useThemeConfig();
|
||||
const [theme, setTheme] = useState(getInitialTheme);
|
||||
|
||||
const setLightTheme = useCallback(() => {
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
|
||||
type ThemeConfig = {
|
||||
// TODO we should complete this theme config type over time
|
||||
// and share it across all themes
|
||||
// and use it in the Joi validation schema?
|
||||
|
||||
// TODO temporary types
|
||||
navbar: any;
|
||||
colorMode: any;
|
||||
announcementBar: any;
|
||||
prism: any;
|
||||
footer: any;
|
||||
};
|
||||
|
||||
export default function useThemeConfig(): ThemeConfig {
|
||||
return useDocusaurusContext().siteConfig.themeConfig as ThemeConfig;
|
||||
}
|
|
@ -23,6 +23,13 @@ const DEFAULT_COLOR_MODE_CONFIG = {
|
|||
const DEFAULT_CONFIG = {
|
||||
colorMode: DEFAULT_COLOR_MODE_CONFIG,
|
||||
metadatas: [],
|
||||
prism: {
|
||||
additionalLanguages: [],
|
||||
},
|
||||
navbar: {
|
||||
hideOnScroll: false,
|
||||
items: [],
|
||||
},
|
||||
};
|
||||
exports.DEFAULT_CONFIG = DEFAULT_CONFIG;
|
||||
|
||||
|
@ -195,13 +202,15 @@ const ThemeConfigSchema = Joi.object({
|
|||
}).optional(),
|
||||
navbar: Joi.object({
|
||||
style: Joi.string().equal('dark', 'primary'),
|
||||
hideOnScroll: Joi.bool().default(false),
|
||||
hideOnScroll: Joi.bool().default(DEFAULT_CONFIG.navbar.hideOnScroll),
|
||||
// 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),
|
||||
items: Joi.array()
|
||||
.items(NavbarItemSchema)
|
||||
.default(DEFAULT_CONFIG.navbar.items),
|
||||
title: Joi.string().allow('', null),
|
||||
logo: Joi.object({
|
||||
alt: Joi.string().allow(''),
|
||||
|
@ -210,7 +219,7 @@ const ThemeConfigSchema = Joi.object({
|
|||
href: Joi.string(),
|
||||
target: Joi.string(),
|
||||
}),
|
||||
}),
|
||||
}).default(DEFAULT_CONFIG.navbar),
|
||||
footer: Joi.object({
|
||||
style: Joi.string().equal('dark', 'light').default('light'),
|
||||
logo: Joi.object({
|
||||
|
@ -219,13 +228,15 @@ const ThemeConfigSchema = Joi.object({
|
|||
href: Joi.string(),
|
||||
}),
|
||||
copyright: Joi.string(),
|
||||
links: Joi.array().items(
|
||||
Joi.object({
|
||||
title: Joi.string().required(),
|
||||
items: Joi.array().items(FooterLinkItemSchema).default([]),
|
||||
}),
|
||||
),
|
||||
}),
|
||||
links: Joi.array()
|
||||
.items(
|
||||
Joi.object({
|
||||
title: Joi.string().required(),
|
||||
items: Joi.array().items(FooterLinkItemSchema).default([]),
|
||||
}),
|
||||
)
|
||||
.default([]),
|
||||
}).optional(),
|
||||
prism: Joi.object({
|
||||
theme: Joi.object({
|
||||
plain: Joi.alternatives().try(Joi.array(), Joi.object()).required(),
|
||||
|
@ -236,8 +247,12 @@ const ThemeConfigSchema = Joi.object({
|
|||
styles: Joi.alternatives().try(Joi.array(), Joi.object()).required(),
|
||||
}),
|
||||
defaultLanguage: Joi.string(),
|
||||
additionalLanguages: Joi.array().items(Joi.string()),
|
||||
}).unknown(),
|
||||
additionalLanguages: Joi.array()
|
||||
.items(Joi.string())
|
||||
.default(DEFAULT_CONFIG.prism.additionalLanguages),
|
||||
})
|
||||
.default(DEFAULT_CONFIG.prism)
|
||||
.unknown(),
|
||||
});
|
||||
exports.ThemeConfigSchema = ThemeConfigSchema;
|
||||
|
||||
|
|
|
@ -24,18 +24,13 @@ import useLogo from '@theme/hooks/useLogo';
|
|||
|
||||
const Example = () => {
|
||||
// highlight-next-line
|
||||
const {logoLink, logoLinkProps, logoImageUrl, logoAlt} = useLogo();
|
||||
const {logoLink, logoLinkProps, logoImageUrl, logoAlt} = useLogo();
|
||||
|
||||
return (
|
||||
<Link to={logoLink} {...logoLinkProps}>
|
||||
{logoImageUrl != null && (
|
||||
<img
|
||||
src={logoImageUrl}
|
||||
alt={logoAlt}
|
||||
/>
|
||||
)}
|
||||
{logoImageUrl != null && <img src={logoImageUrl} alt={logoAlt} />}
|
||||
</Link>
|
||||
)
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -107,7 +102,6 @@ React Router should automatically apply active link styling to links, but you ca
|
|||
|
||||
Outbound (external) links automatically get `target="_blank" rel="noopener noreferrer"` attributes.
|
||||
|
||||
|
||||
## Footer
|
||||
|
||||
You can add logo and a copyright to the footer via `themeConfig.footer`. Logo can be placed in [static folder](static-assets.md). Logo URL works in the same way of the navbar logo.
|
||||
|
@ -125,58 +119,58 @@ You can add logo and a copyright to the footer via `themeConfig.footer`. Logo ca
|
|||
```
|
||||
|
||||
## Footer Links
|
||||
You can add links to the navbar via `themeConfig.footer.links`:
|
||||
|
||||
You can add links to the navbar via `themeConfig.footer.links`:
|
||||
|
||||
```js {5-15} title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
// ...
|
||||
footer: {
|
||||
links: [
|
||||
{
|
||||
// Label of the section of these links
|
||||
title: 'Docs',
|
||||
items: [
|
||||
{
|
||||
// Label of the link
|
||||
label: 'Style Guide',
|
||||
// Client-side routing, used for navigating within the website.
|
||||
// The baseUrl will be automatically prepended to this value.
|
||||
to: 'docs/',
|
||||
},
|
||||
{
|
||||
label: 'Second Doc',
|
||||
to: 'docs/doc2/',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Community',
|
||||
items: [
|
||||
{
|
||||
label: 'Stack Overflow',
|
||||
// A full-page navigation, used for navigating outside of the website.
|
||||
href: 'https://stackoverflow.com/questions/tagged/docusaurus',
|
||||
},
|
||||
{
|
||||
label: 'Discord',
|
||||
href: 'https://discordapp.com/invite/docusaurus',
|
||||
},
|
||||
{
|
||||
label: 'Twitter',
|
||||
href: 'https://twitter.com/docusaurus',
|
||||
},
|
||||
{
|
||||
//Renders the html pass-through instead of a simple link
|
||||
html: `
|
||||
links: [
|
||||
{
|
||||
// Label of the section of these links
|
||||
title: 'Docs',
|
||||
items: [
|
||||
{
|
||||
// Label of the link
|
||||
label: 'Style Guide',
|
||||
// Client-side routing, used for navigating within the website.
|
||||
// The baseUrl will be automatically prepended to this value.
|
||||
to: 'docs/',
|
||||
},
|
||||
{
|
||||
label: 'Second Doc',
|
||||
to: 'docs/doc2/',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Community',
|
||||
items: [
|
||||
{
|
||||
label: 'Stack Overflow',
|
||||
// A full-page navigation, used for navigating outside of the website.
|
||||
href: 'https://stackoverflow.com/questions/tagged/docusaurus',
|
||||
},
|
||||
{
|
||||
label: 'Discord',
|
||||
href: 'https://discordapp.com/invite/docusaurus',
|
||||
},
|
||||
{
|
||||
label: 'Twitter',
|
||||
href: 'https://twitter.com/docusaurus',
|
||||
},
|
||||
{
|
||||
//Renders the html pass-through instead of a simple link
|
||||
html: `
|
||||
<a href="https://www.netlify.com" target="_blank" rel="noreferrer noopener" aria-label="Deploys by Netlify">
|
||||
<img src="https://www.netlify.com/img/global/badges/netlify-color-accent.svg" alt="Deploys by Netlify" />
|
||||
</a>
|
||||
`,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue