This commit is contained in:
2024-03-22 03:47:51 +05:30
parent 8bcf3d211e
commit 89819f6fe2
28440 changed files with 3211033 additions and 2 deletions

21
node_modules/@docusaurus/theme-classic/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) Facebook, Inc. and its affiliates.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

31
node_modules/@docusaurus/theme-classic/README.md generated vendored Normal file
View File

@@ -0,0 +1,31 @@
# Docusaurus Theme Classic
The classic theme for Docusaurus.
## Installation
Add `docusaurus/theme-classic` to your package:
```bash
npm i @docusaurus/theme-classic
# or
yarn add @docusaurus/theme-classic
```
Modify your `docusaurus.config.js`:
```diff
module.exports = {
...
+ themes: ['@docusaurus/theme-classic'],
...
}
```
## Swizzling components
```bash
$ npm swizzle @docusaurus/theme-classic [component name]
```
All components used by this theme can be found [here](https://github.com/facebook/docusaurus/tree/main/packages/docusaurus-theme-classic/src/theme)

View File

@@ -0,0 +1,8 @@
/**
* 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 type { SwizzleConfig } from '@docusaurus/types';
export default function getSwizzleConfig(): SwizzleConfig;

View File

@@ -0,0 +1,375 @@
"use strict";
/**
* 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint sort-keys: "error" */
function getSwizzleConfig() {
return {
components: {
'Admonition/Icon': {
actions: {
eject: 'safe',
wrap: 'forbidden', // Can't wrap a folder
},
description: 'The folder containing all admonition icons',
},
'Admonition/Icon/Danger': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The admonition danger icon',
},
'Admonition/Icon/Info': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The admonition info icon',
},
'Admonition/Icon/Note': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The admonition note icon',
},
'Admonition/Icon/Tip': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The admonition tip icon',
},
'Admonition/Icon/Warning': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The admonition warning icon',
},
'Admonition/Layout': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The standard admonition layout applied to all default admonition types',
},
'Admonition/Type': {
actions: {
eject: 'safe',
wrap: 'forbidden',
},
description: 'The folder containing all the admonition type components.',
},
'Admonition/Type/Caution': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The component responsible for rendering a :::caution admonition type',
},
'Admonition/Type/Danger': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The component responsible for rendering a :::danger admonition type',
},
'Admonition/Type/Info': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The component responsible for rendering a :::info admonition type',
},
'Admonition/Type/Note': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The component responsible for rendering a :::note admonition type',
},
'Admonition/Type/Tip': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The component responsible for rendering a :::tip admonition type',
},
'Admonition/Type/Warning': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The component responsible for rendering a :::warning admonition type',
},
'Admonition/Types': {
actions: {
eject: 'safe',
// TODO the swizzle CLI should provide a way to wrap such objects
wrap: 'forbidden',
},
description: 'The object mapping admonition type to a React component.\nUse it to add custom admonition type components, or replace existing ones.\nCan be ejected or wrapped (only manually, see our documentation).',
},
CodeBlock: {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The component used to render multi-line code blocks, generally used in Markdown files.',
},
'CodeBlock/Content': {
actions: {
eject: 'unsafe',
wrap: 'forbidden',
},
description: 'The folder containing components responsible for rendering different types of CodeBlock content.',
},
ColorModeToggle: {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The color mode toggle to switch between light and dark mode.',
},
'DocBreadcrumbs/Items': {
actions: {
eject: 'unsafe',
wrap: 'forbidden', // Can't wrap a folder
},
description: 'The components responsible for rendering the breadcrumb items',
},
DocCardList: {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The component responsible for rendering a list of sidebar items cards.\nNotable used on the category generated-index pages.',
},
'DocItem/TOC': {
actions: {
// Forbidden because it's a parent folder, makes the CLI crash atm
// TODO the CLI should rather support --eject
// Subfolders can be swizzled
eject: 'forbidden',
wrap: 'forbidden',
},
description: 'The DocItem TOC is not directly swizzle-able, but you can swizzle its sub-components.',
},
DocSidebar: {
actions: {
eject: 'unsafe',
wrap: 'safe',
},
description: 'The sidebar component on docs pages',
},
Footer: {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: "The footer component of your site's layout",
},
'Footer/Copyright': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The footer copyright',
},
'Footer/Layout': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The footer main layout component',
},
'Footer/LinkItem': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The footer link item component',
},
'Footer/Links': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The footer component rendering the footer links',
},
'Footer/Links/MultiColumn': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The footer component rendering the footer links with a multi-column layout',
},
'Footer/Links/Simple': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The footer component rendering the footer links with a simple layout (single row)',
},
'Footer/Logo': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The footer logo',
},
Icon: {
actions: {
// Forbidden because it's a parent folder, makes the CLI crash atm
// TODO the CLI should rather support --eject
// Subfolders can be swizzled
eject: 'forbidden',
wrap: 'forbidden',
},
description: 'The Icon folder is not directly swizzle-able, but you can swizzle its sub-components.',
},
'Icon/Arrow': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The arrow icon component',
},
'Icon/DarkMode': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The dark mode icon component.',
},
'Icon/Edit': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The edit icon component',
},
'Icon/LightMode': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The light mode icon component.',
},
'Icon/Menu': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The menu icon component',
},
MDXComponents: {
actions: {
eject: 'safe',
wrap: 'forbidden', /// TODO allow wrapping objects???
},
description: 'The MDX components to use for rendering MDX files. Meant to be ejected.',
},
'MDXComponents/A': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The component used to render <a> tags and Markdown links in MDX',
},
'MDXComponents/Code': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The component used to render <code> tags and Markdown code blocks in MDX',
},
'MDXComponents/Details': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The component used to render <details> tags in MDX',
},
'MDXComponents/Heading': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The component used to render heading tags (<h1>, <h2>...) and Markdown headings in MDX',
},
'MDXComponents/Img': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The component used to render <img> tags and Markdown images in MDX',
},
'MDXComponents/Pre': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The component used to render <pre> tags in MDX',
},
'MDXComponents/Ul': {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The component used to render <ul> tags and Markdown unordered lists in MDX',
},
MDXContent: {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'A component wrapping all MDX content and providing the MDXComponents to the MDX context',
},
'NavbarItem/ComponentTypes': {
actions: {
eject: 'safe',
wrap: 'forbidden',
},
description: 'The Navbar item components mapping. Can be ejected to add custom navbar item types.\nSee https://github.com/facebook/docusaurus/issues/7227.',
},
NotFound: {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The global 404 page of your site, meant to be ejected and customized',
},
SearchBar: {
actions: {
eject: 'safe',
wrap: 'safe',
},
// TODO how to describe this one properly?
// By default it's an empty placeholder for the user to fill
description: 'The search bar component of your site, appearing in the navbar.',
},
SkipToContent: {
actions: {
eject: 'safe',
wrap: 'safe',
},
description: 'The component responsible for implementing the accessibility "skip to content" link (https://www.w3.org/TR/WCAG20-TECHS/G1.html)',
},
'prism-include-languages': {
actions: {
eject: 'safe',
wrap: 'forbidden', // Not a component!
},
description: 'The Prism languages to include for code block syntax highlighting. Meant to be ejected.',
},
},
};
}
exports.default = getSwizzleConfig;

12
node_modules/@docusaurus/theme-classic/lib/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,12 @@
/**
* 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 type { LoadContext, Plugin } from '@docusaurus/types';
import type { PluginOptions } from '@docusaurus/theme-classic';
export declare const AnnouncementBarDismissStorageKey = "docusaurus.announcement.dismiss";
export default function themeClassic(context: LoadContext, options: PluginOptions): Plugin<undefined>;
export { default as getSwizzleConfig } from './getSwizzleConfig';
export { validateThemeConfig, validateOptions } from './options';

189
node_modules/@docusaurus/theme-classic/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,189 @@
"use strict";
/**
* 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateOptions = exports.validateThemeConfig = exports.getSwizzleConfig = exports.AnnouncementBarDismissStorageKey = void 0;
const tslib_1 = require("tslib");
const path_1 = tslib_1.__importDefault(require("path"));
const module_1 = require("module");
const rtlcss_1 = tslib_1.__importDefault(require("rtlcss"));
const theme_translations_1 = require("@docusaurus/theme-translations");
const translations_1 = require("./translations");
const requireFromDocusaurusCore = (0, module_1.createRequire)(require.resolve('@docusaurus/core/package.json'));
const ContextReplacementPlugin = requireFromDocusaurusCore('webpack/lib/ContextReplacementPlugin');
// Need to be inlined to prevent dark mode FOUC
// Make sure the key is the same as the one in `/theme/hooks/useTheme.js`
const ThemeStorageKey = 'theme';
// Support for ?docusaurus-theme=dark
const ThemeQueryStringKey = 'docusaurus-theme';
// Support for ?docusaurus-data-mode=embed&docusaurus-data-myAttr=42
const DataQueryStringPrefixKey = 'docusaurus-data-';
const noFlashColorMode = ({ defaultMode, respectPrefersColorScheme, }) =>
/* language=js */
`(function() {
var defaultMode = '${defaultMode}';
var respectPrefersColorScheme = ${respectPrefersColorScheme};
function setDataThemeAttribute(theme) {
document.documentElement.setAttribute('data-theme', theme);
}
function getQueryStringTheme() {
try {
return new URLSearchParams(window.location.search).get('${ThemeQueryStringKey}')
} catch(e) {}
}
function getStoredTheme() {
try {
return localStorage.getItem('${ThemeStorageKey}');
} catch (err) {}
}
var initialTheme = getQueryStringTheme() || getStoredTheme();
if (initialTheme !== null) {
setDataThemeAttribute(initialTheme);
} else {
if (
respectPrefersColorScheme &&
window.matchMedia('(prefers-color-scheme: dark)').matches
) {
setDataThemeAttribute('dark');
} else if (
respectPrefersColorScheme &&
window.matchMedia('(prefers-color-scheme: light)').matches
) {
setDataThemeAttribute('light');
} else {
setDataThemeAttribute(defaultMode === 'dark' ? 'dark' : 'light');
}
}
})();`;
/* language=js */
const DataAttributeQueryStringInlineJavaScript = `
(function() {
try {
const entries = new URLSearchParams(window.location.search).entries();
for (var [searchKey, value] of entries) {
if (searchKey.startsWith('${DataQueryStringPrefixKey}')) {
var key = searchKey.replace('${DataQueryStringPrefixKey}',"data-")
document.documentElement.setAttribute(key, value);
}
}
} catch(e) {}
})();
`;
// Duplicated constant. Unfortunately we can't import it from theme-common, as
// we need to support older nodejs versions without ESM support
// TODO: import from theme-common once we only support Node.js with ESM support
// + move all those announcementBar stuff there too
exports.AnnouncementBarDismissStorageKey = 'docusaurus.announcement.dismiss';
const AnnouncementBarDismissDataAttribute = 'data-announcement-bar-initially-dismissed';
// We always render the announcement bar html on the server, to prevent layout
// shifts on React hydration. The theme can use CSS + the data attribute to hide
// the announcement bar asap (before React hydration)
/* language=js */
const AnnouncementBarInlineJavaScript = `
(function() {
function isDismissed() {
try {
return localStorage.getItem('${exports.AnnouncementBarDismissStorageKey}') === 'true';
} catch (err) {}
return false;
}
document.documentElement.setAttribute('${AnnouncementBarDismissDataAttribute}', isDismissed());
})();`;
function getInfimaCSSFile(direction) {
return `infima/dist/css/default/default${direction === 'rtl' ? '-rtl' : ''}.css`;
}
function themeClassic(context, options) {
const { i18n: { currentLocale, localeConfigs }, } = context;
const themeConfig = context.siteConfig.themeConfig;
const { announcementBar, colorMode, prism: { additionalLanguages }, } = themeConfig;
const { customCss } = options;
const { direction } = localeConfigs[currentLocale];
return {
name: 'docusaurus-theme-classic',
getThemePath() {
return '../lib/theme';
},
getTypeScriptThemePath() {
return '../src/theme';
},
getTranslationFiles: () => (0, translations_1.getTranslationFiles)({ themeConfig }),
translateThemeConfig: (params) => (0, translations_1.translateThemeConfig)({
themeConfig: params.themeConfig,
translationFiles: params.translationFiles,
}),
getDefaultCodeTranslationMessages() {
return (0, theme_translations_1.readDefaultCodeTranslationMessages)({
locale: currentLocale,
name: 'theme-common',
});
},
getClientModules() {
const modules = [
require.resolve(getInfimaCSSFile(direction)),
'./prism-include-languages',
'./nprogress',
];
modules.push(...customCss.map((p) => path_1.default.resolve(context.siteDir, p)));
return modules;
},
configureWebpack() {
const prismLanguages = additionalLanguages
.map((lang) => `prism-${lang}`)
.join('|');
return {
plugins: [
// This allows better optimization by only bundling those components
// that the user actually needs, because the modules are dynamically
// required and can't be known during compile time.
new ContextReplacementPlugin(/prismjs[\\/]components$/, new RegExp(`^./(${prismLanguages})$`)),
],
};
},
configurePostCss(postCssOptions) {
if (direction === 'rtl') {
const resolvedInfimaFile = require.resolve(getInfimaCSSFile(direction));
const plugin = {
postcssPlugin: 'RtlCssPlugin',
prepare: (result) => {
const file = result.root.source?.input.file;
// Skip Infima as we are using the its RTL version.
if (file === resolvedInfimaFile) {
return {};
}
return (0, rtlcss_1.default)(result.root);
},
};
postCssOptions.plugins.push(plugin);
}
return postCssOptions;
},
injectHtmlTags() {
return {
preBodyTags: [
{
tagName: 'script',
innerHTML: `
${noFlashColorMode(colorMode)}
${DataAttributeQueryStringInlineJavaScript}
${announcementBar ? AnnouncementBarInlineJavaScript : ''}
`,
},
],
};
},
};
}
exports.default = themeClassic;
var getSwizzleConfig_1 = require("./getSwizzleConfig");
Object.defineProperty(exports, "getSwizzleConfig", { enumerable: true, get: function () { return tslib_1.__importDefault(getSwizzleConfig_1).default; } });
var options_1 = require("./options");
Object.defineProperty(exports, "validateThemeConfig", { enumerable: true, get: function () { return options_1.validateThemeConfig; } });
Object.defineProperty(exports, "validateOptions", { enumerable: true, get: function () { return options_1.validateOptions; } });

View File

@@ -0,0 +1,41 @@
/**
* 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.
*/
/**
* Styles for NProgress
* Copied over to remove unused styles for the spinner.
* https://github.com/rstacruz/nprogress/blob/master/nprogress.css
*/
:root {
--docusaurus-progress-bar-color: var(--ifm-color-primary);
}
#nprogress {
pointer-events: none;
}
#nprogress .bar {
background: var(--docusaurus-progress-bar-color);
position: fixed;
z-index: 1031;
top: 0;
left: 0;
width: 100%;
height: 2px;
}
#nprogress .peg {
position: absolute;
right: 0;
width: 100px;
height: 100%;
box-shadow: 0 0 10px var(--docusaurus-progress-bar-color),
0 0 5px var(--docusaurus-progress-bar-color);
opacity: 1;
transform: rotate(3deg) translate(0, -4px);
}

View File

@@ -0,0 +1,10 @@
/**
* 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 type { ClientModule } from '@docusaurus/types';
import './nprogress.css';
declare const clientModule: ClientModule;
export default clientModule;

View File

@@ -0,0 +1,25 @@
/**
* 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 nprogress from 'nprogress';
import './nprogress.css';
nprogress.configure({ showSpinner: false });
const delay = 200;
const clientModule = {
onRouteUpdate({ location, previousLocation }) {
if (previousLocation && location.pathname !== previousLocation.pathname) {
const progressBarTimeout = window.setTimeout(() => {
nprogress.start();
}, delay);
return () => window.clearTimeout(progressBarTimeout);
}
return undefined;
},
onRouteDidUpdate() {
nprogress.done();
},
};
export default clientModule;

View File

@@ -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 { Joi } from '@docusaurus/utils-validation';
import type { Options, PluginOptions } from '@docusaurus/theme-classic';
import type { ThemeConfig } from '@docusaurus/theme-common';
import type { ThemeConfigValidationContext, OptionValidationContext } from '@docusaurus/types';
export declare const DEFAULT_CONFIG: ThemeConfig;
export declare const ThemeConfigSchema: Joi.ObjectSchema<ThemeConfig>;
export declare function validateThemeConfig({ validate, themeConfig, }: ThemeConfigValidationContext<ThemeConfig>): ThemeConfig;
export declare function validateOptions({ validate, options, }: OptionValidationContext<Options, PluginOptions>): PluginOptions;

413
node_modules/@docusaurus/theme-classic/lib/options.js generated vendored Normal file
View File

@@ -0,0 +1,413 @@
"use strict";
/**
* 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateOptions = exports.validateThemeConfig = exports.ThemeConfigSchema = exports.DEFAULT_CONFIG = void 0;
const prism_react_renderer_1 = require("prism-react-renderer");
const utils_validation_1 = require("@docusaurus/utils-validation");
const defaultPrismTheme = prism_react_renderer_1.themes.palenight;
const DEFAULT_DOCS_CONFIG = {
versionPersistence: 'localStorage',
sidebar: {
hideable: false,
autoCollapseCategories: false,
},
};
const DocsSchema = utils_validation_1.Joi.object({
versionPersistence: utils_validation_1.Joi.string()
.equal('localStorage', 'none')
.default(DEFAULT_DOCS_CONFIG.versionPersistence),
sidebar: utils_validation_1.Joi.object({
hideable: utils_validation_1.Joi.bool().default(DEFAULT_DOCS_CONFIG.sidebar.hideable),
autoCollapseCategories: utils_validation_1.Joi.bool().default(DEFAULT_DOCS_CONFIG.sidebar.autoCollapseCategories),
}).default(DEFAULT_DOCS_CONFIG.sidebar),
}).default(DEFAULT_DOCS_CONFIG);
const DEFAULT_COLOR_MODE_CONFIG = {
defaultMode: 'light',
disableSwitch: false,
respectPrefersColorScheme: false,
};
exports.DEFAULT_CONFIG = {
colorMode: DEFAULT_COLOR_MODE_CONFIG,
docs: DEFAULT_DOCS_CONFIG,
metadata: [],
prism: {
additionalLanguages: [],
theme: defaultPrismTheme,
magicComments: [
{
className: 'theme-code-block-highlighted-line',
line: 'highlight-next-line',
block: { start: 'highlight-start', end: 'highlight-end' },
},
],
},
navbar: {
hideOnScroll: false,
items: [],
},
tableOfContents: {
minHeadingLevel: 2,
maxHeadingLevel: 3,
},
};
const NavbarItemPosition = utils_validation_1.Joi.string().equal('left', 'right').default('left');
const NavbarItemBaseSchema = utils_validation_1.Joi.object({
label: utils_validation_1.Joi.string(),
html: utils_validation_1.Joi.string(),
className: utils_validation_1.Joi.string(),
})
.nand('html', 'label')
// We allow any unknown attributes on the links (users may need additional
// attributes like target, aria-role, data-customAttribute...)
.unknown();
const DefaultNavbarItemSchema = NavbarItemBaseSchema.append({
to: utils_validation_1.Joi.string(),
href: utils_validation_1.URISchema,
activeBasePath: utils_validation_1.Joi.string(),
activeBaseRegex: utils_validation_1.Joi.string(),
prependBaseUrlToHref: utils_validation_1.Joi.bool(),
// This is only triggered in case of a nested dropdown
items: utils_validation_1.Joi.forbidden().messages({
'any.unknown': 'Nested dropdowns are not allowed',
}),
})
.xor('href', 'to')
.messages({
'object.xor': 'One and only one between "to" and "href" should be provided',
});
const DocsVersionNavbarItemSchema = NavbarItemBaseSchema.append({
type: utils_validation_1.Joi.string().equal('docsVersion').required(),
to: utils_validation_1.Joi.string(),
docsPluginId: utils_validation_1.Joi.string(),
});
const DocItemSchema = NavbarItemBaseSchema.append({
type: utils_validation_1.Joi.string().equal('doc').required(),
docId: utils_validation_1.Joi.string().required(),
docsPluginId: utils_validation_1.Joi.string(),
});
const DocSidebarItemSchema = NavbarItemBaseSchema.append({
type: utils_validation_1.Joi.string().equal('docSidebar').required(),
sidebarId: utils_validation_1.Joi.string().required(),
docsPluginId: utils_validation_1.Joi.string(),
});
const HtmlNavbarItemSchema = utils_validation_1.Joi.object({
className: utils_validation_1.Joi.string(),
type: utils_validation_1.Joi.string().equal('html').required(),
value: utils_validation_1.Joi.string().required(),
});
// A temporary workaround to allow users to add custom navbar items
// See https://github.com/facebook/docusaurus/issues/7227
const CustomNavbarItemRegexp = /custom-.*/;
const CustomNavbarItemSchema = utils_validation_1.Joi.object({
type: utils_validation_1.Joi.string().regex(CustomNavbarItemRegexp).required(),
}).unknown();
const itemWithType = (type) => {
// Because equal(undefined) is not supported :/
const typeSchema =
// eslint-disable-next-line no-nested-ternary
type instanceof RegExp
? utils_validation_1.Joi.string().required().regex(type)
: type
? utils_validation_1.Joi.string().required().equal(type)
: utils_validation_1.Joi.string().forbidden();
return utils_validation_1.Joi.object({
type: typeSchema,
})
.unknown()
.required();
};
const DropdownSubitemSchema = utils_validation_1.Joi.object({
position: utils_validation_1.Joi.forbidden(),
}).when('.', {
switch: [
{
is: itemWithType('docsVersion'),
then: DocsVersionNavbarItemSchema,
},
{
is: itemWithType('doc'),
then: DocItemSchema,
},
{
is: itemWithType('docSidebar'),
then: DocSidebarItemSchema,
},
{
is: itemWithType(undefined),
then: DefaultNavbarItemSchema,
},
{
is: itemWithType('html'),
then: HtmlNavbarItemSchema,
},
{
is: itemWithType(CustomNavbarItemRegexp),
then: CustomNavbarItemSchema,
},
{
is: utils_validation_1.Joi.alternatives().try(itemWithType('dropdown'), itemWithType('docsVersionDropdown'), itemWithType('localeDropdown'), itemWithType('search')),
then: utils_validation_1.Joi.forbidden().messages({
'any.unknown': 'Nested dropdowns are not allowed',
}),
},
],
otherwise: utils_validation_1.Joi.forbidden().messages({
'any.unknown': 'Bad navbar item type {.type}',
}),
});
const DropdownNavbarItemSchema = NavbarItemBaseSchema.append({
items: utils_validation_1.Joi.array().items(DropdownSubitemSchema).required(),
});
const DocsVersionDropdownNavbarItemSchema = NavbarItemBaseSchema.append({
type: utils_validation_1.Joi.string().equal('docsVersionDropdown').required(),
docsPluginId: utils_validation_1.Joi.string(),
dropdownActiveClassDisabled: utils_validation_1.Joi.boolean(),
dropdownItemsBefore: utils_validation_1.Joi.array().items(DropdownSubitemSchema).default([]),
dropdownItemsAfter: utils_validation_1.Joi.array().items(DropdownSubitemSchema).default([]),
});
const LocaleDropdownNavbarItemSchema = NavbarItemBaseSchema.append({
type: utils_validation_1.Joi.string().equal('localeDropdown').required(),
dropdownItemsBefore: utils_validation_1.Joi.array().items(DropdownSubitemSchema).default([]),
dropdownItemsAfter: utils_validation_1.Joi.array().items(DropdownSubitemSchema).default([]),
queryString: utils_validation_1.Joi.string(),
});
const SearchItemSchema = utils_validation_1.Joi.object({
type: utils_validation_1.Joi.string().equal('search').required(),
className: utils_validation_1.Joi.string(),
});
const NavbarItemSchema = utils_validation_1.Joi.object({
position: NavbarItemPosition,
}).when('.', {
switch: [
{
is: itemWithType('docsVersion'),
then: DocsVersionNavbarItemSchema,
},
{
is: itemWithType('dropdown'),
then: DropdownNavbarItemSchema,
},
{
is: itemWithType('docsVersionDropdown'),
then: DocsVersionDropdownNavbarItemSchema,
},
{
is: itemWithType('doc'),
then: DocItemSchema,
},
{
is: itemWithType('docSidebar'),
then: DocSidebarItemSchema,
},
{
is: itemWithType('localeDropdown'),
then: LocaleDropdownNavbarItemSchema,
},
{
is: itemWithType('search'),
then: SearchItemSchema,
},
{
is: itemWithType('html'),
then: HtmlNavbarItemSchema,
},
{
is: itemWithType(CustomNavbarItemRegexp),
then: CustomNavbarItemSchema,
},
{
is: itemWithType(undefined),
then: utils_validation_1.Joi.object().when('.', {
// Dropdown item can be specified without type field
is: utils_validation_1.Joi.object({
items: utils_validation_1.Joi.array().required(),
}).unknown(),
then: DropdownNavbarItemSchema,
otherwise: DefaultNavbarItemSchema,
}),
},
],
otherwise: utils_validation_1.Joi.forbidden().messages({
'any.unknown': 'Bad navbar item type {.type}',
}),
});
const ColorModeSchema = utils_validation_1.Joi.object({
defaultMode: utils_validation_1.Joi.string()
.equal('dark', 'light')
.default(DEFAULT_COLOR_MODE_CONFIG.defaultMode),
disableSwitch: utils_validation_1.Joi.bool().default(DEFAULT_COLOR_MODE_CONFIG.disableSwitch),
respectPrefersColorScheme: utils_validation_1.Joi.bool().default(DEFAULT_COLOR_MODE_CONFIG.respectPrefersColorScheme),
switchConfig: utils_validation_1.Joi.any().forbidden().messages({
'any.unknown': 'colorMode.switchConfig is deprecated. If you want to customize the icons for light and dark mode, swizzle IconLightMode, IconDarkMode, or ColorModeToggle instead.',
}),
}).default(DEFAULT_COLOR_MODE_CONFIG);
const HtmlMetadataSchema = utils_validation_1.Joi.object({
id: utils_validation_1.Joi.string(),
name: utils_validation_1.Joi.string(),
property: utils_validation_1.Joi.string(),
content: utils_validation_1.Joi.string(),
itemprop: utils_validation_1.Joi.string(),
}).unknown();
const FooterLinkItemSchema = utils_validation_1.Joi.object({
to: utils_validation_1.Joi.string(),
href: utils_validation_1.URISchema,
html: utils_validation_1.Joi.string(),
label: utils_validation_1.Joi.string(),
})
.xor('to', 'href', 'html')
.with('to', 'label')
.with('href', 'label')
.nand('html', 'label')
// We allow any unknown attributes on the links (users may need additional
// attributes like target, aria-role, data-customAttribute...)
.unknown();
const LogoSchema = utils_validation_1.Joi.object({
alt: utils_validation_1.Joi.string().allow(''),
src: utils_validation_1.Joi.string().required(),
srcDark: utils_validation_1.Joi.string(),
width: utils_validation_1.Joi.alternatives().try(utils_validation_1.Joi.string(), utils_validation_1.Joi.number()),
height: utils_validation_1.Joi.alternatives().try(utils_validation_1.Joi.string(), utils_validation_1.Joi.number()),
href: utils_validation_1.Joi.string(),
target: utils_validation_1.Joi.string(),
style: utils_validation_1.Joi.object(),
className: utils_validation_1.Joi.string(),
});
// Normalize prism language to lowercase
// See https://github.com/facebook/docusaurus/issues/9012
const PrismLanguage = utils_validation_1.Joi.string().custom((val) => val.toLowerCase());
exports.ThemeConfigSchema = utils_validation_1.Joi.object({
// TODO temporary (@alpha-58)
// @ts-expect-error: forbidden
disableDarkMode: utils_validation_1.Joi.any().forbidden().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: utils_validation_1.Joi.any().forbidden().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: utils_validation_1.Joi.string(),
docs: DocsSchema,
metadata: utils_validation_1.Joi.array()
.items(HtmlMetadataSchema)
.default(exports.DEFAULT_CONFIG.metadata),
// cSpell:ignore metadatas
metadatas: utils_validation_1.Joi.any().forbidden().messages({
'any.unknown':
// cSpell:ignore metadatas
'themeConfig.metadatas has been renamed as themeConfig.metadata. See https://github.com/facebook/docusaurus/pull/5871',
}),
announcementBar: utils_validation_1.Joi.object({
id: utils_validation_1.Joi.string().default('announcement-bar'),
content: utils_validation_1.Joi.string().required(),
backgroundColor: utils_validation_1.Joi.string(),
textColor: utils_validation_1.Joi.string(),
isCloseable: utils_validation_1.Joi.bool().default(true),
}).optional(),
navbar: utils_validation_1.Joi.object({
style: utils_validation_1.Joi.string().equal('dark', 'primary'),
hideOnScroll: utils_validation_1.Joi.bool().default(exports.DEFAULT_CONFIG.navbar.hideOnScroll),
// TODO temporary (@alpha-58)
links: utils_validation_1.Joi.any().forbidden().messages({
'any.unknown': 'themeConfig.navbar.links has been renamed as themeConfig.navbar.items',
}),
items: utils_validation_1.Joi.array()
.items(NavbarItemSchema)
.default(exports.DEFAULT_CONFIG.navbar.items),
title: utils_validation_1.Joi.string().allow('', null),
logo: LogoSchema,
}).default(exports.DEFAULT_CONFIG.navbar),
footer: utils_validation_1.Joi.object({
style: utils_validation_1.Joi.string().equal('dark', 'light').default('light'),
logo: LogoSchema,
copyright: utils_validation_1.Joi.string(),
links: utils_validation_1.Joi.alternatives(utils_validation_1.Joi.array().items(utils_validation_1.Joi.object({
title: utils_validation_1.Joi.string().allow(null).default(null),
items: utils_validation_1.Joi.array().items(FooterLinkItemSchema).default([]),
})), utils_validation_1.Joi.array().items(FooterLinkItemSchema))
.messages({
'alternatives.match': `The footer must be either simple or multi-column, and not a mix of the two. See: https://docusaurus.io/docs/api/themes/configuration#footer-links`,
})
.default([]),
}).optional(),
prism: utils_validation_1.Joi.object({
theme: utils_validation_1.Joi.object({
plain: utils_validation_1.Joi.alternatives().try(utils_validation_1.Joi.array(), utils_validation_1.Joi.object()).required(),
styles: utils_validation_1.Joi.alternatives().try(utils_validation_1.Joi.array(), utils_validation_1.Joi.object()).required(),
}).default(exports.DEFAULT_CONFIG.prism.theme),
darkTheme: utils_validation_1.Joi.object({
plain: utils_validation_1.Joi.alternatives().try(utils_validation_1.Joi.array(), utils_validation_1.Joi.object()).required(),
styles: utils_validation_1.Joi.alternatives().try(utils_validation_1.Joi.array(), utils_validation_1.Joi.object()).required(),
}),
defaultLanguage: PrismLanguage,
additionalLanguages: utils_validation_1.Joi.array()
.items(PrismLanguage)
.default(exports.DEFAULT_CONFIG.prism.additionalLanguages),
magicComments: utils_validation_1.Joi.array()
.items(utils_validation_1.Joi.object({
className: utils_validation_1.Joi.string().required(),
line: utils_validation_1.Joi.string(),
block: utils_validation_1.Joi.object({
start: utils_validation_1.Joi.string().required(),
end: utils_validation_1.Joi.string().required(),
}),
}).or('line', 'block'))
.default(exports.DEFAULT_CONFIG.prism.magicComments),
})
.default(exports.DEFAULT_CONFIG.prism)
.unknown(),
hideableSidebar: utils_validation_1.Joi.forbidden().messages({
'any.unknown': 'themeConfig.hideableSidebar has been moved to themeConfig.docs.sidebar.hideable.',
}),
autoCollapseSidebarCategories: utils_validation_1.Joi.forbidden().messages({
'any.unknown': 'themeConfig.autoCollapseSidebarCategories has been moved to themeConfig.docs.sidebar.autoCollapseCategories.',
}),
sidebarCollapsible: utils_validation_1.Joi.forbidden().messages({
'any.unknown': 'The themeConfig.sidebarCollapsible has been moved to docs plugin options. See: https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-docs',
}),
tableOfContents: utils_validation_1.Joi.object({
minHeadingLevel: utils_validation_1.Joi.number()
.default(exports.DEFAULT_CONFIG.tableOfContents.minHeadingLevel)
.when('maxHeadingLevel', {
is: utils_validation_1.Joi.exist(),
then: utils_validation_1.Joi.number()
.integer()
.min(2)
.max(6)
.max(utils_validation_1.Joi.ref('maxHeadingLevel')),
otherwise: utils_validation_1.Joi.number().integer().min(2).max(6),
}),
maxHeadingLevel: utils_validation_1.Joi.number()
.integer()
.min(2)
.max(6)
.default(exports.DEFAULT_CONFIG.tableOfContents.maxHeadingLevel),
}).default(exports.DEFAULT_CONFIG.tableOfContents),
});
function validateThemeConfig({ validate, themeConfig, }) {
return validate(exports.ThemeConfigSchema, themeConfig);
}
exports.validateThemeConfig = validateThemeConfig;
const DEFAULT_OPTIONS = {
customCss: [],
};
const PluginOptionSchema = utils_validation_1.Joi.object({
customCss: utils_validation_1.Joi.alternatives()
.try(utils_validation_1.Joi.array().items(utils_validation_1.Joi.string().required()), utils_validation_1.Joi.alternatives().conditional(utils_validation_1.Joi.string().required(), {
then: utils_validation_1.Joi.custom((val) => [val]),
otherwise: utils_validation_1.Joi.forbidden().messages({
'any.unknown': '"customCss" must be a string or an array of strings',
}),
}))
.default(DEFAULT_OPTIONS.customCss),
});
function validateOptions({ validate, options, }) {
const validatedOptions = validate(PluginOptionSchema, options);
return validatedOptions;
}
exports.validateOptions = validateOptions;

View File

@@ -0,0 +1,7 @@
/**
* 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.
*/
export {};

View File

@@ -0,0 +1,9 @@
/**
* 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 { Prism } from 'prism-react-renderer';
import prismIncludeLanguages from '@theme/prism-include-languages';
prismIncludeLanguages(Prism);

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/Admonition/Icon/Danger';
export default function AdmonitionIconDanger(props: Props): JSX.Element;

View File

@@ -0,0 +1,17 @@
/**
* 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';
export default function AdmonitionIconDanger(props) {
return (
<svg viewBox="0 0 12 16" {...props}>
<path
fillRule="evenodd"
d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"
/>
</svg>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/Admonition/Icon/Info';
export default function AdmonitionIconInfo(props: Props): JSX.Element;

View File

@@ -0,0 +1,17 @@
/**
* 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';
export default function AdmonitionIconInfo(props) {
return (
<svg viewBox="0 0 14 16" {...props}>
<path
fillRule="evenodd"
d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"
/>
</svg>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/Admonition/Icon/Note';
export default function AdmonitionIconNote(props: Props): JSX.Element;

View File

@@ -0,0 +1,17 @@
/**
* 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';
export default function AdmonitionIconNote(props) {
return (
<svg viewBox="0 0 14 16" {...props}>
<path
fillRule="evenodd"
d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"
/>
</svg>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/Admonition/Icon/Tip';
export default function AdmonitionIconTip(props: Props): JSX.Element;

View File

@@ -0,0 +1,17 @@
/**
* 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';
export default function AdmonitionIconTip(props) {
return (
<svg viewBox="0 0 12 16" {...props}>
<path
fillRule="evenodd"
d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"
/>
</svg>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/Admonition/Icon/Warning';
export default function AdmonitionIconCaution(props: Props): JSX.Element;

View File

@@ -0,0 +1,17 @@
/**
* 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';
export default function AdmonitionIconCaution(props) {
return (
<svg viewBox="0 0 16 16" {...props}>
<path
fillRule="evenodd"
d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"
/>
</svg>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/Admonition/Layout';
export default function AdmonitionLayout(props: Props): JSX.Element;

View File

@@ -0,0 +1,45 @@
/**
* 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 clsx from 'clsx';
import {ThemeClassNames} from '@docusaurus/theme-common';
import styles from './styles.module.css';
function AdmonitionContainer({type, className, children}) {
return (
<div
className={clsx(
ThemeClassNames.common.admonition,
ThemeClassNames.common.admonitionType(type),
styles.admonition,
className,
)}>
{children}
</div>
);
}
function AdmonitionHeading({icon, title}) {
return (
<div className={styles.admonitionHeading}>
<span className={styles.admonitionIcon}>{icon}</span>
{title}
</div>
);
}
function AdmonitionContent({children}) {
return children ? (
<div className={styles.admonitionContent}>{children}</div>
) : null;
}
export default function AdmonitionLayout(props) {
const {type, icon, title, children, className} = props;
return (
<AdmonitionContainer type={type} className={className}>
<AdmonitionHeading title={title} icon={icon} />
<AdmonitionContent>{children}</AdmonitionContent>
</AdmonitionContainer>
);
}

View File

@@ -0,0 +1,42 @@
/**
* 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.
*/
.admonition {
margin-bottom: 1em;
}
.admonitionHeading {
font: var(--ifm-heading-font-weight) var(--ifm-h5-font-size) /
var(--ifm-heading-line-height) var(--ifm-heading-font-family);
text-transform: uppercase;
}
/* Heading alone without content (does not handle fragment content) */
.admonitionHeading:not(:last-child) {
margin-bottom: 0.3rem;
}
.admonitionHeading code {
text-transform: none;
}
.admonitionIcon {
display: inline-block;
vertical-align: middle;
margin-right: 0.4em;
}
.admonitionIcon svg {
display: inline-block;
height: 1.6em;
width: 1.6em;
fill: var(--ifm-alert-foreground-color);
}
.admonitionContent > :last-child {
margin-bottom: 0;
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/Admonition/Type/Caution';
export default function AdmonitionTypeCaution(props: Props): JSX.Element;

View File

@@ -0,0 +1,34 @@
/**
* 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 clsx from 'clsx';
import Translate from '@docusaurus/Translate';
import AdmonitionLayout from '@theme/Admonition/Layout';
import IconWarning from '@theme/Admonition/Icon/Warning';
const infimaClassName = 'alert alert--warning';
const defaultProps = {
icon: <IconWarning />,
title: (
<Translate
id="theme.admonition.caution"
description="The default label used for the Caution admonition (:::caution)">
caution
</Translate>
),
};
// TODO remove before v4: Caution replaced by Warning
// see https://github.com/facebook/docusaurus/issues/7558
export default function AdmonitionTypeCaution(props) {
return (
<AdmonitionLayout
{...defaultProps}
{...props}
className={clsx(infimaClassName, props.className)}>
{props.children}
</AdmonitionLayout>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/Admonition/Type/Danger';
export default function AdmonitionTypeDanger(props: Props): JSX.Element;

View File

@@ -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 clsx from 'clsx';
import Translate from '@docusaurus/Translate';
import AdmonitionLayout from '@theme/Admonition/Layout';
import IconDanger from '@theme/Admonition/Icon/Danger';
const infimaClassName = 'alert alert--danger';
const defaultProps = {
icon: <IconDanger />,
title: (
<Translate
id="theme.admonition.danger"
description="The default label used for the Danger admonition (:::danger)">
danger
</Translate>
),
};
export default function AdmonitionTypeDanger(props) {
return (
<AdmonitionLayout
{...defaultProps}
{...props}
className={clsx(infimaClassName, props.className)}>
{props.children}
</AdmonitionLayout>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/Admonition/Type/Info';
export default function AdmonitionTypeInfo(props: Props): JSX.Element;

View File

@@ -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 clsx from 'clsx';
import Translate from '@docusaurus/Translate';
import AdmonitionLayout from '@theme/Admonition/Layout';
import IconInfo from '@theme/Admonition/Icon/Info';
const infimaClassName = 'alert alert--info';
const defaultProps = {
icon: <IconInfo />,
title: (
<Translate
id="theme.admonition.info"
description="The default label used for the Info admonition (:::info)">
info
</Translate>
),
};
export default function AdmonitionTypeInfo(props) {
return (
<AdmonitionLayout
{...defaultProps}
{...props}
className={clsx(infimaClassName, props.className)}>
{props.children}
</AdmonitionLayout>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/Admonition/Type/Note';
export default function AdmonitionTypeNote(props: Props): JSX.Element;

View File

@@ -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 clsx from 'clsx';
import Translate from '@docusaurus/Translate';
import AdmonitionLayout from '@theme/Admonition/Layout';
import IconNote from '@theme/Admonition/Icon/Note';
const infimaClassName = 'alert alert--secondary';
const defaultProps = {
icon: <IconNote />,
title: (
<Translate
id="theme.admonition.note"
description="The default label used for the Note admonition (:::note)">
note
</Translate>
),
};
export default function AdmonitionTypeNote(props) {
return (
<AdmonitionLayout
{...defaultProps}
{...props}
className={clsx(infimaClassName, props.className)}>
{props.children}
</AdmonitionLayout>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/Admonition/Type/Tip';
export default function AdmonitionTypeTip(props: Props): JSX.Element;

View File

@@ -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 clsx from 'clsx';
import Translate from '@docusaurus/Translate';
import AdmonitionLayout from '@theme/Admonition/Layout';
import IconTip from '@theme/Admonition/Icon/Tip';
const infimaClassName = 'alert alert--success';
const defaultProps = {
icon: <IconTip />,
title: (
<Translate
id="theme.admonition.tip"
description="The default label used for the Tip admonition (:::tip)">
tip
</Translate>
),
};
export default function AdmonitionTypeTip(props) {
return (
<AdmonitionLayout
{...defaultProps}
{...props}
className={clsx(infimaClassName, props.className)}>
{props.children}
</AdmonitionLayout>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/Admonition/Type/Warning';
export default function AdmonitionTypeWarning(props: Props): JSX.Element;

View File

@@ -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 clsx from 'clsx';
import Translate from '@docusaurus/Translate';
import AdmonitionLayout from '@theme/Admonition/Layout';
import IconWarning from '@theme/Admonition/Icon/Warning';
const infimaClassName = 'alert alert--warning';
const defaultProps = {
icon: <IconWarning />,
title: (
<Translate
id="theme.admonition.warning"
description="The default label used for the Warning admonition (:::warning)">
warning
</Translate>
),
};
export default function AdmonitionTypeWarning(props) {
return (
<AdmonitionLayout
{...defaultProps}
{...props}
className={clsx(infimaClassName, props.className)}>
{props.children}
</AdmonitionLayout>
);
}

View File

@@ -0,0 +1,12 @@
/**
* 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.
*/
/// <reference path="../../../src/theme-classic.d.ts" />
import React from 'react';
declare const _default: {
[x: string]: React.ComponentType<import("@theme/Admonition").Props>;
};
export default _default;

View File

@@ -0,0 +1,33 @@
/**
* 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 AdmonitionTypeNote from '@theme/Admonition/Type/Note';
import AdmonitionTypeTip from '@theme/Admonition/Type/Tip';
import AdmonitionTypeInfo from '@theme/Admonition/Type/Info';
import AdmonitionTypeWarning from '@theme/Admonition/Type/Warning';
import AdmonitionTypeDanger from '@theme/Admonition/Type/Danger';
import AdmonitionTypeCaution from '@theme/Admonition/Type/Caution';
const admonitionTypes = {
note: AdmonitionTypeNote,
tip: AdmonitionTypeTip,
info: AdmonitionTypeInfo,
warning: AdmonitionTypeWarning,
danger: AdmonitionTypeDanger,
};
// Undocumented legacy admonition type aliases
// Provide hardcoded/untranslated retrocompatible label
// See also https://github.com/facebook/docusaurus/issues/7767
const admonitionAliases = {
secondary: (props) => <AdmonitionTypeNote title="secondary" {...props} />,
important: (props) => <AdmonitionTypeInfo title="important" {...props} />,
success: (props) => <AdmonitionTypeTip title="success" {...props} />,
caution: AdmonitionTypeCaution,
};
export default {
...admonitionTypes,
...admonitionAliases,
};

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/Admonition';
export default function Admonition(unprocessedProps: Props): JSX.Element;

View File

@@ -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 React from 'react';
import {processAdmonitionProps} from '@docusaurus/theme-common';
import AdmonitionTypes from '@theme/Admonition/Types';
function getAdmonitionTypeComponent(type) {
const component = AdmonitionTypes[type];
if (component) {
return component;
}
console.warn(
`No admonition component found for admonition type "${type}". Using Info as fallback.`,
);
return AdmonitionTypes.info;
}
export default function Admonition(unprocessedProps) {
const props = processAdmonitionProps(unprocessedProps);
const AdmonitionTypeComponent = getAdmonitionTypeComponent(props.type);
return <AdmonitionTypeComponent {...props} />;
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/AnnouncementBar/CloseButton';
export default function AnnouncementBarCloseButton(props: Props): JSX.Element | null;

View File

@@ -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 React from 'react';
import clsx from 'clsx';
import {translate} from '@docusaurus/Translate';
import IconClose from '@theme/Icon/Close';
import styles from './styles.module.css';
export default function AnnouncementBarCloseButton(props) {
return (
<button
type="button"
aria-label={translate({
id: 'theme.AnnouncementBar.closeButtonAriaLabel',
message: 'Close',
description: 'The ARIA label for close button of announcement bar',
})}
{...props}
className={clsx('clean-btn close', styles.closeButton, props.className)}>
<IconClose width={14} height={14} strokeWidth={3.1} />
</button>
);
}

View File

@@ -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.
*/
.closeButton {
padding: 0;
line-height: 0;
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/AnnouncementBar/Content';
export default function AnnouncementBarContent(props: Props): JSX.Element | null;

View File

@@ -0,0 +1,23 @@
/**
* 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 clsx from 'clsx';
import {useThemeConfig} from '@docusaurus/theme-common';
import styles from './styles.module.css';
export default function AnnouncementBarContent(props) {
const {announcementBar} = useThemeConfig();
const {content} = announcementBar;
return (
<div
{...props}
className={clsx(styles.content, props.className)}
// Developer provided the HTML, so assume it's safe.
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{__html: content}}
/>
);
}

View File

@@ -0,0 +1,17 @@
/**
* 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.
*/
.content {
font-size: 85%;
text-align: center;
padding: 5px 0;
}
.content a {
color: inherit;
text-decoration: underline;
}

View File

@@ -0,0 +1,8 @@
/**
* 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.
*/
/// <reference types="react" />
export default function AnnouncementBar(): JSX.Element | null;

View File

@@ -0,0 +1,35 @@
/**
* 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 {useThemeConfig} from '@docusaurus/theme-common';
import {useAnnouncementBar} from '@docusaurus/theme-common/internal';
import AnnouncementBarCloseButton from '@theme/AnnouncementBar/CloseButton';
import AnnouncementBarContent from '@theme/AnnouncementBar/Content';
import styles from './styles.module.css';
export default function AnnouncementBar() {
const {announcementBar} = useThemeConfig();
const {isActive, close} = useAnnouncementBar();
if (!isActive) {
return null;
}
const {backgroundColor, textColor, isCloseable} = announcementBar;
return (
<div
className={styles.announcementBar}
style={{backgroundColor, color: textColor}}
role="banner">
{isCloseable && <div className={styles.announcementBarPlaceholder} />}
<AnnouncementBarContent className={styles.announcementBarContent} />
{isCloseable && (
<AnnouncementBarCloseButton
onClick={close}
className={styles.announcementBarClose}
/>
)}
</div>
);
}

View File

@@ -0,0 +1,62 @@
/**
* 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.
*/
:root {
--docusaurus-announcement-bar-height: auto;
}
.announcementBar {
display: flex;
align-items: center;
height: var(--docusaurus-announcement-bar-height);
background-color: var(--ifm-color-white);
color: var(--ifm-color-black);
/*
Unfortunately we can't make announcement bar render above the navbar
IE need to use border-bottom instead of shadow
See https://github.com/facebookincubator/infima/issues/275
box-shadow: var(--ifm-global-shadow-lw);
z-index: calc(var(--ifm-z-index-fixed) + 1);
*/
border-bottom: 1px solid var(--ifm-color-emphasis-100);
}
html[data-announcement-bar-initially-dismissed='true'] .announcementBar {
display: none;
}
.announcementBarPlaceholder {
flex: 0 0 10px;
}
.announcementBarClose {
flex: 0 0 30px;
align-self: stretch;
}
.announcementBarContent {
flex: 1 1 auto;
}
@media print {
.announcementBar {
display: none;
}
}
@media (min-width: 997px) {
:root {
--docusaurus-announcement-bar-height: 30px;
}
.announcementBarPlaceholder,
.announcementBarClose {
flex-basis: 50px;
}
}

View File

@@ -0,0 +1,8 @@
/**
* 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.
*/
/// <reference types="react" />
export default function BackToTopButton(): JSX.Element;

View File

@@ -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 clsx from 'clsx';
import {translate} from '@docusaurus/Translate';
import {ThemeClassNames} from '@docusaurus/theme-common';
import {useBackToTopButton} from '@docusaurus/theme-common/internal';
import styles from './styles.module.css';
export default function BackToTopButton() {
const {shown, scrollToTop} = useBackToTopButton({threshold: 300});
return (
<button
aria-label={translate({
id: 'theme.BackToTopButton.buttonAriaLabel',
message: 'Scroll back to top',
description: 'The ARIA label for the back to top button',
})}
className={clsx(
'clean-btn',
ThemeClassNames.common.backToTopButton,
styles.backToTopButton,
shown && styles.backToTopButtonShow,
)}
type="button"
onClick={scrollToTop}
/>
);
}

View File

@@ -0,0 +1,44 @@
/**
* 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.
*/
.backToTopButton {
position: fixed;
right: 1.3rem;
bottom: 1.3rem;
border-radius: 50%;
background-color: var(--ifm-color-emphasis-200);
width: 3rem;
height: 3rem;
z-index: calc(var(--ifm-z-index-fixed) - 1);
box-shadow: var(--ifm-global-shadow-lw);
transition: all var(--ifm-transition-fast)
var(--ifm-transition-timing-default);
opacity: 0;
transform: scale(0);
visibility: hidden;
}
.backToTopButton::after {
content: ' ';
display: inline-block;
mask: var(--ifm-menu-link-sublist-icon) 50% / 2rem 2rem no-repeat;
background-color: var(--ifm-color-emphasis-1000);
width: 100%;
height: 100%;
}
@media (hover: hover) {
.backToTopButton:hover {
background-color: var(--ifm-color-emphasis-300);
}
}
.backToTopButtonShow {
opacity: 1;
transform: scale(1);
visibility: visible;
}

View File

@@ -0,0 +1,10 @@
/**
* 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.
*/
/// <reference types="@docusaurus/plugin-content-blog" />
/// <reference types="react" />
import type { Props } from '@theme/BlogArchivePage';
export default function BlogArchive({ archive }: Props): JSX.Element;

View File

@@ -0,0 +1,85 @@
/**
* 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 Link from '@docusaurus/Link';
import {translate} from '@docusaurus/Translate';
import {PageMetadata} from '@docusaurus/theme-common';
import Layout from '@theme/Layout';
import Heading from '@theme/Heading';
function Year({year, posts}) {
return (
<>
<Heading as="h3" id={year}>
{year}
</Heading>
<ul>
{posts.map((post) => (
<li key={post.metadata.date}>
<Link to={post.metadata.permalink}>
{post.metadata.formattedDate} - {post.metadata.title}
</Link>
</li>
))}
</ul>
</>
);
}
function YearsSection({years}) {
return (
<section className="margin-vert--lg">
<div className="container">
<div className="row">
{years.map((_props, idx) => (
<div key={idx} className="col col--4 margin-vert--lg">
<Year {..._props} />
</div>
))}
</div>
</div>
</section>
);
}
function listPostsByYears(blogPosts) {
const postsByYear = blogPosts.reduce((posts, post) => {
const year = post.metadata.date.split('-')[0];
const yearPosts = posts.get(year) ?? [];
return posts.set(year, [post, ...yearPosts]);
}, new Map());
return Array.from(postsByYear, ([year, posts]) => ({
year,
posts,
}));
}
export default function BlogArchive({archive}) {
const title = translate({
id: 'theme.blog.archive.title',
message: 'Archive',
description: 'The page & hero title of the blog archive page',
});
const description = translate({
id: 'theme.blog.archive.description',
message: 'Archive',
description: 'The page & hero description of the blog archive page',
});
const years = listPostsByYears(archive.blogPosts);
return (
<>
<PageMetadata title={title} description={description} />
<Layout>
<header className="hero hero--primary">
<div className="container">
<Heading as="h1" className="hero__title">
{title}
</Heading>
<p className="hero__subtitle">{description}</p>
</div>
</header>
<main>{years.length > 0 && <YearsSection years={years} />}</main>
</Layout>
</>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/BlogLayout';
export default function BlogLayout(props: Props): JSX.Element;

View File

@@ -0,0 +1,33 @@
/**
* 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 clsx from 'clsx';
import Layout from '@theme/Layout';
import BlogSidebar from '@theme/BlogSidebar';
export default function BlogLayout(props) {
const {sidebar, toc, children, ...layoutProps} = props;
const hasSidebar = sidebar && sidebar.items.length > 0;
return (
<Layout {...layoutProps}>
<div className="container margin-vert--lg">
<div className="row">
<BlogSidebar sidebar={sidebar} />
<main
className={clsx('col', {
'col--7': hasSidebar,
'col--9 col--offset-1': !hasSidebar,
})}
itemScope
itemType="https://schema.org/Blog">
{children}
</main>
{toc && <div className="col col--2">{toc}</div>}
</div>
</div>
</Layout>
);
}

View File

@@ -0,0 +1,10 @@
/**
* 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.
*/
/// <reference types="@docusaurus/plugin-content-blog" />
/// <reference types="react" />
import type { Props } from '@theme/BlogListPage';
export default function BlogListPage(props: Props): JSX.Element;

View File

@@ -0,0 +1,54 @@
/**
* 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 clsx from 'clsx';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import {
PageMetadata,
HtmlClassNameProvider,
ThemeClassNames,
} from '@docusaurus/theme-common';
import BlogLayout from '@theme/BlogLayout';
import BlogListPaginator from '@theme/BlogListPaginator';
import SearchMetadata from '@theme/SearchMetadata';
import BlogPostItems from '@theme/BlogPostItems';
function BlogListPageMetadata(props) {
const {metadata} = props;
const {
siteConfig: {title: siteTitle},
} = useDocusaurusContext();
const {blogDescription, blogTitle, permalink} = metadata;
const isBlogOnlyMode = permalink === '/';
const title = isBlogOnlyMode ? siteTitle : blogTitle;
return (
<>
<PageMetadata title={title} description={blogDescription} />
<SearchMetadata tag="blog_posts_list" />
</>
);
}
function BlogListPageContent(props) {
const {metadata, items, sidebar} = props;
return (
<BlogLayout sidebar={sidebar}>
<BlogPostItems items={items} />
<BlogListPaginator metadata={metadata} />
</BlogLayout>
);
}
export default function BlogListPage(props) {
return (
<HtmlClassNameProvider
className={clsx(
ThemeClassNames.wrapper.blogPages,
ThemeClassNames.page.blogListPage,
)}>
<BlogListPageMetadata {...props} />
<BlogListPageContent {...props} />
</HtmlClassNameProvider>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/BlogListPaginator';
export default function BlogListPaginator(props: Props): JSX.Element;

View File

@@ -0,0 +1,48 @@
/**
* 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 Translate, {translate} from '@docusaurus/Translate';
import PaginatorNavLink from '@theme/PaginatorNavLink';
export default function BlogListPaginator(props) {
const {metadata} = props;
const {previousPage, nextPage} = metadata;
return (
<nav
className="pagination-nav"
aria-label={translate({
id: 'theme.blog.paginator.navAriaLabel',
message: 'Blog list page navigation',
description: 'The ARIA label for the blog pagination',
})}>
{previousPage && (
<PaginatorNavLink
permalink={previousPage}
title={
<Translate
id="theme.blog.paginator.newerEntries"
description="The label used to navigate to the newer blog posts page (previous page)">
Newer Entries
</Translate>
}
/>
)}
{nextPage && (
<PaginatorNavLink
permalink={nextPage}
title={
<Translate
id="theme.blog.paginator.olderEntries"
description="The label used to navigate to the older blog posts page (next page)">
Older Entries
</Translate>
}
isNext
/>
)}
</nav>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/BlogPostItem/Container';
export default function BlogPostItemContainer({ children, className, }: Props): JSX.Element;

View File

@@ -0,0 +1,35 @@
/**
* 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 {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
import {useBlogPost} from '@docusaurus/theme-common/internal';
export default function BlogPostItemContainer({children, className}) {
const {
frontMatter,
assets,
metadata: {description},
} = useBlogPost();
const {withBaseUrl} = useBaseUrlUtils();
const image = assets.image ?? frontMatter.image;
const keywords = frontMatter.keywords ?? [];
return (
<article
className={className}
itemProp="blogPost"
itemScope
itemType="https://schema.org/BlogPosting">
{description && <meta itemProp="description" content={description} />}
{image && (
<link itemProp="image" href={withBaseUrl(image, {absolute: true})} />
)}
{keywords.length > 0 && (
<meta itemProp="keywords" content={keywords.join(',')} />
)}
{children}
</article>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/BlogPostItem/Content';
export default function BlogPostItemContent({ children, className, }: Props): JSX.Element;

View File

@@ -0,0 +1,23 @@
/**
* 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 clsx from 'clsx';
import {blogPostContainerID} from '@docusaurus/utils-common';
import {useBlogPost} from '@docusaurus/theme-common/internal';
import MDXContent from '@theme/MDXContent';
export default function BlogPostItemContent({children, className}) {
const {isBlogPostPage} = useBlogPost();
return (
<div
// This ID is used for the feed generation to locate the main content
id={isBlogPostPage ? blogPostContainerID : undefined}
className={clsx('markdown', className)}
itemProp="articleBody">
<MDXContent>{children}</MDXContent>
</div>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/BlogPostItem/Footer/ReadMoreLink';
export default function BlogPostItemFooterReadMoreLink(props: Props): JSX.Element;

View File

@@ -0,0 +1,38 @@
/**
* 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 Translate, {translate} from '@docusaurus/Translate';
import Link from '@docusaurus/Link';
function ReadMoreLabel() {
return (
<b>
<Translate
id="theme.blog.post.readMore"
description="The label used in blog post item excerpts to link to full blog posts">
Read More
</Translate>
</b>
);
}
export default function BlogPostItemFooterReadMoreLink(props) {
const {blogPostTitle, ...linkProps} = props;
return (
<Link
aria-label={translate(
{
message: 'Read more about {title}',
id: 'theme.blog.post.readMoreLabel',
description:
'The ARIA label for the link to full blog posts from excerpts',
},
{title: blogPostTitle},
)}
{...linkProps}>
<ReadMoreLabel />
</Link>
);
}

View File

@@ -0,0 +1,8 @@
/**
* 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.
*/
/// <reference types="react" />
export default function BlogPostItemFooter(): JSX.Element | null;

View File

@@ -0,0 +1,52 @@
/**
* 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 clsx from 'clsx';
import {useBlogPost} from '@docusaurus/theme-common/internal';
import EditThisPage from '@theme/EditThisPage';
import TagsListInline from '@theme/TagsListInline';
import ReadMoreLink from '@theme/BlogPostItem/Footer/ReadMoreLink';
import styles from './styles.module.css';
export default function BlogPostItemFooter() {
const {metadata, isBlogPostPage} = useBlogPost();
const {tags, title, editUrl, hasTruncateMarker} = metadata;
// A post is truncated if it's in the "list view" and it has a truncate marker
const truncatedPost = !isBlogPostPage && hasTruncateMarker;
const tagsExists = tags.length > 0;
const renderFooter = tagsExists || truncatedPost || editUrl;
if (!renderFooter) {
return null;
}
return (
<footer
className={clsx(
'row docusaurus-mt-lg',
isBlogPostPage && styles.blogPostFooterDetailsFull,
)}>
{tagsExists && (
<div className={clsx('col', {'col--9': truncatedPost})}>
<TagsListInline tags={tags} />
</div>
)}
{isBlogPostPage && editUrl && (
<div className="col margin-top--sm">
<EditThisPage editUrl={editUrl} />
</div>
)}
{truncatedPost && (
<div
className={clsx('col text--right', {
'col--3': tagsExists,
})}>
<ReadMoreLink blogPostTitle={title} to={metadata.permalink} />
</div>
)}
</footer>
);
}

View File

@@ -0,0 +1,10 @@
/**
* 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.
*/
.blogPostFooterDetailsFull {
flex-direction: column;
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/BlogPostItem/Header/Author';
export default function BlogPostItemHeaderAuthor({ author, className, }: Props): JSX.Element;

View File

@@ -0,0 +1,52 @@
/**
* 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 clsx from 'clsx';
import Link from '@docusaurus/Link';
function MaybeLink(props) {
if (props.href) {
return <Link {...props} />;
}
return <>{props.children}</>;
}
export default function BlogPostItemHeaderAuthor({author, className}) {
const {name, title, url, imageURL, email} = author;
const link = url || (email && `mailto:${email}`) || undefined;
return (
<div className={clsx('avatar margin-bottom--sm', className)}>
{imageURL && (
<MaybeLink href={link} className="avatar__photo-link">
<img
className="avatar__photo"
src={imageURL}
alt={name}
itemProp="image"
/>
</MaybeLink>
)}
{name && (
<div
className="avatar__intro"
itemProp="author"
itemScope
itemType="https://schema.org/Person">
<div className="avatar__name">
<MaybeLink href={link} itemProp="url">
<span itemProp="name">{name}</span>
</MaybeLink>
</div>
{title && (
<small className="avatar__subtitle" itemProp="description">
{title}
</small>
)}
</div>
)}
</div>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/BlogPostItem/Header/Authors';
export default function BlogPostItemHeaderAuthors({ className, }: Props): JSX.Element | null;

View File

@@ -0,0 +1,48 @@
/**
* 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 clsx from 'clsx';
import {useBlogPost} from '@docusaurus/theme-common/internal';
import BlogPostItemHeaderAuthor from '@theme/BlogPostItem/Header/Author';
import styles from './styles.module.css';
// Component responsible for the authors layout
export default function BlogPostItemHeaderAuthors({className}) {
const {
metadata: {authors},
assets,
} = useBlogPost();
const authorsCount = authors.length;
if (authorsCount === 0) {
return null;
}
const imageOnly = authors.every(({name}) => !name);
return (
<div
className={clsx(
'margin-top--md margin-bottom--sm',
imageOnly ? styles.imageOnlyAuthorRow : 'row',
className,
)}>
{authors.map((author, idx) => (
<div
className={clsx(
!imageOnly && 'col col--6',
imageOnly ? styles.imageOnlyAuthorCol : styles.authorCol,
)}
key={idx}>
<BlogPostItemHeaderAuthor
author={{
...author,
// Handle author images using relative paths
imageURL: assets.authorsImageUrls[idx] ?? author.imageURL,
}}
/>
</div>
))}
</div>
);
}

View File

@@ -0,0 +1,21 @@
/**
* 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.
*/
.authorCol {
max-width: inherit !important;
flex-grow: 1 !important;
}
.imageOnlyAuthorRow {
display: flex;
flex-flow: row wrap;
}
.imageOnlyAuthorCol {
margin-left: 0.3rem;
margin-right: 0.3rem;
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/BlogPostItem/Header/Info';
export default function BlogPostItemHeaderInfo({ className, }: Props): JSX.Element;

View File

@@ -0,0 +1,60 @@
/**
* 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 clsx from 'clsx';
import {translate} from '@docusaurus/Translate';
import {usePluralForm} from '@docusaurus/theme-common';
import {useBlogPost} from '@docusaurus/theme-common/internal';
import styles from './styles.module.css';
// Very simple pluralization: probably good enough for now
function useReadingTimePlural() {
const {selectMessage} = usePluralForm();
return (readingTimeFloat) => {
const readingTime = Math.ceil(readingTimeFloat);
return selectMessage(
readingTime,
translate(
{
id: 'theme.blog.post.readingTime.plurals',
description:
'Pluralized label for "{readingTime} min read". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',
message: 'One min read|{readingTime} min read',
},
{readingTime},
),
);
};
}
function ReadingTime({readingTime}) {
const readingTimePlural = useReadingTimePlural();
return <>{readingTimePlural(readingTime)}</>;
}
function Date({date, formattedDate}) {
return (
<time dateTime={date} itemProp="datePublished">
{formattedDate}
</time>
);
}
function Spacer() {
return <>{' · '}</>;
}
export default function BlogPostItemHeaderInfo({className}) {
const {metadata} = useBlogPost();
const {date, formattedDate, readingTime} = metadata;
return (
<div className={clsx(styles.container, 'margin-vert--md', className)}>
<Date date={date} formattedDate={formattedDate} />
{typeof readingTime !== 'undefined' && (
<>
<Spacer />
<ReadingTime readingTime={readingTime} />
</>
)}
</div>
);
}

View File

@@ -0,0 +1,10 @@
/**
* 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.
*/
.container {
font-size: 0.9rem;
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/BlogPostItem/Header/Title';
export default function BlogPostItemHeaderTitle({ className, }: Props): JSX.Element;

View File

@@ -0,0 +1,27 @@
/**
* 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 clsx from 'clsx';
import Link from '@docusaurus/Link';
import {useBlogPost} from '@docusaurus/theme-common/internal';
import styles from './styles.module.css';
export default function BlogPostItemHeaderTitle({className}) {
const {metadata, isBlogPostPage} = useBlogPost();
const {permalink, title} = metadata;
const TitleHeading = isBlogPostPage ? 'h1' : 'h2';
return (
<TitleHeading className={clsx(styles.title, className)} itemProp="headline">
{isBlogPostPage ? (
title
) : (
<Link itemProp="url" to={permalink}>
{title}
</Link>
)}
</TitleHeading>
);
}

View File

@@ -0,0 +1,19 @@
/**
* 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.
*/
.title {
font-size: 3rem;
}
/**
Blog post title should be smaller on smaller devices
**/
@media (max-width: 576px) {
.title {
font-size: 2rem;
}
}

View File

@@ -0,0 +1,8 @@
/**
* 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.
*/
/// <reference types="react" />
export default function BlogPostItemHeader(): JSX.Element;

View File

@@ -0,0 +1,19 @@
/**
* 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 BlogPostItemHeaderTitle from '@theme/BlogPostItem/Header/Title';
import BlogPostItemHeaderInfo from '@theme/BlogPostItem/Header/Info';
import BlogPostItemHeaderAuthors from '@theme/BlogPostItem/Header/Authors';
export default function BlogPostItemHeader() {
return (
<header>
<BlogPostItemHeaderTitle />
<BlogPostItemHeaderInfo />
<BlogPostItemHeaderAuthors />
</header>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/BlogPostItem';
export default function BlogPostItem({ children, className, }: Props): JSX.Element;

View File

@@ -0,0 +1,28 @@
/**
* 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 clsx from 'clsx';
import {useBlogPost} from '@docusaurus/theme-common/internal';
import BlogPostItemContainer from '@theme/BlogPostItem/Container';
import BlogPostItemHeader from '@theme/BlogPostItem/Header';
import BlogPostItemContent from '@theme/BlogPostItem/Content';
import BlogPostItemFooter from '@theme/BlogPostItem/Footer';
// apply a bottom margin in list view
function useContainerClassName() {
const {isBlogPostPage} = useBlogPost();
return !isBlogPostPage ? 'margin-bottom--xl' : undefined;
}
export default function BlogPostItem({children, className}) {
const containerClassName = useContainerClassName();
return (
<BlogPostItemContainer className={clsx(containerClassName, className)}>
<BlogPostItemHeader />
<BlogPostItemContent>{children}</BlogPostItemContent>
<BlogPostItemFooter />
</BlogPostItemContainer>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/BlogPostItems';
export default function BlogPostItems({ items, component: BlogPostItemComponent, }: Props): JSX.Element;

View File

@@ -0,0 +1,27 @@
/**
* 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 {BlogPostProvider} from '@docusaurus/theme-common/internal';
import BlogPostItem from '@theme/BlogPostItem';
export default function BlogPostItems({
items,
component: BlogPostItemComponent = BlogPostItem,
}) {
return (
<>
{items.map(({content: BlogPostContent}) => (
<BlogPostProvider
key={BlogPostContent.metadata.permalink}
content={BlogPostContent}>
<BlogPostItemComponent>
<BlogPostContent />
</BlogPostItemComponent>
</BlogPostProvider>
))}
</>
);
}

View File

@@ -0,0 +1,8 @@
/**
* 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.
*/
/// <reference types="react" />
export default function BlogPostPageMetadata(): JSX.Element;

View File

@@ -0,0 +1,41 @@
/**
* 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 {PageMetadata} from '@docusaurus/theme-common';
import {useBlogPost} from '@docusaurus/theme-common/internal';
export default function BlogPostPageMetadata() {
const {assets, metadata} = useBlogPost();
const {title, description, date, tags, authors, frontMatter} = metadata;
const {keywords} = frontMatter;
const image = assets.image ?? frontMatter.image;
return (
<PageMetadata
title={title}
description={description}
keywords={keywords}
image={image}>
<meta property="og:type" content="article" />
<meta property="article:published_time" content={date} />
{/* TODO double check those article meta array syntaxes, see https://ogp.me/#array */}
{authors.some((author) => author.url) && (
<meta
property="article:author"
content={authors
.map((author) => author.url)
.filter(Boolean)
.join(',')}
/>
)}
{tags.length > 0 && (
<meta
property="article:tag"
content={tags.map((tag) => tag.label).join(',')}
/>
)}
</PageMetadata>
);
}

View File

@@ -0,0 +1,10 @@
/**
* 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.
*/
/// <reference types="@docusaurus/plugin-content-blog" />
/// <reference types="react" />
import type { Props } from '@theme/BlogPostPage';
export default function BlogPostPage(props: Props): JSX.Element;

View File

@@ -0,0 +1,62 @@
/**
* 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 clsx from 'clsx';
import {HtmlClassNameProvider, ThemeClassNames} from '@docusaurus/theme-common';
import {BlogPostProvider, useBlogPost} from '@docusaurus/theme-common/internal';
import BlogLayout from '@theme/BlogLayout';
import BlogPostItem from '@theme/BlogPostItem';
import BlogPostPaginator from '@theme/BlogPostPaginator';
import BlogPostPageMetadata from '@theme/BlogPostPage/Metadata';
import TOC from '@theme/TOC';
import Unlisted from '@theme/Unlisted';
function BlogPostPageContent({sidebar, children}) {
const {metadata, toc} = useBlogPost();
const {nextItem, prevItem, frontMatter, unlisted} = metadata;
const {
hide_table_of_contents: hideTableOfContents,
toc_min_heading_level: tocMinHeadingLevel,
toc_max_heading_level: tocMaxHeadingLevel,
} = frontMatter;
return (
<BlogLayout
sidebar={sidebar}
toc={
!hideTableOfContents && toc.length > 0 ? (
<TOC
toc={toc}
minHeadingLevel={tocMinHeadingLevel}
maxHeadingLevel={tocMaxHeadingLevel}
/>
) : undefined
}>
{unlisted && <Unlisted />}
<BlogPostItem>{children}</BlogPostItem>
{(nextItem || prevItem) && (
<BlogPostPaginator nextItem={nextItem} prevItem={prevItem} />
)}
</BlogLayout>
);
}
export default function BlogPostPage(props) {
const BlogPostContent = props.content;
return (
<BlogPostProvider content={props.content} isBlogPostPage>
<HtmlClassNameProvider
className={clsx(
ThemeClassNames.wrapper.blogPages,
ThemeClassNames.page.blogPostPage,
)}>
<BlogPostPageMetadata />
<BlogPostPageContent sidebar={props.sidebar}>
<BlogPostContent />
</BlogPostPageContent>
</HtmlClassNameProvider>
</BlogPostProvider>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/BlogPostPaginator';
export default function BlogPostPaginator(props: Props): JSX.Element;

View File

@@ -0,0 +1,47 @@
/**
* 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 Translate, {translate} from '@docusaurus/Translate';
import PaginatorNavLink from '@theme/PaginatorNavLink';
export default function BlogPostPaginator(props) {
const {nextItem, prevItem} = props;
return (
<nav
className="pagination-nav docusaurus-mt-lg"
aria-label={translate({
id: 'theme.blog.post.paginator.navAriaLabel',
message: 'Blog post page navigation',
description: 'The ARIA label for the blog posts pagination',
})}>
{prevItem && (
<PaginatorNavLink
{...prevItem}
subLabel={
<Translate
id="theme.blog.post.paginator.newerPost"
description="The blog post button label to navigate to the newer/previous post">
Newer Post
</Translate>
}
/>
)}
{nextItem && (
<PaginatorNavLink
{...nextItem}
subLabel={
<Translate
id="theme.blog.post.paginator.olderPost"
description="The blog post button label to navigate to the older/next post">
Older Post
</Translate>
}
isNext
/>
)}
</nav>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/BlogSidebar/Desktop';
export default function BlogSidebarDesktop({ sidebar }: Props): JSX.Element;

View File

@@ -0,0 +1,43 @@
/**
* 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 clsx from 'clsx';
import Link from '@docusaurus/Link';
import {translate} from '@docusaurus/Translate';
import {useVisibleBlogSidebarItems} from '@docusaurus/theme-common/internal';
import styles from './styles.module.css';
export default function BlogSidebarDesktop({sidebar}) {
const items = useVisibleBlogSidebarItems(sidebar.items);
return (
<aside className="col col--3">
<nav
className={clsx(styles.sidebar, 'thin-scrollbar')}
aria-label={translate({
id: 'theme.blog.sidebar.navAriaLabel',
message: 'Blog recent posts navigation',
description: 'The ARIA label for recent posts in the blog sidebar',
})}>
<div className={clsx(styles.sidebarItemTitle, 'margin-bottom--md')}>
{sidebar.title}
</div>
<ul className={clsx(styles.sidebarItemList, 'clean-list')}>
{items.map((item) => (
<li key={item.permalink} className={styles.sidebarItem}>
<Link
isNavLink
to={item.permalink}
className={styles.sidebarItemLink}
activeClassName={styles.sidebarItemLinkActive}>
{item.title}
</Link>
</li>
))}
</ul>
</nav>
</aside>
);
}

View File

@@ -0,0 +1,45 @@
/**
* 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.
*/
.sidebar {
max-height: calc(100vh - (var(--ifm-navbar-height) + 2rem));
overflow-y: auto;
position: sticky;
top: calc(var(--ifm-navbar-height) + 2rem);
}
.sidebarItemTitle {
font-size: var(--ifm-h3-font-size);
font-weight: var(--ifm-font-weight-bold);
}
.sidebarItemList {
font-size: 0.9rem;
}
.sidebarItem {
margin-top: 0.7rem;
}
.sidebarItemLink {
color: var(--ifm-font-color-base);
display: block;
}
.sidebarItemLink:hover {
text-decoration: none;
}
.sidebarItemLinkActive {
color: var(--ifm-color-primary) !important;
}
@media (max-width: 996px) {
.sidebar {
display: none;
}
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/BlogSidebar/Mobile';
export default function BlogSidebarMobile(props: Props): JSX.Element;

View File

@@ -0,0 +1,36 @@
/**
* 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 Link from '@docusaurus/Link';
import {useVisibleBlogSidebarItems} from '@docusaurus/theme-common/internal';
import {NavbarSecondaryMenuFiller} from '@docusaurus/theme-common';
function BlogSidebarMobileSecondaryMenu({sidebar}) {
const items = useVisibleBlogSidebarItems(sidebar.items);
return (
<ul className="menu__list">
{items.map((item) => (
<li key={item.permalink} className="menu__list-item">
<Link
isNavLink
to={item.permalink}
className="menu__link"
activeClassName="menu__link--active">
{item.title}
</Link>
</li>
))}
</ul>
);
}
export default function BlogSidebarMobile(props) {
return (
<NavbarSecondaryMenuFiller
component={BlogSidebarMobileSecondaryMenu}
props={props}
/>
);
}

View File

@@ -0,0 +1,9 @@
/**
* 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.
*/
/// <reference types="react" />
import type { Props } from '@theme/BlogSidebar';
export default function BlogSidebar({ sidebar }: Props): JSX.Element | null;

Some files were not shown because too many files have changed in this diff Show More