├── workers-site ├── .cargo-ok ├── .gitignore ├── package.json ├── index.js └── package-lock.json ├── .github ├── CODEOWNERS └── workflows │ └── semgrep.yml ├── .prettierignore ├── src ├── constants │ └── sidebar-collapse-transition-duration.js ├── images │ └── cloudflare-icon.png ├── components │ ├── mdx │ │ ├── root.js │ │ ├── code.js │ │ ├── inline-code.js │ │ ├── param-type.js │ │ ├── type.js │ │ ├── example.js │ │ ├── prop-meta.js │ │ ├── definitions.js │ │ ├── content-column.js │ │ ├── button-group.js │ │ ├── table-wrap.js │ │ ├── type-link.js │ │ ├── aside.js │ │ ├── headers.js │ │ ├── button.js │ │ ├── youtube.js │ │ ├── stream-video.js │ │ ├── demo.js │ │ ├── directory-listing.js │ │ ├── custom-syntax-highlighting.js │ │ ├── anchor-link.js │ │ └── code-block.js │ ├── docs-title.js │ ├── code-block.js │ ├── handle-mobile-page-navigations.js │ ├── docs-sidebar.js │ ├── docs-product-logo.js │ ├── accessible-svg.js │ ├── icons │ │ ├── external-link.js │ │ ├── base.js │ │ └── nav-menu.js │ ├── docs-mobile-header.js │ ├── docs-sidebar-header-section.js │ ├── docs-nav-logo-lockup.js │ ├── docs-sidebar-title-section.js │ ├── browser-resize-tracking.js │ ├── docs-mobile-title-header.js │ ├── docs-table-of-contents.js │ ├── cloudflare-logo.js │ ├── worker-starter.js │ ├── docs-sidebar-nav-data.js │ ├── docs-footer.js │ ├── breadcrumbs.js │ ├── docs-sidebar-more-dropdown.js │ ├── scrollbars-with-scroll-shadows.js │ ├── docs-sidebar-nav.js │ ├── seo.js │ ├── mdx-custom-renderer.js │ ├── smooth-scroll-hash-changes.js │ ├── docs-toolbar.js │ ├── dropdown.js │ ├── docs-sidebar-nav-section.js │ ├── docs-tutorials.js │ ├── docs-page.js │ ├── docs-code-examples-overview.js │ ├── docs-sidebar-nav-item.js │ ├── docs-search.js │ ├── theme-toggle.js │ └── architecture-diagram.js ├── utils │ ├── get-normalized-path.js │ ├── get-unique-readable-id.js │ ├── get-page-type.js │ ├── is-mobile.js │ ├── get-pxc-content-type.js │ ├── has-breadcrumbs.js │ ├── get-parent-path.js │ ├── get-table-of-contents.js │ ├── user-prefers-reduced-motion.js │ ├── get-page-by-path.js │ ├── get-order.js │ ├── get-page-title.js │ ├── animate.js │ ├── google-analytics.js │ ├── mobile-sidebar-manipulation.js │ ├── get-path-prefix.js │ ├── get-breadcrumbs.js │ ├── get-cloudflare-docs-config.js │ └── generate-nav-tree.js ├── css │ └── docs │ │ └── components │ │ ├── docs-noscript.css │ │ ├── docs-mobile-nav-backdrop.css │ │ ├── skip-nav-link.css │ │ ├── tags-filter.css │ │ ├── docs-footer.css │ │ ├── docs-content.css │ │ ├── docs-mobile-header.css │ │ ├── docs-table-of-contents.css │ │ ├── docs-nav-logo-lockup.css │ │ ├── docs-body.css │ │ ├── docs-toolbar.css │ │ ├── worker-starter.css │ │ ├── docs-page.css │ │ ├── docs-mobile-title-header.css │ │ ├── docs-code-examples-overview.css │ │ ├── docs-tutorials.css │ │ ├── architecture-diagram.css │ │ ├── docs-search.css │ │ └── docs-sidebar.css ├── pages │ └── 404.js └── html.js ├── .prettierrc ├── gatsby-ssr.js ├── .eslintrc.js ├── README.md ├── LICENSE-MIT ├── .gitignore ├── bin ├── postbuild.js └── commands.sh ├── package.json ├── gatsby-browser.js ├── gatsby-node.js ├── gatsby-config.js └── LICENSE-APACHE /workers-site/.cargo-ok: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | src/ @adamschwartz 2 | -------------------------------------------------------------------------------- /workers-site/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | worker 3 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .cache 2 | package.json 3 | package-lock.json 4 | public 5 | -------------------------------------------------------------------------------- /src/constants/sidebar-collapse-transition-duration.js: -------------------------------------------------------------------------------- 1 | export default 400 2 | -------------------------------------------------------------------------------- /src/images/cloudflare-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudflare/cloudflare-docs-engine/master/src/images/cloudflare-icon.png -------------------------------------------------------------------------------- /src/components/mdx/root.js: -------------------------------------------------------------------------------- 1 | const prefix = "DocsMarkdown" 2 | export const className = suffix => !suffix ? prefix : `${prefix}--${suffix}` 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "semi": false, 4 | "singleQuote": false, 5 | "tabWidth": 2, 6 | "trailingComma": "es5" 7 | } 8 | -------------------------------------------------------------------------------- /src/utils/get-normalized-path.js: -------------------------------------------------------------------------------- 1 | export default path => { 2 | if (path === "/") return path 3 | 4 | return path.replace(/\/$/, "") 5 | } 6 | -------------------------------------------------------------------------------- /src/utils/get-unique-readable-id.js: -------------------------------------------------------------------------------- 1 | const random = () => Math.random().toString().split('.')[1] 2 | 3 | export default prefix => `${prefix}-${random()}` 4 | -------------------------------------------------------------------------------- /src/utils/get-page-type.js: -------------------------------------------------------------------------------- 1 | export default ({ frontmatter }) => { 2 | if (!frontmatter) return "error" 3 | 4 | return frontmatter.type || "document" 5 | } 6 | -------------------------------------------------------------------------------- /src/utils/is-mobile.js: -------------------------------------------------------------------------------- 1 | export default () => { 2 | if (typeof window === "undefined") return false 3 | return matchMedia("(max-width: 768px)").matches 4 | } 5 | -------------------------------------------------------------------------------- /src/components/mdx/code.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | export default props => ( 4 | 5 | {props.children} 6 | 7 | ) 8 | -------------------------------------------------------------------------------- /src/utils/get-pxc-content-type.js: -------------------------------------------------------------------------------- 1 | export default ({ frontmatter }) => { 2 | if (!frontmatter) return "error" 3 | 4 | return frontmatter.pcx_content_type || "" 5 | } 6 | -------------------------------------------------------------------------------- /src/components/mdx/inline-code.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | export default props => ( 4 | 5 | {props.children} 6 | 7 | ) 8 | -------------------------------------------------------------------------------- /src/utils/has-breadcrumbs.js: -------------------------------------------------------------------------------- 1 | export default ({ frontmatter }) => { 2 | if (frontmatter && frontmatter.breadcrumbs === false) 3 | return false 4 | 5 | return true 6 | } 7 | -------------------------------------------------------------------------------- /src/components/mdx/param-type.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | export default props => ( 4 | 5 | {props.children} 6 | 7 | ) 8 | -------------------------------------------------------------------------------- /src/utils/get-parent-path.js: -------------------------------------------------------------------------------- 1 | import getNormalizedPath from "./get-normalized-path" 2 | 3 | export default path => { 4 | return getNormalizedPath(path).replace(/\/[^/]*$/, '') 5 | } 6 | -------------------------------------------------------------------------------- /src/components/docs-title.js: -------------------------------------------------------------------------------- 1 | import getCloudflareDocsConfig from "../utils/get-cloudflare-docs-config" 2 | 3 | export default () => { 4 | return getCloudflareDocsConfig().product 5 | } 6 | -------------------------------------------------------------------------------- /src/components/mdx/type.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | export default props => ( 4 | 5 | {props.children} 6 | 7 | ) 8 | -------------------------------------------------------------------------------- /src/utils/get-table-of-contents.js: -------------------------------------------------------------------------------- 1 | export default ({ tableOfContents: toc }) => { 2 | if (!toc || !toc.items || !toc.items.length) 3 | return [] 4 | 5 | return toc.items[0].items 6 | } 7 | -------------------------------------------------------------------------------- /src/utils/user-prefers-reduced-motion.js: -------------------------------------------------------------------------------- 1 | export default () => { 2 | if (typeof window === "undefined") return false 3 | return matchMedia("(prefers-reduced-motion: reduce)").matches 4 | } 5 | -------------------------------------------------------------------------------- /gatsby-ssr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's SSR (Server Side Rendering) APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/ssr-apis/ 5 | */ 6 | 7 | // You can delete this file if you're not using it 8 | -------------------------------------------------------------------------------- /src/components/mdx/example.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | import { className } from "./root" 4 | 5 | export default props => ( 6 |
7 | {props.children} 8 |
9 | ) 10 | -------------------------------------------------------------------------------- /src/components/mdx/prop-meta.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | import { className } from "./root" 4 | 5 | export default props => ( 6 | 7 | {props.children} 8 | 9 | ) 10 | -------------------------------------------------------------------------------- /src/components/mdx/definitions.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | import { className } from "./root" 4 | 5 | export default props => ( 6 |
7 | {props.children} 8 |
9 | ) 10 | -------------------------------------------------------------------------------- /src/components/mdx/content-column.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | import { className } from "./root" 4 | 5 | export default props => ( 6 |
7 | {props.children} 8 |
9 | ) 10 | -------------------------------------------------------------------------------- /src/utils/get-page-by-path.js: -------------------------------------------------------------------------------- 1 | import getNormalizedPath from "./get-normalized-path" 2 | 3 | export default (pages, path) => ( 4 | pages.find(page => ( 5 | getNormalizedPath(page.fields.slug) === 6 | getNormalizedPath(path) 7 | )) 8 | ) 9 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | globals: { 3 | __PATH_PREFIX__: true, 4 | }, 5 | extends: `react-app`, 6 | "rules": { 7 | /* Don’t require for proxy elements in https://github.com/nfl/react-helmet */ 8 | "jsx-a11y/html-has-lang": 0 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/components/mdx/button-group.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { className } from "./root" 3 | 4 | export default props => ( 5 |

6 | 7 | {props.children} 8 | 9 |

10 | ) 11 | -------------------------------------------------------------------------------- /src/components/mdx/table-wrap.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | import { className } from "./root" 4 | 5 | export default props => ( 6 |
7 |
8 | {props.children} 9 |
10 |
11 | ) 12 | -------------------------------------------------------------------------------- /src/css/docs/components/docs-noscript.css: -------------------------------------------------------------------------------- 1 | .DocsNoscript { 2 | position: fixed; 3 | top: 0; 4 | left: 50%; 5 | transform: translate3d(-50%, 0, 0); 6 | font-size: .8em; 7 | padding: .5em 1em; 8 | background: rgba(var(--orange-rgb), .15); 9 | border-radius: 0 0 .25em .25em; 10 | z-index: 100; 11 | } 12 | -------------------------------------------------------------------------------- /src/components/mdx/type-link.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import AnchorLink from "./anchor-link" 3 | 4 | export default props => ( 5 | 6 | 7 | {props.children} 8 | 9 | 10 | ) 11 | -------------------------------------------------------------------------------- /src/utils/get-order.js: -------------------------------------------------------------------------------- 1 | export default ({ frontmatter }) => { 2 | if (frontmatter && (frontmatter.order || frontmatter.order === 0)) { 3 | return frontmatter.order 4 | } 5 | 6 | // Use a large number instead of `Infinity` to be able to 7 | // use subtraction-based sort comparison method 8 | return 10e6 9 | } 10 | -------------------------------------------------------------------------------- /src/utils/get-page-title.js: -------------------------------------------------------------------------------- 1 | export default ({ frontmatter, headings }, useHeading=false) => { 2 | if (!frontmatter) return "Not found" 3 | 4 | if (useHeading) { 5 | return (headings.length && headings[0].value) || frontmatter.title 6 | } 7 | 8 | return frontmatter.title || (headings.length && headings[0].value) 9 | } 10 | -------------------------------------------------------------------------------- /src/components/code-block.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | import MDXCodeBlock from "./mdx/code-block" 4 | 5 | const CodeBlock = props => { 6 | return ( 7 | 8 | 9 | {props.children} 10 | 11 | 12 | ) 13 | } 14 | 15 | export default CodeBlock 16 | -------------------------------------------------------------------------------- /src/utils/animate.js: -------------------------------------------------------------------------------- 1 | import anime from "animejs/lib/anime.es.js" 2 | 3 | export default options => { 4 | const obj = { 5 | objProperty: options.from 6 | } 7 | 8 | anime({ 9 | targets: obj, 10 | objProperty: options.to, 11 | easing: options.easing, 12 | duration: options.duration, 13 | update: () => options.update(obj.objProperty) 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /workers-site/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "worker", 4 | "version": "1.0.0", 5 | "description": "A template for kick starting a Cloudflare Workers project", 6 | "main": "index.js", 7 | "author": "Cloudflare ", 8 | "license": "MIT", 9 | "dependencies": { 10 | "@cloudflare/kv-asset-handler": "^0.0.12", 11 | "lilredirector": "^0.5.1", 12 | "workers-google-analytics": "0.0.3" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/utils/google-analytics.js: -------------------------------------------------------------------------------- 1 | export default `const GA_ID = "UA-107218623-2" 2 | window.ga = 3 | window.ga || 4 | function () { 5 | if (!GA_ID) { 6 | return 7 | } 8 | ;(ga.q = ga.q || []).push(arguments) 9 | } 10 | ga.l = +new Date() 11 | ga('create', GA_ID, 'auto') 12 | ga('set', 'transport', 'beacon') 13 | var timeout = setTimeout( 14 | (onload = function () { 15 | clearTimeout(timeout) 16 | ga('send', 'pageview') 17 | }), 18 | 1000, 19 | )` 20 | -------------------------------------------------------------------------------- /src/components/mdx/aside.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | import { className } from "./root" 4 | 5 | const Aside = props => ( 6 | 14 | ) 15 | 16 | Aside.defaultProps = { 17 | type: "note" 18 | } 19 | 20 | export default Aside 21 | -------------------------------------------------------------------------------- /src/pages/404.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | import AnchorLink from "../components/mdx/anchor-link" 4 | import SEO from "../components/seo" 5 | 6 | import DocsTitle from "../components/docs-title" 7 | 8 | const NotFoundPage = () => ( 9 | <> 10 | 11 |

Not found

12 |

Unfortunately, the page you requested cannot be found.

13 |

Go to docs home

14 | 15 | ) 16 | 17 | export default NotFoundPage 18 | -------------------------------------------------------------------------------- /src/utils/mobile-sidebar-manipulation.js: -------------------------------------------------------------------------------- 1 | const attr = "is-mobile-sidebar-open" 2 | 3 | export const sidebarIsOpen = () => { 4 | return document.documentElement.hasAttribute(attr) 5 | } 6 | 7 | export const sidebarOpen = () => { 8 | document.documentElement.setAttribute(attr, "") 9 | } 10 | 11 | export const sidebarClose = () => { 12 | document.documentElement.removeAttribute(attr) 13 | } 14 | 15 | export const sidebarToggle = () => { 16 | if (sidebarIsOpen()) return sidebarClose() 17 | sidebarOpen() 18 | } 19 | -------------------------------------------------------------------------------- /src/css/docs/components/docs-mobile-nav-backdrop.css: -------------------------------------------------------------------------------- 1 | .DocsMobileNavBackdrop { 2 | position: fixed; 3 | top: 0; 4 | right: 0; 5 | bottom: 0; 6 | left: 0; 7 | opacity: 0; 8 | pointer-events: none; 9 | background: rgba(var(--shadow-color-rgb), .5); 10 | will-change: opacity; 11 | transition: opacity .3s ease; 12 | z-index: 8; 13 | } 14 | 15 | @media (min-width: 769px) { 16 | .DocsMobileNavBackdrop { 17 | display: none; 18 | } 19 | } 20 | 21 | [is-mobile-sidebar-open] .DocsMobileNavBackdrop { 22 | opacity: 1; 23 | pointer-events: all; 24 | } 25 | -------------------------------------------------------------------------------- /src/components/handle-mobile-page-navigations.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { globalHistory } from "@reach/router" 3 | 4 | import { sidebarClose } from "../utils/mobile-sidebar-manipulation" 5 | 6 | class HandleMobilePageNavigations extends React.Component { 7 | 8 | componentDidMount() { 9 | this.historyUnsubscribe = globalHistory.listen(() => sidebarClose()) 10 | } 11 | 12 | componentWillUnmount() { 13 | this.historyUnsubscribe() 14 | } 15 | 16 | render() { 17 | return null 18 | } 19 | } 20 | 21 | export default HandleMobilePageNavigations 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cloudflare Docs Engine 2 | 3 | Cloudflare’s open-source tool for building documentation. 4 | 5 | https://developers.cloudflare.com/docs-engine 6 | 7 | ## Known issues 8 | 9 | - [@gatsbyjs/gatsby#17506](https://github.com/gatsbyjs/gatsby/issues/17506) Console warning about `lazy=load` images missing dimensions. This is a known issue in Gatsby and the [recommendation as of Sept, 2019](https://github.com/gatsbyjs/gatsby/issues/17506#issuecomment-529904482) is to ignore it. 10 | - Hard page loads with hashes don’t start scrolled when developing locally (e.g. `http://localhost:8000/#docs-content`). 11 | -------------------------------------------------------------------------------- /src/css/docs/components/skip-nav-link.css: -------------------------------------------------------------------------------- 1 | .SkipNavLink { 2 | position: absolute; 3 | overflow: hidden; 4 | color: inherit; 5 | text-decoration: none; 6 | clip: rect(0 0 0 0); 7 | height: 1px; 8 | width: 1px; 9 | margin: -1px; 10 | padding: 0; 11 | } 12 | 13 | .SkipNavLink:focus { 14 | padding: .5em 1em; 15 | position: fixed; 16 | top: 0; 17 | left: 50%; 18 | transform: translate3d(-50%, 0, 0); 19 | background: var(--background-color); 20 | width: auto; 21 | height: auto; 22 | clip: auto; 23 | z-index: 100; 24 | outline: none; 25 | box-shadow: 0 0 0 var(--focus-size) var(--focus-color); 26 | } 27 | -------------------------------------------------------------------------------- /src/css/docs/components/tags-filter.css: -------------------------------------------------------------------------------- 1 | .TagsFilter { 2 | display: flex; 3 | flex-wrap: wrap; 4 | margin: 0 -.25em; 5 | } 6 | 7 | .TagsFilter--button { 8 | --border-color: rgba(var(--color-rgb), .2); 9 | padding: .25em .3125em; 10 | margin: .3125em .25em; 11 | border-radius: .125em; 12 | } 13 | 14 | .TagsFilter--button[is-focus-visible] { 15 | --border-color: rgba(var(--orange-rgb), .7); 16 | } 17 | 18 | .TagsFilter--button-active { 19 | pointer-events: none; 20 | } 21 | 22 | [theme="light"] .TagsFilter--button-active { 23 | --border-color: transparent; 24 | } 25 | 26 | [theme="dark"] .TagsFilter--button-active { 27 | color: var(--code-orange); 28 | } 29 | -------------------------------------------------------------------------------- /src/components/mdx/headers.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | import { className } from "./root" 4 | 5 | const header = (TagName) => (props => { 6 | const href = `#${ props.id }` 7 | 8 | return ( 9 | 10 | 11 | 12 | 13 | {props.children} 14 | 15 | ) 16 | }) 17 | 18 | export default { 19 | h2: header('h2'), 20 | h3: header('h3'), 21 | h4: header('h4'), 22 | h5: header('h5'), 23 | h6: header('h6'), 24 | } 25 | -------------------------------------------------------------------------------- /src/components/docs-sidebar.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | import DocsSidebarHeaderSection from "./docs-sidebar-header-section" 4 | import DocsSidebarTitleSection from "./docs-sidebar-title-section" 5 | import DocsSidebarNavSection from "./docs-sidebar-nav-section" 6 | 7 | const DocsSidebar = () => ( 8 |
9 |
10 | 11 |
12 | 13 | 14 |
15 | 16 |
17 |
18 | ) 19 | 20 | export default DocsSidebar 21 | -------------------------------------------------------------------------------- /src/components/docs-product-logo.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import getCloudflareDocsConfig from "../utils/get-cloudflare-docs-config" 3 | import AccessibleSVG from "./accessible-svg" 4 | 5 | 6 | export default () => { 7 | const { product, productLogoPathD, productIconKey, logoSVGContent } = getCloudflareDocsConfig() 8 | 9 | return logoSVGContent ? ( 10 | 14 | ) : ( 15 | 16 | 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /.github/workflows/semgrep.yml: -------------------------------------------------------------------------------- 1 | 2 | on: 3 | pull_request: {} 4 | workflow_dispatch: {} 5 | push: 6 | branches: 7 | - main 8 | - master 9 | schedule: 10 | - cron: '0 0 * * *' 11 | name: Semgrep config 12 | jobs: 13 | semgrep: 14 | name: semgrep/ci 15 | runs-on: ubuntu-20.04 16 | env: 17 | SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} 18 | SEMGREP_URL: https://cloudflare.semgrep.dev 19 | SEMGREP_APP_URL: https://cloudflare.semgrep.dev 20 | SEMGREP_VERSION_CHECK_URL: https://cloudflare.semgrep.dev/api/check-version 21 | container: 22 | image: returntocorp/semgrep 23 | steps: 24 | - uses: actions/checkout@v3 25 | - run: semgrep ci 26 | -------------------------------------------------------------------------------- /src/components/accessible-svg.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | import getUniqueReadableID from "../utils/get-unique-readable-id" 5 | 6 | const AccessibleSVG = props => { 7 | const titleID = getUniqueReadableID("title") 8 | const { title, children, ...svgProps } = props 9 | 10 | return ( 11 | 12 | {title} 13 | {children} 14 | 15 | ) 16 | } 17 | 18 | AccessibleSVG.defaultProps = { 19 | fill: "currentColor", 20 | role: "img" 21 | } 22 | 23 | AccessibleSVG.propTypes = { 24 | title: PropTypes.string.isRequired 25 | } 26 | 27 | export default AccessibleSVG 28 | -------------------------------------------------------------------------------- /src/utils/get-path-prefix.js: -------------------------------------------------------------------------------- 1 | import { withPrefix } from "gatsby" 2 | 3 | // Gatsby’s `` component automatically applies the 4 | // `pathPrefix` set in gatsby-config.js. However when 5 | // constructing URLs manually, it can be useful to have 6 | // direct access to the `pathPrefix`. Gatsby offers a 7 | // method `withPrefix()` for this purpose, but this still 8 | // doesn’t give you direct access to the value. Here, we 9 | // "trick" `withPrefix` to giving us the value by passing 10 | // in "/" and then trimming the "/" off of the end. Sadly 11 | // you can’t just call `withPrefix("")` because that 12 | // somewhat surprisingly returns "". 13 | // See: https://www.gatsbyjs.com/docs/path-prefix/ 14 | export default () => withPrefix("/").slice(0, -1) 15 | -------------------------------------------------------------------------------- /src/components/mdx/button.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import AnchorLink from "./anchor-link" 3 | 4 | export default ({ type, href, children, ...props }) => { 5 | let className = "Button" 6 | 7 | if (type === "primary") { 8 | className += " Button-is-docs-primary" 9 | } else if (type === "secondary") { 10 | className += " Button-is-docs-secondary" 11 | } 12 | 13 | if (props.className) { 14 | className += ` ${props.className}` 15 | } 16 | 17 | if (href) { 18 | return ( 19 | 20 | {children} 21 | 22 | ) 23 | } 24 | 25 | return ( 26 | 29 | ) 30 | } 31 | -------------------------------------------------------------------------------- /src/components/mdx/youtube.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | const defaultAspectRatio = 16 / 9 4 | 5 | export default props => { 6 | const style = { 7 | "--aspect-ratio": `calc(${ props.aspectRatio || defaultAspectRatio })` 8 | } 9 | 10 | return ( 11 |
12 |
13 |