mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-22 21:47:01 +02:00
feat(v2): bootstrap theme, preset, template, CI previews (#2981)
* fix(v2): doc sidebar * chore(v2): prettier * fix(v2): docs navbar path * fix(v2): fix error about activepath * chore(v2): prettier * feat(v2): change active color * feat(v2): Add bootstrap doc * docs(v2): Update preset * doc(v2): finish bootstrap documentation * chore(v2): run lint * doc(v2): update hook * fix theme bootstrap layout (far from perfect) * Try to fix bootstrap theme and deploy it! * fix netlify error Co-authored-by: slorber <lorber.sebastien@gmail.com>
This commit is contained in:
parent
5fdf96c552
commit
8c05aa8e94
17 changed files with 561 additions and 67 deletions
|
@ -13,6 +13,7 @@
|
|||
"start:v2": "yarn workspace docusaurus-2-website start",
|
||||
"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",
|
||||
"build": "yarn build:packages && yarn build:v2",
|
||||
"build:packages": "lerna run build --no-private",
|
||||
"build:v1": "yarn workspace docusaurus-1-website build",
|
||||
|
|
|
@ -62,17 +62,18 @@ function Home() {
|
|||
<Layout
|
||||
title={`Hello from ${siteConfig.title}`}
|
||||
description="Description will go into a meta tag in <head />">
|
||||
<div className={styles.hero}>
|
||||
<header>
|
||||
<h1 className="hero__title">{siteConfig.title}</h1>
|
||||
<p className="hero__subtitle">{siteConfig.tagline}</p>
|
||||
<h1>{siteConfig.title}</h1>
|
||||
<p>{siteConfig.tagline}</p>
|
||||
<div className={styles.buttons}>
|
||||
<Link to={useBaseUrl('docs/')}>Get Started</Link>
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
{features && features.length > 0 && (
|
||||
<section className={styles.features}>
|
||||
<div className="row">
|
||||
<section className={styles.section}>
|
||||
<div className={styles.features}>
|
||||
{features.map((props, idx) => (
|
||||
<Feature key={idx} {...props} />
|
||||
))}
|
||||
|
@ -80,6 +81,7 @@ function Home() {
|
|||
</section>
|
||||
)}
|
||||
</main>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,18 @@
|
|||
justify-content: center;
|
||||
}
|
||||
|
||||
.hero {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
place-content: center;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin: 10rem;
|
||||
}
|
||||
|
||||
.features {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
@ -14,34 +14,45 @@ import Layout from '@theme/Layout';
|
|||
import {MDXProvider} from '@mdx-js/react';
|
||||
import {matchPath} from '@docusaurus/router';
|
||||
|
||||
function DocPage(props) {
|
||||
const {route: baseRoute, docsMetadata, location} = props;
|
||||
// case-sensitive route such as it is defined in the sidebar
|
||||
const currentRoute =
|
||||
baseRoute.routes.find((route) => {
|
||||
return matchPath(location.pathname, route);
|
||||
}) || {};
|
||||
const {permalinkToSidebar, docsSidebars} = docsMetadata;
|
||||
const sidebar = permalinkToSidebar[currentRoute.path];
|
||||
|
||||
if (Object.keys(currentRoute).length === 0) {
|
||||
return <NotFound {...props} />;
|
||||
}
|
||||
|
||||
function DocPageContent({currentDocRoute, versionMetadata, children}) {
|
||||
const {permalinkToSidebar, docsSidebars} = versionMetadata;
|
||||
const sidebarName = permalinkToSidebar[currentDocRoute.path];
|
||||
const sidebar = docsSidebars[sidebarName];
|
||||
return (
|
||||
<Layout title="Doc page" description="My Doc page">
|
||||
<DocSidebar
|
||||
docsSidebars={docsSidebars}
|
||||
path={currentRoute.path}
|
||||
sidebar={sidebar}
|
||||
/>
|
||||
<section className="offset-1 mr-4 mt-4 col-xl-6 offset-xl-4 p-0 justify-content-center align-self-center overflow-hidden">
|
||||
<MDXProvider components={MDXComponents}>
|
||||
{renderRoutes(baseRoute.routes)}
|
||||
</MDXProvider>
|
||||
</section>
|
||||
<div className="d-flex vh-100 overflow-hidden">
|
||||
{sidebar && (
|
||||
<div className="vh-100" role="complementary">
|
||||
<DocSidebar path={currentDocRoute.path} sidebar={sidebar} />
|
||||
</div>
|
||||
)}
|
||||
<main className="vh-100 w-100 d-flex flex-column align-items-center overflow-auto p-5">
|
||||
<MDXProvider components={MDXComponents}>{children}</MDXProvider>
|
||||
</main>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
function DocPage(props) {
|
||||
const {
|
||||
route: {routes: docRoutes},
|
||||
versionMetadata,
|
||||
location,
|
||||
} = props;
|
||||
const currentDocRoute = docRoutes.find((docRoute) =>
|
||||
matchPath(location.pathname, docRoute),
|
||||
);
|
||||
if (!currentDocRoute) {
|
||||
return <NotFound {...props} />;
|
||||
}
|
||||
return (
|
||||
<DocPageContent
|
||||
currentDocRoute={currentDocRoute}
|
||||
versionMetadata={versionMetadata}>
|
||||
{renderRoutes(docRoutes)}
|
||||
</DocPageContent>
|
||||
);
|
||||
}
|
||||
|
||||
export default DocPage;
|
||||
|
|
|
@ -61,9 +61,7 @@ const DocSidebarItem = ({item, onItemClick, ...props}) => {
|
|||
}
|
||||
};
|
||||
|
||||
const DocSidebar = (props) => {
|
||||
const {docsSidebars, sidebar: currentSidebar} = props;
|
||||
|
||||
const DocSidebar = ({sidebar, path}) => {
|
||||
const [sidebarShown, setSidebarShown] = useState(false);
|
||||
const handleSidebarToggle = useCallback(() => {
|
||||
setSidebarShown(!sidebarShown);
|
||||
|
@ -71,18 +69,6 @@ const DocSidebar = (props) => {
|
|||
|
||||
useLockBodyScroll(sidebarShown);
|
||||
|
||||
if (!currentSidebar) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const sidebarData = docsSidebars[currentSidebar];
|
||||
|
||||
if (!sidebarData) {
|
||||
throw new Error(
|
||||
`Cannot find the sidebar "${currentSidebar}" in the sidebar config!`,
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classNames('bg-info', styles.sidebar)}>
|
||||
<div
|
||||
|
@ -115,7 +101,7 @@ const DocSidebar = (props) => {
|
|||
</div>
|
||||
<div className={classNames(styles.sideMenu)}>
|
||||
<Nav vertical className="list-unstyled p-3 mr-auto">
|
||||
{sidebarData.map((item) => (
|
||||
{sidebar.map((item) => (
|
||||
<DocSidebarItem
|
||||
key={item.label}
|
||||
item={item}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* 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 Layout from '@theme/Layout';
|
||||
import {MDXProvider} from '@mdx-js/react';
|
||||
import MDXComponents from '@theme/MDXComponents';
|
||||
|
||||
function MDXPage(props) {
|
||||
const {content: MDXPageContent} = props;
|
||||
const {frontMatter, metadata} = MDXPageContent;
|
||||
const {title, description} = frontMatter;
|
||||
const {permalink} = metadata;
|
||||
|
||||
return (
|
||||
<Layout title={title} description={description} permalink={permalink}>
|
||||
<main>
|
||||
<div className="container margin-vert--lg padding-vert--lg">
|
||||
<MDXProvider components={MDXComponents}>
|
||||
<MDXPageContent />
|
||||
</MDXProvider>
|
||||
</div>
|
||||
</main>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export default MDXPage;
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* 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';
|
||||
|
||||
function TabItem(props) {
|
||||
return <div>{props.children}</div>;
|
||||
}
|
||||
|
||||
export default TabItem;
|
154
packages/docusaurus-theme-bootstrap/src/theme/Tabs/index.js
Normal file
154
packages/docusaurus-theme-bootstrap/src/theme/Tabs/index.js
Normal file
|
@ -0,0 +1,154 @@
|
|||
/**
|
||||
* 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, Children, useEffect} from 'react';
|
||||
|
||||
import clsx from 'clsx';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
|
||||
const keys = {
|
||||
left: 37,
|
||||
right: 39,
|
||||
tab: 9,
|
||||
};
|
||||
|
||||
// TODO quick fix to make bootstrap theme work
|
||||
function useUserPreferencesContext() {
|
||||
const [state, setState] = useState({});
|
||||
|
||||
return {
|
||||
tabGroupChoices: state,
|
||||
setTabGroupChoices: (id, value) => {
|
||||
setState((s) => ({...s, [id]: value}));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function Tabs(props) {
|
||||
const {block, children, defaultValue, values, groupId} = props;
|
||||
|
||||
const {tabGroupChoices, setTabGroupChoices} = useUserPreferencesContext();
|
||||
|
||||
const [selectedValue, setSelectedValue] = useState(defaultValue);
|
||||
const [keyboardPress, setKeyboardPress] = useState(false);
|
||||
|
||||
if (groupId != null) {
|
||||
const relevantTabGroupChoice = tabGroupChoices[groupId];
|
||||
if (
|
||||
relevantTabGroupChoice != null &&
|
||||
relevantTabGroupChoice !== selectedValue &&
|
||||
values.some((value) => value.value === relevantTabGroupChoice)
|
||||
) {
|
||||
setSelectedValue(relevantTabGroupChoice);
|
||||
}
|
||||
}
|
||||
|
||||
const changeSelectedValue = (newValue) => {
|
||||
setSelectedValue(newValue);
|
||||
if (groupId != null) {
|
||||
setTabGroupChoices(groupId, newValue);
|
||||
}
|
||||
};
|
||||
|
||||
const tabRefs = [];
|
||||
|
||||
const focusNextTab = (tabs, target) => {
|
||||
const next = tabs.indexOf(target) + 1;
|
||||
|
||||
if (!tabs[next]) {
|
||||
tabs[0].focus();
|
||||
} else {
|
||||
tabs[next].focus();
|
||||
}
|
||||
};
|
||||
|
||||
const focusPreviousTab = (tabs, target) => {
|
||||
const prev = tabs.indexOf(target) - 1;
|
||||
|
||||
if (!tabs[prev]) {
|
||||
tabs[tabs.length - 1].focus();
|
||||
} else {
|
||||
tabs[prev].focus();
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeydown = (tabs, target, event) => {
|
||||
switch (event.keyCode) {
|
||||
case keys.right:
|
||||
focusNextTab(tabs, target);
|
||||
break;
|
||||
case keys.left:
|
||||
focusPreviousTab(tabs, target);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyboardEvent = (event) => {
|
||||
if (event.metaKey || event.altKey || event.ctrlKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
setKeyboardPress(true);
|
||||
};
|
||||
|
||||
const handleMouseEvent = () => {
|
||||
setKeyboardPress(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('keydown', handleKeyboardEvent);
|
||||
window.addEventListener('mousedown', handleMouseEvent);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ul
|
||||
role="tablist"
|
||||
aria-orientation="horizontal"
|
||||
className={clsx('tabs', {
|
||||
'tabs--block': block,
|
||||
})}>
|
||||
{values.map(({value, label}) => (
|
||||
<li
|
||||
role="tab"
|
||||
tabIndex={0}
|
||||
aria-selected={selectedValue === value}
|
||||
className={clsx('tabs__item', styles.tabItem, {
|
||||
'tabs__item--active': selectedValue === value,
|
||||
})}
|
||||
style={keyboardPress ? {} : {outline: 'none'}}
|
||||
key={value}
|
||||
ref={(tabControl) => tabRefs.push(tabControl)}
|
||||
onKeyDown={(event) => {
|
||||
handleKeydown(tabRefs, event.target, event);
|
||||
handleKeyboardEvent(event);
|
||||
}}
|
||||
onFocus={() => changeSelectedValue(value)}
|
||||
onClick={() => {
|
||||
changeSelectedValue(value);
|
||||
setKeyboardPress(false);
|
||||
}}
|
||||
onPointerDown={() => setKeyboardPress(false)}>
|
||||
{label}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div role="tabpanel" className="margin-vert--md">
|
||||
{
|
||||
Children.toArray(children).filter(
|
||||
(child) => child.props.value === selectedValue,
|
||||
)[0]
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Tabs;
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
.tabItem {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* 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';
|
||||
|
||||
const usePrismTheme = () => {
|
||||
return defaultTheme;
|
||||
};
|
||||
|
||||
export default usePrismTheme;
|
|
@ -32,6 +32,12 @@ If you do not specify `name` or `template`, it will prompt you for them. We reco
|
|||
npx @docusaurus/init@next init my-website facebook
|
||||
```
|
||||
|
||||
**[Experimental]:** If you want setting up a new website using [bootstrap](https://getbootstrap.com/), use the `bootstrap` template, like the following::
|
||||
|
||||
```bash
|
||||
npx @docusaurus/init@next init my-website bootstrap
|
||||
```
|
||||
|
||||
## Project structure
|
||||
|
||||
Assuming you chose the classic template and named your site `my-website`, you will see the following files generated under a new directory `my-website/`:
|
||||
|
|
|
@ -130,6 +130,40 @@ module.exports = {
|
|||
};
|
||||
```
|
||||
|
||||
### `@docusaurus/preset-bootstrap`
|
||||
|
||||
The classic preset that is usually shipped by default to new docusaurus website. It is a set of plugins and themes.
|
||||
|
||||
| Themes | Plugins |
|
||||
| ---------------------------------- | ------------------------------------- |
|
||||
| `@docusaurus/theme-bootstrap` | `@docusaurus/plugin-content-docs` |
|
||||
| | `@docusaurus/plugin-content-blog` |
|
||||
| | `@docusaurus/plugin-content-pages` |
|
||||
|
||||
|
||||
To specify plugin options individually, you can provide the necessary fields to certain plugins, i.e. `docs` for `@docusaurus/theme-bootstrap`, pass them in the preset field, like this:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-bootstrap',
|
||||
{
|
||||
// Will be passed to @docusaurus/plugin-content-docs
|
||||
docs: {},
|
||||
// Will be passed to @docusaurus/plugin-content-blog
|
||||
blog: {},
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
```
|
||||
:::caution
|
||||
|
||||
This preset is work in progress
|
||||
|
||||
:::
|
||||
|
||||
<!--
|
||||
|
||||
Advanced guide on using and configuring presets
|
||||
|
|
182
website/docs/theme-bootstrap.md
Normal file
182
website/docs/theme-bootstrap.md
Normal file
|
@ -0,0 +1,182 @@
|
|||
---
|
||||
id: theme-bootstrap
|
||||
title: '@docusaurus/theme-bootstrap'
|
||||
---
|
||||
|
||||
:::caution
|
||||
|
||||
This section is a work in progress.
|
||||
|
||||
:::
|
||||
|
||||
## Hooks
|
||||
|
||||
### `useLogo`
|
||||
|
||||
React hook to access the logo asset.
|
||||
|
||||
Usage example:
|
||||
|
||||
```jsx
|
||||
import React from 'react';
|
||||
// highlight-next-line
|
||||
import useLogo from '@theme/hooks/useLogo';
|
||||
|
||||
const Example = () => {
|
||||
// highlight-next-line
|
||||
const {logoLink, logoLinkProps, logoImageUrl, logoAlt} = useLogo();
|
||||
|
||||
return (
|
||||
<Link to={logoLink} {...logoLinkProps}>
|
||||
{logoImageUrl != null && (
|
||||
<img
|
||||
src={logoImageUrl}
|
||||
alt={logoAlt}
|
||||
/>
|
||||
)}
|
||||
</Link>
|
||||
)
|
||||
};
|
||||
```
|
||||
|
||||
## Navbar
|
||||
|
||||
### Navbar title & logo
|
||||
|
||||
You can add a logo and title to the navbar via `themeConfig.navbar`. Logo can be placed in [static folder](static-assets.md). Logo URL is set to base URL of your site by default. Although you can specify your own URL for the logo, if it is an external link, it will open in a new tab. In addition, you can override a value for the target attribute of logo link, it can come in handy if you are hosting docs website in a subdirectory of your main website, and in which case you probably do not need a link in the logo to the main website will open in a new tab.
|
||||
|
||||
```js {5-11} title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
// ...
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
title: 'Site Title',
|
||||
logo: {
|
||||
alt: 'Site Logo',
|
||||
src: 'img/logo.svg',
|
||||
href: 'https://v2.docusaurus.io/', // Default to `siteConfig.baseUrl`.
|
||||
target: '_self', // By default, this value is calculated based on the `href` attribute (the external link will open in a new tab, all others in the current one).
|
||||
},
|
||||
},
|
||||
// ...
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### Navbar links
|
||||
|
||||
You can add links to the navbar via `themeConfig.navbar.links`:
|
||||
|
||||
```js {5-15} title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
// ...
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
links: [
|
||||
{
|
||||
// Client-side routing, used for navigating within the website.
|
||||
// The baseUrl will be automatically prepended to this value.
|
||||
to: 'docs/introduction',
|
||||
// A full-page navigation, used for navigating outside of the website.
|
||||
// You should only use either `to` or `href`.
|
||||
href: 'https://www.facebook.com',
|
||||
// Prepends the baseUrl to href values.
|
||||
prependBaseUrlToHref: true,
|
||||
// The string to be shown.
|
||||
label: 'Introduction',
|
||||
// Left or right side of the navbar.
|
||||
position: 'left', // or 'right'
|
||||
// To apply the active class styling on all
|
||||
// routes starting with this path.
|
||||
// This usually isn't necessary
|
||||
activeBasePath: 'docs',
|
||||
// Alternative to activeBasePath if required.
|
||||
activeBaseRegex: 'docs/(next|v8)',
|
||||
// Custom CSS class (for styling any item).
|
||||
className: '',
|
||||
},
|
||||
// ... other links
|
||||
],
|
||||
},
|
||||
// ...
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
React Router should automatically apply active link styling to links, but you can use `activeBasePath` in edge cases. For cases in which a link should be active on several different paths (such as when you have multiple doc folders under the same sidebar), you can use `activeBaseRegex`. `activeBaseRegex` is a more flexible alternative to `activeBasePath` and takes precedence over it -- Docusaurus parses it into a regular expression that is tested against the current URL.
|
||||
|
||||
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.
|
||||
|
||||
```js {5-15} title="docusaurus.config.js"
|
||||
// ...
|
||||
footer: {
|
||||
logo: {
|
||||
alt: 'Facebook Open Source Logo',
|
||||
src: 'img/oss_logo.png',
|
||||
href: 'https://opensource.facebook.com',
|
||||
},
|
||||
copyright: `Copyright © ${new Date().getFullYear()} My Project, Inc. Built with Docusaurus.`,
|
||||
}
|
||||
```
|
||||
|
||||
## 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: `
|
||||
<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>
|
||||
`,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
```
|
|
@ -117,6 +117,26 @@ If you have installed `@docusaurus/preset-classic`, you don't need to install it
|
|||
|
||||
:::
|
||||
|
||||
### `@docusaurus/theme-bootstrap`
|
||||
|
||||
The bootstrap theme for Docusaurus. You can refer to [bootstrap theme configuration](theme-bootstrap.md) for more details on the configuration.
|
||||
|
||||
```bash npm2yarn
|
||||
npm install --save @docusaurus/theme-bootstrap
|
||||
```
|
||||
|
||||
:::tip
|
||||
|
||||
If you have installed `@docusaurus/preset-bootstrap`, you don't need to install it as a dependency.
|
||||
|
||||
:::
|
||||
|
||||
:::caution
|
||||
|
||||
This theme is a work in progress.
|
||||
|
||||
:::
|
||||
|
||||
### `@docusaurus/theme-search-algolia`
|
||||
|
||||
This theme provides a `@theme/SearchBar` component that integrates with Algolia DocSearch easily. Combined with `@docusaurus/theme-classic`, it provides a very easy search integration. You can read more on [search](search.md) documentation.
|
||||
|
|
|
@ -15,6 +15,12 @@ const allDocHomesPaths = [
|
|||
];
|
||||
|
||||
const baseUrl = process.env.BASE_URL || '/';
|
||||
const isBootstrapPreset = process.env.DOCUSAURUS_PRESET === 'bootstrap';
|
||||
const isVersioningDisabled = !!process.env.DISABLE_VERSIONING;
|
||||
|
||||
if (isBootstrapPreset) {
|
||||
console.log('Will use bootstrap preset!');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
title: 'Docusaurus',
|
||||
|
@ -23,7 +29,7 @@ module.exports = {
|
|||
projectName: 'docusaurus',
|
||||
baseUrl,
|
||||
url: 'https://v2.docusaurus.io',
|
||||
onBrokenLinks: 'throw',
|
||||
onBrokenLinks: isVersioningDisabled ? 'warn' : 'throw',
|
||||
favicon: 'img/docusaurus.ico',
|
||||
customFields: {
|
||||
description:
|
||||
|
@ -154,7 +160,9 @@ module.exports = {
|
|||
],
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
isBootstrapPreset
|
||||
? '@docusaurus/preset-bootstrap'
|
||||
: '@docusaurus/preset-classic',
|
||||
{
|
||||
debug: true, // force debug plugin usage
|
||||
docs: {
|
||||
|
@ -166,7 +174,7 @@ module.exports = {
|
|||
showLastUpdateAuthor: true,
|
||||
showLastUpdateTime: true,
|
||||
remarkPlugins: [require('./src/plugins/remark-npm2yarn')],
|
||||
disableVersioning: !!process.env.DISABLE_VERSIONING,
|
||||
disableVersioning: isVersioningDisabled,
|
||||
},
|
||||
blog: {
|
||||
// routeBasePath: '/',
|
||||
|
|
|
@ -17,10 +17,14 @@
|
|||
# workaroud: a _redirect file is created in website/netlifyDeploy
|
||||
# can't we have context-based redirects with Netlify? :'(
|
||||
[[context.deploy-preview.redirects]]
|
||||
from = "/build/*"
|
||||
to = "/build/404.html"
|
||||
from = "/classic/*"
|
||||
to = "/classic/404.html"
|
||||
status = 200
|
||||
[[context.deploy-preview.redirects]]
|
||||
from = "/bootstrap/*"
|
||||
to = "/bootstrap/404.html"
|
||||
status = 200
|
||||
[[context.deploy-preview.redirects]]
|
||||
from = "/*"
|
||||
to = "/build/"
|
||||
to = "/classic/"
|
||||
|
||||
|
|
|
@ -10,10 +10,13 @@
|
|||
"deploy": "docusaurus deploy",
|
||||
"start:baseUrl": "BASE_URL='/build/' yarn start",
|
||||
"build:baseUrl": "BASE_URL='/build/' yarn build",
|
||||
"start:bootstrap": "DOCUSAURUS_PRESET=bootstrap yarn start",
|
||||
"build:bootstrap": "DOCUSAURUS_PRESET=bootstrap yarn build",
|
||||
"netlify:build:production": "yarn build",
|
||||
"netlify:build:deployPreview": "yarn build:baseUrl && yarn netlify:build:deployPreview:moveBuild && yarn netlify:build:deployPreview:redirects",
|
||||
"netlify:build:deployPreview:moveBuild": "yarn rimraf netlifyDeploy && mkdir netlifyDeploy && mv build netlifyDeploy",
|
||||
"netlify:build:deployPreview:redirects": "echo 'Writing Netlify baseUrl deployPreview _redirects file' && echo '/build/* /build/404.html 200' >> netlifyDeploy/_redirects && echo '/* /build/' >> netlifyDeploy/_redirects",
|
||||
"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:test": "yarn netlify:build:deployPreview && yarn netlify dev --debug"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue