├── .babelrc.js ├── .eslintrc.js ├── .gitignore ├── .npmignore ├── package.json ├── src ├── index.ts ├── prism-include-languages.js ├── styles.css ├── tailwind-preset.js ├── theme │ ├── Anchor.tsx │ ├── AnnouncementBar.tsx │ ├── BlogListPage.tsx │ ├── BlogListPaginator.tsx │ ├── BlogPostItem │ │ └── index.tsx │ ├── BlogPostPage.tsx │ ├── BlogPostPaginator.tsx │ ├── BlogSidebar │ │ ├── index.tsx │ │ └── styles.module.css │ ├── BlogTagsListPage.tsx │ ├── BlogTagsPostsPage.tsx │ ├── CodeBlock │ │ ├── index.tsx │ │ └── styles.module.css │ ├── DocItem │ │ └── index.tsx │ ├── DocPage │ │ └── index.tsx │ ├── DocPaginator │ │ └── index.tsx │ ├── DocSidebar │ │ ├── index.tsx │ │ └── styles.module.css │ ├── DocVersionBanner │ │ └── index.tsx │ ├── EditThisPage │ │ └── index.tsx │ ├── Footer │ │ └── index.tsx │ ├── Heading │ │ ├── index.tsx │ │ ├── styles.css │ │ └── styles.module.css │ ├── IconArrow │ │ └── index.tsx │ ├── IconEdit │ │ ├── index.tsx │ │ └── styles.module.css │ ├── IconLanguage │ │ └── index.tsx │ ├── IconMenu │ │ └── index.tsx │ ├── LastUpdated │ │ ├── index.tsx │ │ └── styles.module.css │ ├── Layout │ │ ├── index.tsx │ │ └── styles.css │ ├── LayoutHead │ │ └── index.tsx │ ├── LayoutProviders │ │ └── index.tsx │ ├── Logo │ │ └── index.tsx │ ├── MDXComponents │ │ ├── Blockquote.tsx │ │ ├── Em.tsx │ │ ├── Hr.tsx │ │ ├── Li.tsx │ │ ├── Ol.tsx │ │ ├── P.tsx │ │ ├── Strong.tsx │ │ ├── Ul.tsx │ │ ├── createStyledElement.tsx │ │ └── index.tsx │ ├── MDXPage │ │ └── index.tsx │ ├── Menu │ │ ├── index.tsx │ │ └── styles.module.css │ ├── Navbar │ │ └── index.tsx │ ├── NavbarItem │ │ ├── DefaultNavbarItem.tsx │ │ ├── DocNavbarItem.tsx │ │ ├── DocsVersionDropdownNavbarItem.tsx │ │ ├── DocsVersionNavbarItem.tsx │ │ ├── LocaleDropdownNavbarItem.tsx │ │ ├── SearchNavbarItem.tsx │ │ ├── index.tsx │ │ └── styles.module.css │ ├── NotFound.tsx │ ├── Paginator.tsx │ ├── SearchBar.tsx │ ├── SearchMetadatas │ │ └── index.tsx │ ├── Seo │ │ └── index.tsx │ ├── SkipToContent │ │ ├── index.tsx │ │ └── styles.module.css │ ├── TOC │ │ └── index.tsx │ ├── TOCInline │ │ ├── index.tsx │ │ └── styles.module.css │ ├── TabItem │ │ └── index.tsx │ ├── Tabs │ │ ├── index.tsx │ │ └── styles.module.css │ ├── ThemeContext.ts │ ├── ThemeProvider │ │ └── index.tsx │ ├── ThemedImage │ │ ├── Toggle │ │ │ ├── index.tsx │ │ │ └── styles.module.css │ │ ├── index.tsx │ │ └── styles.module.css │ ├── Toggle │ │ ├── index.tsx │ │ └── styles.module.css │ ├── UserPreferencesContext.ts │ ├── UserPreferencesProvider │ │ └── index.tsx │ ├── hooks │ │ ├── styles.css │ │ ├── useAnnouncementBar.ts │ │ ├── useContextualSearchFilters.ts │ │ ├── useDocs.ts │ │ ├── useHideableNavbar.ts │ │ ├── useKeyboardNavigation.ts │ │ ├── useLocationHash.ts │ │ ├── useLockBodyScroll.ts │ │ ├── usePrismTheme.ts │ │ ├── useScrollPosition.ts │ │ ├── useTOCHighlight.ts │ │ ├── useTabGroupChoice.ts │ │ ├── useTheme.ts │ │ ├── useThemeContext.ts │ │ ├── useUserPreferencesContext.ts │ │ └── useWindowSize.ts │ └── prism-include-languages.ts ├── translations.ts ├── types.d.ts └── validateThemeConfig.js ├── tailwind.config.js ├── tsconfig.json ├── www ├── .gitignore ├── README.md ├── babel.config.js ├── blog │ ├── 2019-05-28-hola.md │ ├── 2019-05-29-hello-world.md │ └── 2019-05-30-welcome.md ├── docs │ ├── intro.md │ ├── tutorial-basics │ │ ├── _category_.json │ │ ├── congratulations.md │ │ ├── create-a-blog-post.md │ │ ├── create-a-document.md │ │ ├── create-a-page.md │ │ ├── deploy-your-site.md │ │ └── markdown-features.mdx │ └── tutorial-extras │ │ ├── _category_.json │ │ ├── manage-docs-versions.md │ │ └── translate-your-site.md ├── docusaurus.config.js ├── package.json ├── plugins │ └── webpack.js ├── sidebars.js ├── src │ ├── components │ │ ├── HomepageFeatures.js │ │ └── HomepageFeatures.module.css │ ├── css │ │ └── custom.css │ └── pages │ │ ├── index.js │ │ ├── index.module.css │ │ └── markdown-page.md ├── static │ ├── .nojekyll │ └── img │ │ ├── docusaurus.png │ │ ├── favicon.ico │ │ ├── logo.svg │ │ ├── tutorial │ │ ├── docsVersionDropdown.png │ │ └── localeDropdown.png │ │ ├── undraw_docusaurus_mountain.svg │ │ ├── undraw_docusaurus_react.svg │ │ └── undraw_docusaurus_tree.svg ├── tailwind.config.js ├── versioned_docs │ ├── version-1.0.0-alpha.0 │ │ ├── intro.md │ │ ├── tutorial-basics │ │ │ ├── _category_.json │ │ │ ├── congratulations.md │ │ │ ├── create-a-blog-post.md │ │ │ ├── create-a-document.md │ │ │ ├── create-a-page.md │ │ │ ├── deploy-your-site.md │ │ │ └── markdown-features.mdx │ │ └── tutorial-extras │ │ │ ├── _category_.json │ │ │ ├── manage-docs-versions.md │ │ │ └── translate-your-site.md │ └── version-1.0.0-alpha.1 │ │ ├── intro.md │ │ ├── tutorial-basics │ │ ├── _category_.json │ │ ├── congratulations.md │ │ ├── create-a-blog-post.md │ │ ├── create-a-document.md │ │ ├── create-a-page.md │ │ ├── deploy-your-site.md │ │ └── markdown-features.mdx │ │ └── tutorial-extras │ │ ├── _category_.json │ │ ├── manage-docs-versions.md │ │ └── translate-your-site.md ├── versioned_sidebars │ ├── version-1.0.0-alpha.0-sidebars.json │ └── version-1.0.0-alpha.1-sidebars.json ├── versions.json └── yarn.lock └── yarn.lock /.babelrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | "env-modules", 4 | ["@babel/react", { runtime: "automatic" }], 5 | "@babel/typescript", 6 | ], 7 | }; 8 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ["jason/react", "4catalyzer-typescript", "prettier"], 3 | rules: { 4 | "import/extensions": "off", 5 | "@typescript-eslint/no-empty-function": "off", 6 | "react/jsx-uses-react": "off", 7 | "react/react-in-jsx-scope": "off", 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | *.tsbuildinfo 14 | 15 | # Directory for instrumented libs generated by jscoverage/JSCover 16 | lib-cov 17 | 18 | # Coverage directory used by tools like istanbul 19 | coverage 20 | 21 | # nyc test coverage 22 | .nyc_output 23 | 24 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 25 | .grunt 26 | 27 | # Bower dependency directory (https://bower.io/) 28 | bower_components 29 | 30 | # node-waf configuration 31 | .lock-wscript 32 | 33 | # Compiled binary addons (https://nodejs.org/api/addons.html) 34 | build/Release 35 | 36 | # Dependency directories 37 | node_modules/ 38 | jspm_packages/ 39 | 40 | # TypeScript v1 declaration files 41 | typings/ 42 | 43 | esm/ 44 | lib/ 45 | 46 | # Optional npm cache directory 47 | .npm 48 | 49 | # Optional eslint cache 50 | .eslintcache 51 | 52 | # Optional REPL history 53 | .node_repl_history 54 | 55 | # Output of 'npm pack' 56 | *.tgz 57 | 58 | # Yarn Integrity file 59 | .yarn-integrity 60 | 61 | # dotenv environment variables file 62 | .env 63 | 64 | # next.js build output 65 | .next 66 | 67 | # Webpack output. 68 | build/ 69 | 70 | # Generated files. 71 | __generated__ 72 | 73 | # Protractor failure file. 74 | .protractor-fail-fast 75 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | www/ 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docusaurus-theme-tailwind", 3 | "version": "1.0.1-rc.1", 4 | "main": "lib/index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "lint": "4c lint src", 8 | "build": "4c build --no-types", 9 | "prepublishOnly": "yarn build" 10 | }, 11 | "gitHooks": { 12 | "pre-commit": "lint-staged" 13 | }, 14 | "lint-staged": { 15 | "*": "4c lint --fix" 16 | }, 17 | "prettier": { 18 | "singleQuote": false 19 | }, 20 | "peerDependencies": { 21 | "postcss": "^8.2.10", 22 | "react": "^17.0.2", 23 | "react-dom": "^17.0.2" 24 | }, 25 | "devDependencies": { 26 | "@4c/cli": "^2.2.8", 27 | "@4c/start": "^2.5.3", 28 | "@4c/tsconfig": "^0.4.0", 29 | "@babel/core": "^7.15.0", 30 | "@babel/preset-react": "^7.14.5", 31 | "@babel/preset-typescript": "^7.15.0", 32 | "@docusaurus/module-type-aliases": "^2.0.0-beta.4", 33 | "@types/prismjs": "^1.16.6", 34 | "@typescript-eslint/eslint-plugin": "^4.29.2", 35 | "@typescript-eslint/parser": "^4.29.2", 36 | "babel-preset-env-modules": "^1.0.1", 37 | "eslint": "^7.32.0", 38 | "eslint-config-4catalyzer-typescript": "^3.1.0", 39 | "eslint-config-jason": "^8.1.1", 40 | "eslint-config-prettier": "^8.3.0", 41 | "eslint-plugin-import": "^2.24.0", 42 | "eslint-plugin-react": "^7.24.0", 43 | "eslint-plugin-react-hooks": "^4.2.0", 44 | "hookem": "^1.0.8", 45 | "lint-staged": "^11.1.2", 46 | "prettier": "^2.3.2", 47 | "react": "^17.0.2", 48 | "react-dom": "^17.0.2", 49 | "tailwindcss": "^2.2.7", 50 | "typescript": "^4.3.5" 51 | }, 52 | "dependencies": { 53 | "@docusaurus/theme-common": "2.0.0-beta.4", 54 | "@docusaurus/types": "2.0.0-beta.4", 55 | "@docusaurus/utils": "2.0.0-beta.4", 56 | "@tailwindcss/typography": "^0.4.1", 57 | "@types/node": "^16.6.1", 58 | "@types/react": "^17.0.18", 59 | "@types/react-dom": "^17.0.9", 60 | "clsx": "^1.1.1", 61 | "copy-text-to-clipboard": "^3.0.1", 62 | "parse-numeric-range": "^1.2.0", 63 | "postcss": "^8.3.6", 64 | "prism-react-renderer": "^1.2.1", 65 | "prismjs": "^1.24.1" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/prism-include-languages.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import Prism from 'prism-react-renderer/prism'; 9 | import prismIncludeLanguages from '@theme/prism-include-languages'; 10 | 11 | prismIncludeLanguages(Prism); 12 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss/base"; 2 | @import "tailwindcss/components"; 3 | 4 | a { 5 | @apply text-primary hover:underline; 6 | } 7 | 8 | @import "tailwindcss/utilities"; 9 | 10 | .max-w-full-navbar { 11 | max-height: calc(100vh - (theme("height.16") + theme("margin.8"))); 12 | } 13 | 14 | .top-full-navbar { 15 | top: calc(theme("height.16") + theme("margin.8")); 16 | } 17 | -------------------------------------------------------------------------------- /src/tailwind-preset.js: -------------------------------------------------------------------------------- 1 | const colors = require("tailwindcss/colors"); 2 | 3 | const purge = [`${__dirname}/theme/**/*.{js,jsx,ts,tsx}`]; 4 | 5 | const siteDir = process.env.DOCUSAURUS_SITE_DIR; 6 | if (siteDir) { 7 | purge.push(`${siteDir}/blog/**/*.{js,jsx,ts,tsx,mdx}`); 8 | purge.push(`${siteDir}/docs/**/*.{js,jsx,ts,tsx,mdx}`); 9 | purge.push(`${siteDir}/src/**/*.{js,jsx,ts,tsx,mdx}`); 10 | } 11 | console.log(process.env.NODE_ENV); 12 | module.exports = { 13 | purge, 14 | mode: "jit", 15 | darkMode: false, // or 'media' or 'class' 16 | theme: { 17 | menu: { 18 | // color: t('colors') 19 | sublistIcon: 20 | 'data:image/svg+xml;utf8,', 21 | }, 22 | 23 | extend: { 24 | minWidth: (t) => t("width"), 25 | 26 | screens: { 27 | print: { raw: "print" }, 28 | }, 29 | 30 | transitionProperty: { 31 | width: "width", 32 | visibility: "opacity, visibility", 33 | DEFAULT: 34 | "background-color, border-color, color, fill, stroke, opacity, visibility, box-shadow, transform, filter, backdrop-filter", 35 | }, 36 | colors: { 37 | primary: { 38 | DEFAULT: colors.blue["500"], 39 | ...colors.blue, 40 | }, 41 | surface: colors.white, 42 | emphasis: colors.gray, 43 | warning: colors.amber, 44 | info: colors.cyan, 45 | danger: colors.red, 46 | overlay: "rgba(0, 0, 0, 0.05)", 47 | inherit: "inherit", 48 | }, 49 | 50 | typography: (theme) => ({ 51 | DEFAULT: { 52 | css: { 53 | maxWidth: "unset", 54 | a: { 55 | textDecoration: "none", 56 | "&:hover": { 57 | textDecoration: "underline", 58 | }, 59 | }, 60 | strong: { 61 | color: "unset", 62 | }, 63 | 64 | code: { 65 | color: theme("colors.gray.900", colors.gray[900]), 66 | fontSize: "90%", 67 | fontWeight: "normal", 68 | border: "0.1rem solid rgba(0, 0, 0, 0.1)", 69 | borderRadius: theme("borderRadius.DEFAULT"), 70 | padding: ".1rem .3rem", 71 | background: "rgba(0, 0, 0, .05)", 72 | }, 73 | "code::before": { 74 | content: "", 75 | }, 76 | "code::after": { 77 | content: "", 78 | }, 79 | }, 80 | }, 81 | }), 82 | }, 83 | }, 84 | variants: { 85 | extend: {}, 86 | }, 87 | // eslint-disable-next-line global-require 88 | plugins: [require("@tailwindcss/typography")], 89 | }; 90 | -------------------------------------------------------------------------------- /src/theme/Anchor.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | import React from "react"; 3 | 4 | const Anchor = React.forwardRef( 5 | (props: React.ComponentProps<"a">, ref) => { 6 | return ( 7 | 12 | ); 13 | } 14 | ); 15 | 16 | export default Anchor; 17 | -------------------------------------------------------------------------------- /src/theme/AnnouncementBar.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from "react"; 9 | import clsx from "clsx"; 10 | import { useThemeConfig } from "@docusaurus/theme-common"; 11 | import useUserPreferencesContext from "@theme/hooks/useUserPreferencesContext"; 12 | import { translate } from "@docusaurus/Translate"; 13 | 14 | function AnnouncementBar(): JSX.Element | null { 15 | const { 16 | isAnnouncementBarClosed, 17 | closeAnnouncementBar, 18 | } = useUserPreferencesContext(); 19 | const { announcementBar } = useThemeConfig(); 20 | 21 | if (!announcementBar) { 22 | return null; 23 | } 24 | 25 | const { content, backgroundColor, textColor, isCloseable } = announcementBar; 26 | if (!content || (isCloseable && isAnnouncementBarClosed)) { 27 | return null; 28 | } 29 | 30 | return ( 31 |
40 |
49 | {isCloseable ? ( 50 | 62 | ) : null} 63 |
64 | ); 65 | } 66 | 67 | export default AnnouncementBar; 68 | -------------------------------------------------------------------------------- /src/theme/BlogListPage.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from "react"; 9 | 10 | import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; 11 | import Layout from "@theme/Layout"; 12 | import BlogPostItem from "@theme/BlogPostItem"; 13 | import BlogListPaginator from "@theme/BlogListPaginator"; 14 | import type { Props } from "@theme/BlogListPage"; 15 | import BlogSidebar from "@theme/BlogSidebar"; 16 | import { ThemeClassNames } from "@docusaurus/theme-common"; 17 | 18 | function BlogListPage(props: Props): JSX.Element { 19 | const { metadata, items, sidebar } = props; 20 | const { 21 | siteConfig: { title: siteTitle }, 22 | } = useDocusaurusContext(); 23 | const { blogDescription, blogTitle, permalink } = metadata; 24 | const isBlogOnlyMode = permalink === "/"; 25 | const title = isBlogOnlyMode ? siteTitle : blogTitle; 26 | return ( 27 | 37 |
38 | 39 | 40 |
41 | {items.map(({ content: BlogPostContent }) => ( 42 | 48 | 49 | 50 | ))} 51 | 52 |
53 |
54 |
55 | ); 56 | } 57 | 58 | export default BlogListPage; 59 | -------------------------------------------------------------------------------- /src/theme/BlogListPaginator.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from "react"; 9 | import Translate, { translate } from "@docusaurus/Translate"; 10 | import type { Props } from "@theme/BlogListPaginator"; 11 | import Paginator from "./Paginator"; 12 | 13 | function BlogListPaginator(props: Props): JSX.Element { 14 | const { metadata } = props; 15 | const { previousPage, nextPage } = metadata; 16 | 17 | return ( 18 | 25 | 26 | {previousPage && ( 27 | 31 | {" "} 32 | «{" "} 33 | 37 | Newer Entries 38 | 39 | 40 | } 41 | /> 42 | )} 43 | 44 | 45 | {nextPage && ( 46 | 50 | 54 | Older Entries 55 | {" "} 56 | » 57 | 58 | } 59 | /> 60 | )} 61 | 62 | 63 | ); 64 | } 65 | 66 | export default BlogListPaginator; 67 | -------------------------------------------------------------------------------- /src/theme/BlogPostItem/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from "react"; 9 | import { MDXProvider } from "@mdx-js/react"; 10 | import Translate, { translate } from "@docusaurus/Translate"; 11 | import Link from "@docusaurus/Link"; 12 | import MDXComponents from "@theme/MDXComponents"; 13 | import Seo from "@theme/Seo"; 14 | import type { Props } from "@theme/BlogPostItem"; 15 | 16 | import { usePluralForm } from "@docusaurus/theme-common"; 17 | 18 | // Very simple pluralization: probably good enough for now 19 | function useReadingTimePlural() { 20 | const { selectMessage } = usePluralForm(); 21 | return (readingTimeFloat: number) => { 22 | const readingTime = Math.ceil(readingTimeFloat); 23 | return selectMessage( 24 | readingTime, 25 | translate( 26 | { 27 | id: "theme.blog.post.readingTime.plurals", 28 | description: 29 | '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)', 30 | message: "One min read|{readingTime} min read", 31 | }, 32 | { readingTime } 33 | ) 34 | ); 35 | }; 36 | } 37 | 38 | function BlogPostItem(props: Props): JSX.Element { 39 | const readingTimePlural = useReadingTimePlural(); 40 | const { 41 | children, 42 | frontMatter, 43 | metadata, 44 | truncated, 45 | isBlogPostPage = false, 46 | } = props; 47 | const { date, formattedDate, permalink, tags, readingTime } = metadata; 48 | const { author, title, image, keywords } = frontMatter; 49 | 50 | const authorURL = frontMatter.author_url || frontMatter.authorURL; 51 | const authorTitle = frontMatter.author_title || frontMatter.authorTitle; 52 | const authorImageURL = 53 | frontMatter.author_image_url || frontMatter.authorImageURL; 54 | 55 | const renderPostHeader = () => { 56 | const TitleHeading = isBlogPostPage ? "h1" : "h2"; 57 | 58 | return ( 59 |
60 | 61 | {isBlogPostPage ? title : {title}} 62 | 63 |
64 | 73 |
74 |
75 | {authorImageURL && ( 76 | 80 | {author} 81 | 82 | )} 83 |
84 | {author && ( 85 | <> 86 |

87 | {author} 88 |

89 | {authorTitle} 90 | 91 | )} 92 |
93 |
94 |
95 | ); 96 | }; 97 | 98 | return ( 99 | <> 100 | 101 | 102 |
103 | {renderPostHeader()} 104 |
105 | {children} 106 |
107 | {(tags.length > 0 || truncated) && ( 108 |
109 | {tags.length > 0 && ( 110 |
111 | 112 | 116 | Tags: 117 | 118 | 119 | {tags.map(({ label, permalink: tagPermalink }) => ( 120 | 121 | {label} 122 | 123 | ))} 124 |
125 | )} 126 | {truncated && ( 127 |
128 | 132 | 133 | 137 | Read More 138 | 139 | 140 | 141 |
142 | )} 143 |
144 | )} 145 |
146 | 147 | ); 148 | } 149 | 150 | export default BlogPostItem; 151 | -------------------------------------------------------------------------------- /src/theme/BlogPostPage.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from "react"; 9 | import Layout from "@theme/Layout"; 10 | import BlogPostItem from "@theme/BlogPostItem"; 11 | import BlogPostPaginator from "@theme/BlogPostPaginator"; 12 | import type { Props } from "@theme/BlogPostPage"; 13 | import BlogSidebar from "@theme/BlogSidebar"; 14 | import TOC from "@theme/TOC"; 15 | import EditThisPage from "@theme/EditThisPage"; 16 | import { ThemeClassNames } from "@docusaurus/theme-common"; 17 | 18 | function BlogPostPage(props: Props): JSX.Element { 19 | const { content: BlogPostContents, sidebar } = props; 20 | const { frontMatter, metadata } = BlogPostContents; 21 | const { title, description, nextItem, prevItem, editUrl } = metadata; 22 | const { hide_table_of_contents: hideTableOfContents } = frontMatter; 23 | 24 | return ( 25 | 31 | {BlogPostContents && ( 32 |
33 |
34 | 35 |
36 |
37 | 42 | 43 | 44 |
{editUrl && }
45 | {(nextItem || prevItem) && ( 46 |
47 | 48 |
49 | )} 50 |
51 | {!hideTableOfContents && BlogPostContents.toc && ( 52 | 53 | )} 54 |
55 | )} 56 |
57 | ); 58 | } 59 | 60 | export default BlogPostPage; 61 | -------------------------------------------------------------------------------- /src/theme/BlogPostPaginator.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from "react"; 9 | import Translate, { translate } from "@docusaurus/Translate"; 10 | 11 | import type { Props } from "@theme/BlogPostPaginator"; 12 | import Paginator from "./Paginator"; 13 | 14 | function BlogPostPaginator(props: Props): JSX.Element { 15 | const { nextItem, prevItem } = props; 16 | 17 | return ( 18 | 25 | 26 | {prevItem && ( 27 | 34 | Newer Post 35 | 36 | } 37 | title={<>« {prevItem.title}} 38 | /> 39 | )} 40 | 41 | 42 | {nextItem && ( 43 | {nextItem.title} »} 46 | subtitle={ 47 | 51 | Older Post 52 | 53 | } 54 | /> 55 | )} 56 | 57 | 58 | ); 59 | } 60 | 61 | export default BlogPostPaginator; 62 | -------------------------------------------------------------------------------- /src/theme/BlogSidebar/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from "react"; 9 | import clsx from "clsx"; 10 | import Link from "@docusaurus/Link"; 11 | import type { Props } from "@theme/BlogSidebar"; 12 | import styles from "./styles.module.css"; 13 | 14 | export default function BlogSidebar({ 15 | sidebar, 16 | className, 17 | }: Props & { className?: string }): JSX.Element | null { 18 | if (sidebar.items.length === 0) { 19 | return null; 20 | } 21 | return ( 22 |
29 |

{sidebar.title}

30 |
    31 | {sidebar.items.map((item) => { 32 | return ( 33 |
  • 34 | 40 | {item.title} 41 | 42 |
  • 43 | ); 44 | })} 45 |
46 |
47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /src/theme/BlogSidebar/styles.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | .sidebar { 9 | max-height: calc(100vh - (theme("height.16") + theme("margin.8"))); 10 | } 11 | -------------------------------------------------------------------------------- /src/theme/BlogTagsListPage.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from "react"; 9 | 10 | import Layout from "@theme/Layout"; 11 | import Link from "@docusaurus/Link"; 12 | import type { Props } from "@theme/BlogTagsListPage"; 13 | import BlogSidebar from "@theme/BlogSidebar"; 14 | import Translate from "@docusaurus/Translate"; 15 | import { ThemeClassNames } from "@docusaurus/theme-common"; 16 | import Anchor from "@theme/Anchor"; 17 | 18 | function getCategoryOfTag(tag: string) { 19 | // tag's category should be customizable 20 | return tag[0].toUpperCase(); 21 | } 22 | 23 | function BlogTagsListPage(props: Props): JSX.Element { 24 | const { tags, sidebar } = props; 25 | 26 | const tagCategories: { [category: string]: string[] } = {}; 27 | Object.keys(tags).forEach((tag) => { 28 | const category = getCategoryOfTag(tag); 29 | tagCategories[category] = tagCategories[category] || []; 30 | tagCategories[category].push(tag); 31 | }); 32 | const tagsList = Object.entries(tagCategories).sort(([a], [b]) => { 33 | if (a === b) { 34 | return 0; 35 | } 36 | return a > b ? 1 : -1; 37 | }); 38 | const tagsSection = tagsList 39 | .map(([category, tagsForCategory]) => ( 40 |
41 |

{category}

42 | {tagsForCategory.map((tag) => ( 43 | 49 | {tags[tag].name} ({tags[tag].count}) 50 | 51 | ))} 52 |
53 |
54 | )) 55 | .filter((item) => item != null); 56 | 57 | return ( 58 | 68 |
69 | 70 | 71 |
72 |

73 | 77 | Tags 78 | 79 |

80 |
{tagsSection}
81 |
82 |
83 |
84 | ); 85 | } 86 | 87 | export default BlogTagsListPage; 88 | -------------------------------------------------------------------------------- /src/theme/BlogTagsPostsPage.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from "react"; 9 | 10 | import Layout from "@theme/Layout"; 11 | import BlogPostItem from "@theme/BlogPostItem"; 12 | import Link from "@docusaurus/Link"; 13 | import type { Props } from "@theme/BlogTagsPostsPage"; 14 | import BlogSidebar from "@theme/BlogSidebar"; 15 | import Translate, { translate } from "@docusaurus/Translate"; 16 | import { ThemeClassNames, usePluralForm } from "@docusaurus/theme-common"; 17 | import Anchor from "@theme/Anchor"; 18 | 19 | // Very simple pluralization: probably good enough for now 20 | function useBlogPostsPlural() { 21 | const { selectMessage } = usePluralForm(); 22 | return (count: number) => 23 | selectMessage( 24 | count, 25 | translate( 26 | { 27 | id: "theme.blog.post.plurals", 28 | description: 29 | 'Pluralized label for "{count} posts". 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)', 30 | message: "One post|{count} posts", 31 | }, 32 | { count } 33 | ) 34 | ); 35 | } 36 | 37 | function BlogTagsPostPageTitle({ 38 | tagName, 39 | count, 40 | }: { 41 | tagName: string; 42 | count: number; 43 | }) { 44 | const blogPostsPlural = useBlogPostsPlural(); 45 | return ( 46 | 51 | {'{nPosts} tagged with "{tagName}"'} 52 | 53 | ); 54 | } 55 | 56 | function BlogTagsPostPage(props: Props): JSX.Element { 57 | const { metadata, items, sidebar } = props; 58 | const { allTagsPath, name: tagName, count } = metadata; 59 | 60 | return ( 61 | 71 |
72 | 73 |
74 |

75 | 76 |

77 | 78 | 82 | View All Tags 83 | 84 | 85 |
86 | {items.map(({ content: BlogPostContent }) => ( 87 | 93 | 94 | 95 | ))} 96 |
97 |
98 |
99 |
100 | ); 101 | } 102 | 103 | export default BlogTagsPostPage; 104 | -------------------------------------------------------------------------------- /src/theme/CodeBlock/styles.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | .codeBlockContent { 9 | position: relative; 10 | /*rtl:ignore*/ 11 | direction: ltr; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /src/theme/DocItem/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from "react"; 9 | import DocPaginator from "@theme/DocPaginator"; 10 | import DocVersionBanner from "@theme/DocVersionBanner"; 11 | import Seo from "@theme/Seo"; 12 | import LastUpdated from "@theme/LastUpdated"; 13 | import type { Props } from "@theme/DocItem"; 14 | import TOC from "@theme/TOC"; 15 | import EditThisPage from "@theme/EditThisPage"; 16 | 17 | import clsx from "clsx"; 18 | import { 19 | useActivePlugin, 20 | useVersions, 21 | useActiveVersion, 22 | } from "@theme/hooks/useDocs"; 23 | 24 | function DocItem(props: Props): JSX.Element { 25 | const { content: DocContent, versionMetadata } = props; 26 | const { 27 | metadata, 28 | frontMatter: { 29 | image, 30 | keywords, 31 | hide_title: hideTitle, 32 | hide_table_of_contents: hideTableOfContents, 33 | }, 34 | } = DocContent; 35 | const { 36 | description, 37 | title, 38 | editUrl, 39 | lastUpdatedAt, 40 | formattedLastUpdatedAt, 41 | lastUpdatedBy, 42 | } = metadata; 43 | 44 | const { pluginId } = useActivePlugin({ failfast: true }); 45 | const versions = useVersions(pluginId); 46 | const version = useActiveVersion(pluginId); 47 | 48 | // If site is not versioned or only one version is included 49 | // we don't show the version badge 50 | // See https://github.com/facebook/docusaurus/issues/3362 51 | const showVersionBadge = versions.length > 1; 52 | 53 | return ( 54 | <> 55 | 56 | 57 |
58 |
59 | 60 |
61 |
62 | {showVersionBadge && ( 63 |
64 | 65 | Version: {version.label} 66 | 67 |
68 | )} 69 | {!hideTitle && ( 70 |
71 |

72 | {title} 73 |

74 |
75 | )} 76 |
77 | 78 |
79 |
80 | {(editUrl || lastUpdatedAt || lastUpdatedBy) && ( 81 |
82 |
83 |
84 | {editUrl && } 85 |
86 | {(lastUpdatedAt || lastUpdatedBy) && ( 87 | 92 | )} 93 |
94 |
95 | )} 96 |
97 | 98 |
99 |
100 |
101 | {!hideTableOfContents && DocContent.toc && ( 102 |
103 | 104 |
105 | )} 106 |
107 | 108 | ); 109 | } 110 | 111 | export default DocItem; 112 | -------------------------------------------------------------------------------- /src/theme/DocPaginator/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from "react"; 9 | import Link from "@docusaurus/Link"; 10 | import Translate, { translate } from "@docusaurus/Translate"; 11 | import type { Props } from "@theme/DocPaginator"; 12 | import Paginator from "../Paginator"; 13 | 14 | function DocPaginator(props: Props): JSX.Element { 15 | const { metadata } = props; 16 | 17 | return ( 18 | 25 | 26 | {metadata.previous && ( 27 | 34 | Previous 35 | 36 | } 37 | title={<>« {metadata.previous.title}} 38 | /> 39 | )} 40 | 41 | 42 | {metadata.next && ( 43 | 50 | Next 51 | 52 | } 53 | title={<>{metadata.next.title} »} 54 | /> 55 | )} 56 | 57 | 58 | ); 59 | } 60 | 61 | export default DocPaginator; 62 | -------------------------------------------------------------------------------- /src/theme/DocSidebar/styles.module.css: -------------------------------------------------------------------------------- 1 | .menuLinkExternal { 2 | align-items: center; 3 | } 4 | .menuLinkExternal:after { 5 | content: ""; 6 | height: 1.15rem; 7 | width: 1.15rem; 8 | min-width: 1.15rem; 9 | margin: 0 auto 0 3%; 10 | background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24'%3E%3Cpath fill='rgba(0,0,0,0.5)' d='M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z'/%3E%3C/svg%3E") 11 | no-repeat; 12 | filter: var(--ifm-menu-link-sublist-icon-filter); 13 | } 14 | -------------------------------------------------------------------------------- /src/theme/DocVersionBanner/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React, { ComponentType } from "react"; 9 | import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; 10 | import Link from "@docusaurus/Link"; 11 | import Translate from "@docusaurus/Translate"; 12 | import { 13 | useActivePlugin, 14 | useDocVersionSuggestions, 15 | } from "@theme/hooks/useDocs"; 16 | import { useDocsPreferredVersion } from "@docusaurus/theme-common"; 17 | 18 | import type { Props } from "@theme/DocVersionBanner"; 19 | 20 | type BannerLabelComponentProps = { 21 | siteTitle: string; 22 | versionMetadata: Props["versionMetadata"]; 23 | }; 24 | 25 | function UnreleasedVersionLabel({ 26 | siteTitle, 27 | versionMetadata, 28 | }: BannerLabelComponentProps) { 29 | return ( 30 | {versionMetadata.label}, 36 | }} 37 | > 38 | { 39 | "This is unreleased documentation for {siteTitle} {versionLabel} version." 40 | } 41 | 42 | ); 43 | } 44 | 45 | function UnmaintainedVersionLabel({ 46 | siteTitle, 47 | versionMetadata, 48 | }: BannerLabelComponentProps) { 49 | return ( 50 | {versionMetadata.label}, 56 | }} 57 | > 58 | { 59 | "This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained." 60 | } 61 | 62 | ); 63 | } 64 | 65 | const BannerLabelComponents: Record< 66 | Exclude, 67 | ComponentType 68 | > = { 69 | unreleased: UnreleasedVersionLabel, 70 | unmaintained: UnmaintainedVersionLabel, 71 | }; 72 | 73 | function BannerLabel(props: BannerLabelComponentProps) { 74 | const BannerLabelComponent = 75 | BannerLabelComponents[props.versionMetadata.banner]; 76 | return ; 77 | } 78 | 79 | function LatestVersionSuggestionLabel({ 80 | versionLabel, 81 | to, 82 | onClick, 83 | }: { 84 | to: string; 85 | onClick: () => void; 86 | versionLabel: string; 87 | }) { 88 | return ( 89 | 96 | 101 | 105 | latest version 106 | 107 | 108 | 109 | ), 110 | }} 111 | > 112 | { 113 | "For up-to-date documentation, see the {latestVersionLink} ({versionLabel})." 114 | } 115 | 116 | ); 117 | } 118 | 119 | function DocVersionBannerEnabled({ versionMetadata }: Props): JSX.Element { 120 | const { 121 | siteConfig: { title: siteTitle }, 122 | } = useDocusaurusContext(); 123 | const { pluginId } = useActivePlugin({ failfast: true })!; 124 | 125 | const getVersionMainDoc = (version: any) => 126 | version.docs.find((doc) => doc.id === version.mainDocId)!; 127 | 128 | const { savePreferredVersionName } = useDocsPreferredVersion(pluginId); 129 | 130 | const { latestDocSuggestion, latestVersionSuggestion } = 131 | useDocVersionSuggestions(pluginId); 132 | 133 | // try to link to same doc in latest version (not always possible) 134 | // fallback to main doc of latest version 135 | const latestVersionSuggestedDoc = 136 | latestDocSuggestion ?? getVersionMainDoc(latestVersionSuggestion); 137 | 138 | return ( 139 |
140 |
141 | 142 |
143 |
144 | savePreferredVersionName(latestVersionSuggestion.name)} 148 | /> 149 |
150 |
151 | ); 152 | } 153 | 154 | function DocVersionBanner({ versionMetadata }: Props): JSX.Element { 155 | if (versionMetadata.banner === "none") { 156 | return <>; 157 | } else { 158 | return ; 159 | } 160 | } 161 | 162 | export default DocVersionBanner; 163 | -------------------------------------------------------------------------------- /src/theme/EditThisPage/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react'; 9 | import Translate from '@docusaurus/Translate'; 10 | 11 | import type {Props} from '@theme/EditThisPage'; 12 | import IconEdit from '@theme/IconEdit'; 13 | 14 | export default function EditThisPage({editUrl}: Props): JSX.Element { 15 | return ( 16 |
17 | 18 | 21 | Edit this page 22 | 23 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /src/theme/Footer/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from "react"; 9 | import clsx from "clsx"; 10 | 11 | import Link from "@docusaurus/Link"; 12 | import { FooterLinkItem, useThemeConfig } from "@docusaurus/theme-common"; 13 | import useBaseUrl from "@docusaurus/useBaseUrl"; 14 | import ThemedImage, { Props as ThemedImageProps } from "@theme/ThemedImage"; 15 | 16 | function FooterLink({ 17 | to, 18 | href, 19 | label, 20 | prependBaseUrlToHref, 21 | ...props 22 | }: FooterLinkItem) { 23 | const toUrl = useBaseUrl(to); 24 | const normalizedHref = useBaseUrl(href, { forcePrependBaseUrl: true }); 25 | 26 | return ( 27 | 38 | {label} 39 | 40 | ); 41 | } 42 | 43 | const FooterLogo = ({ 44 | sources, 45 | alt, 46 | }: Pick) => ( 47 | 48 | ); 49 | 50 | function Footer(): JSX.Element | null { 51 | const { footer } = useThemeConfig(); 52 | 53 | const { copyright, links = [], logo = {} } = footer || {}; 54 | const sources = { 55 | light: useBaseUrl(logo.src), 56 | dark: useBaseUrl(logo.srcDark || logo.src), 57 | }; 58 | 59 | if (!footer) { 60 | return null; 61 | } 62 | 63 | return ( 64 |
72 |
73 | {links && links.length > 0 && ( 74 |
75 | {links.map((linkItem, i) => ( 76 |
77 | {linkItem.title != null ? ( 78 |

{linkItem.title}

79 | ) : null} 80 | {linkItem.items != null && 81 | Array.isArray(linkItem.items) && 82 | linkItem.items.length > 0 ? ( 83 |
    84 | {linkItem.items.map((item, key) => 85 | item.html ? ( 86 |
  • 94 | ) : ( 95 |
  • 96 | 97 |
  • 98 | ) 99 | )} 100 |
101 | ) : null} 102 |
103 | ))} 104 |
105 | )} 106 | {(logo || copyright) && ( 107 |
108 | {logo && (logo.src || logo.srcDark) && ( 109 |
110 | {logo.href ? ( 111 | 115 | 116 | 117 | ) : ( 118 | 119 | )} 120 |
121 | )} 122 | {copyright ? ( 123 |
130 | ) : null} 131 |
132 | )} 133 |
134 |
135 | ); 136 | } 137 | 138 | export default Footer; 139 | -------------------------------------------------------------------------------- /src/theme/Heading/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /* eslint-disable jsx-a11y/anchor-has-content, jsx-a11y/anchor-is-valid */ 9 | 10 | import React from 'react'; 11 | import clsx from 'clsx'; 12 | import type {HeadingType, Props} from '@theme/Heading'; 13 | import {translate} from '@docusaurus/Translate'; 14 | import {useThemeConfig} from '@docusaurus/theme-common'; 15 | 16 | import './styles.css'; 17 | import styles from './styles.module.css'; 18 | 19 | const Heading = (Tag: HeadingType): ((props: Props) => JSX.Element) => 20 | function TargetComponent({id, ...props}) { 21 | const { 22 | navbar: {hideOnScroll}, 23 | } = useThemeConfig(); 24 | 25 | if (!id) { 26 | return ; 27 | } 28 | 29 | return ( 30 | 31 | 48 | # 49 | 50 | 51 | ); 52 | }; 53 | 54 | export default Heading; 55 | -------------------------------------------------------------------------------- /src/theme/Heading/styles.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | .anchor { 9 | display: block; 10 | position: relative; 11 | top: -0.5rem; 12 | } 13 | 14 | .hash-link { 15 | opacity: 0; 16 | padding-left: 0.5rem; 17 | transition: opacity var(--ifm-transition-fast); 18 | } 19 | 20 | .hash-link:focus, 21 | *:hover > .hash-link { 22 | opacity: 1; 23 | } 24 | -------------------------------------------------------------------------------- /src/theme/Heading/styles.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | .enhancedAnchor { 9 | top: calc(var(--ifm-navbar-height) * -1 - 0.5rem); 10 | } 11 | -------------------------------------------------------------------------------- /src/theme/IconArrow/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react'; 9 | import type {Props} from '@theme/IconArrow'; 10 | 11 | const IconArrow = (props: Props): JSX.Element => { 12 | return ( 13 | 14 | 15 | 16 | 17 | 18 | 19 | ); 20 | }; 21 | 22 | export default IconArrow; 23 | -------------------------------------------------------------------------------- /src/theme/IconEdit/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from "react"; 9 | import clsx from "clsx"; 10 | 11 | import type { Props } from "@theme/IconEdit"; 12 | 13 | import styles from "./styles.module.css"; 14 | 15 | const IconEdit = ({ className, ...restProps }: Props): JSX.Element => { 16 | return ( 17 | 28 | 29 | 30 | 31 | 32 | ); 33 | }; 34 | 35 | export default IconEdit; 36 | -------------------------------------------------------------------------------- /src/theme/IconEdit/styles.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | .iconEdit { 9 | margin-right: 0.3em; 10 | vertical-align: sub; 11 | } 12 | -------------------------------------------------------------------------------- /src/theme/IconLanguage/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react'; 9 | import type {Props} from '@theme/IconLanguage'; 10 | 11 | const IconLanguage = ({ 12 | width = 20, 13 | height = 20, 14 | ...props 15 | }: Props): JSX.Element => { 16 | return ( 17 | 23 | 27 | 28 | ); 29 | }; 30 | 31 | export default IconLanguage; 32 | -------------------------------------------------------------------------------- /src/theme/IconMenu/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react'; 9 | import type {Props} from '@theme/IconMenu'; 10 | 11 | const IconMenu = ({ 12 | width = 30, 13 | height = 30, 14 | className, 15 | ...restProps 16 | }: Props): JSX.Element => { 17 | return ( 18 | 27 | Menu 28 | 35 | 36 | ); 37 | }; 38 | 39 | export default IconMenu; 40 | -------------------------------------------------------------------------------- /src/theme/LastUpdated/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react'; 9 | import styles from './styles.module.css'; 10 | import Translate from '@docusaurus/Translate'; 11 | import type {Props} from '@theme/LastUpdated'; 12 | 13 | function LastUpdatedAtDate({ 14 | lastUpdatedAt, 15 | formattedLastUpdatedAt, 16 | }: { 17 | lastUpdatedAt: number; 18 | formattedLastUpdatedAt: string; 19 | }): JSX.Element { 20 | return ( 21 | 29 | {formattedLastUpdatedAt} 30 | 31 | ), 32 | }}> 33 | {' on {date}'} 34 | 35 | ); 36 | } 37 | 38 | function LastUpdatedByUser({ 39 | lastUpdatedBy, 40 | }: { 41 | lastUpdatedBy: string; 42 | }): JSX.Element { 43 | return ( 44 | {lastUpdatedBy}, 49 | }}> 50 | {' by {user}'} 51 | 52 | ); 53 | } 54 | 55 | export default function LastUpdated({ 56 | lastUpdatedAt, 57 | formattedLastUpdatedAt, 58 | lastUpdatedBy, 59 | }: Props): JSX.Element { 60 | return ( 61 |
62 | 63 | 64 | 74 | ) : ( 75 | '' 76 | ), 77 | byUser: lastUpdatedBy ? ( 78 | 79 | ) : ( 80 | '' 81 | ), 82 | }}> 83 | {'Last updated{atDate}{byUser}'} 84 | 85 | {process.env.NODE_ENV === 'development' && ( 86 |
87 | (Simulated during dev for better perf) 88 |
89 | )} 90 |
91 |
92 |
93 | ); 94 | } 95 | -------------------------------------------------------------------------------- /src/theme/LastUpdated/styles.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | .lastUpdatedDate { 9 | font-weight: bold; 10 | } 11 | -------------------------------------------------------------------------------- /src/theme/Layout/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react'; 9 | import clsx from 'clsx'; 10 | import SkipToContent from '@theme/SkipToContent'; 11 | import AnnouncementBar from '@theme/AnnouncementBar'; 12 | import Navbar from '@theme/Navbar'; 13 | import Footer from '@theme/Footer'; 14 | import LayoutProviders from '@theme/LayoutProviders'; 15 | import LayoutHead from '@theme/LayoutHead'; 16 | import type {Props} from '@theme/Layout'; 17 | import useKeyboardNavigation from '@theme/hooks/useKeyboardNavigation'; 18 | import {ThemeClassNames} from '@docusaurus/theme-common'; 19 | import './styles.css'; 20 | 21 | function Layout(props: Props): JSX.Element { 22 | const {children, noFooter, wrapperClassName, pageClassName} = props; 23 | 24 | useKeyboardNavigation(); 25 | 26 | return ( 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
42 | {children} 43 |
44 | 45 | {!noFooter &&