Setting up accessibility linting (#433)

* Adding required packages and configurations * Fixes done by npm run lintfix * Linti errors fixed by disabling some rules * Fixing lint errors manually * Addressing comment

20shivangi committed Feb 8, 2023 at 10:11 UTC 43ece07c151fd25e78c956d8650897e5d59b2c17
64 files changed +532 -686
package-lock.json
+17 -8
@@ -2631,6 +2631,12 @@
2631 "resolved": "https://registry.npmjs.org/@github/paste-markdown/-/paste-markdown-1.4.2.tgz",
2632 "integrity": "sha512-ZwSgPyo9nA6TRngXV0QnFT4e5ujeOGxRDWN2aa6qfimz2o2VOsJ9bFGuGvB723nvzq5z9zKr6JWGtvK7MSJj3w=="
2633 },
2634 + "node_modules/@github/prettier-config": {
2635 + "version": "0.0.6",
2636 + "resolved": "https://registry.npmjs.org/@github/prettier-config/-/prettier-config-0.0.6.tgz",
2637 + "integrity": "sha512-Sdb089z+QbGnFF2NivbDeaJ62ooPlD31wE6Fkb/ESjAOXSjNJo+gjqzYYhlM7G3ERJmKFZRUJYMlsqB7Tym8lQ==",
2638 + "dev": true
2639 + },
2640 "node_modules/@github/relative-time-element": {
2641 "version": "4.1.2",
2642 "resolved": "https://registry.npmjs.org/@github/relative-time-element/-/relative-time-element-4.1.2.tgz",
@@ -12133,9 +12139,9 @@
12139 }
12140 },
12141 "node_modules/eslint": {
12136 - "version": "8.31.0",
12137 - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.31.0.tgz",
12138 - "integrity": "sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA==",
12142 + "version": "8.33.0",
12143 + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.33.0.tgz",
12144 + "integrity": "sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==",
12145 "dependencies": {
12146 "@eslint/eslintrc": "^1.4.1",
12147 "@humanwhocodes/config-array": "^0.11.8",
@@ -24343,9 +24349,9 @@
24349 }
24350 },
24351 "node_modules/prettier": {
24346 - "version": "2.8.1",
24347 - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.1.tgz",
24348 - "integrity": "sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==",
24352 + "version": "2.8.3",
24353 + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz",
24354 + "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==",
24355 "dev": true,
24356 "bin": {
24357 "prettier": "bin-prettier.js"
@@ -32532,15 +32538,18 @@
32538 "styled-system": "^5.1.5"
32539 },
32540 "devDependencies": {
32541 + "@github/prettier-config": "^0.0.6",
32542 "@npmcli/template-oss": "4.11.0",
32543 "@testing-library/jest-dom": "^5.16.5",
32544 "babel-jest": "^29.3.1",
32538 - "eslint": "^8.29.0",
32545 + "eslint": "^8.33.0",
32546 + "eslint-plugin-github": "^4.6.0",
32547 "eslint-plugin-jsx-a11y": "^6.6.1",
32548 "eslint-plugin-primer-react": "1.0.1",
32549 "eslint-plugin-react": "^7.31.11",
32550 "jest": "^29.3.1",
32543 - "jest-environment-jsdom": "^29.3.1"
32551 + "jest-environment-jsdom": "^29.3.1",
32552 + "prettier": "^2.8.3"
32553 },
32554 "engines": {
32555 "node": ">=18.0.0"
theme/.eslintrc.js
+7 -4
@@ -14,8 +14,9 @@ module.exports = {
14 '@npmcli',
15 'eslint:recommended',
16 'plugin:react/recommended',
17 - 'plugin:jsx-a11y/recommended',
17 + 'plugin:github/react',
18 'plugin:primer-react/recommended',
19 + 'prettier',
20 ],
21 settings: {
22 react: {
@@ -28,16 +29,18 @@ module.exports = {
29 'react/display-name': 'off',
30 'eslint-comments/no-use': 'off',
31 'no-shadow': 'off',
31 - 'primer-react/no-system-props': ['warn', { includeUtilityComponents: true }],
32 + 'primer-react/no-system-props': ['warn', {includeUtilityComponents: true}],
33 + 'import/no-commonjs': 'off',
34 + 'no-console': 'off',
35 },
36 overrides: [
37 {
38 files: ['gatsby-node.js', 'gatsby-config.js'],
36 - env: { node: true, browser: false },
39 + env: {node: true, browser: false},
40 },
41 {
42 files: ['test/*', './src/**/__tests__/*'],
40 - env: { jest: true },
43 + env: {jest: true},
44 },
45 ],
46 }
theme/gatsby-browser.js
+2 -2
@@ -1,2 +1,2 @@
1 -export { default as wrapPageElement } from './src/components/wrap-page-element'
2 -export { default as wrapRootElement } from './src/components/wrap-root-element'
1 +export {default as wrapPageElement} from './src/components/wrap-page-element'
2 +export {default as wrapRootElement} from './src/components/wrap-root-element'
theme/gatsby-config.js
+2 -4
@@ -1,6 +1,6 @@
1 const path = require('path')
2
3 -module.exports = (themeOptions) => {
3 +module.exports = themeOptions => {
4 return {
5 plugins: [
6 'gatsby-plugin-styled-components',
@@ -26,9 +26,7 @@ module.exports = (themeOptions) => {
26 {
27 resolve: 'gatsby-plugin-manifest',
28 options: {
29 - icon: themeOptions.icon
30 - ? path.resolve(themeOptions.icon)
31 - : require.resolve('./src/images/favicon.png'),
29 + icon: themeOptions.icon ? path.resolve(themeOptions.icon) : require.resolve('./src/images/favicon.png'),
30 },
31 },
32 ],
theme/gatsby-node.js
+21 -31
@@ -6,7 +6,7 @@ const uniqBy = require('lodash.uniqby')
6
7 const CONTRIBUTOR_CACHE = new Map()
8
9 -exports.createSchemaCustomization = ({ actions: { createTypes } }) => {
9 +exports.createSchemaCustomization = ({actions: {createTypes}}) => {
10 createTypes(`
11 type Mdx implements Node {
12 frontmatter: MdxFrontmatter
@@ -26,10 +26,10 @@ exports.createSchemaCustomization = ({ actions: { createTypes } }) => {
26 `)
27 }
28
29 -exports.createPages = async ({ graphql, actions }, themeOptions) => {
30 - const repo = themeOptions.repo ? themeOptions.repo : { url: getPkgRepo(readPkgUp.sync().package).browse() }
29 +exports.createPages = async ({graphql, actions}, themeOptions) => {
30 + const repo = themeOptions.repo ? themeOptions.repo : {url: getPkgRepo(readPkgUp.sync().package).browse()}
31
32 - const { data } = await graphql(`
32 + const {data} = await graphql(`
33 {
34 allMdx {
35 nodes {
@@ -68,15 +68,9 @@ exports.createPages = async ({ graphql, actions }, themeOptions) => {
68 data.allMdx.nodes.map(async node => {
69 const pagePath = getPath(node)
70
71 - const rootAbsolutePath = path.resolve(
72 - process.cwd(),
73 - themeOptions.repoRootPath || '.'
74 - )
71 + const rootAbsolutePath = path.resolve(process.cwd(), themeOptions.repoRootPath || '.')
72
76 - const fileRelativePath = path.relative(
77 - rootAbsolutePath,
78 - node.fileAbsolutePath
79 - )
73 + const fileRelativePath = path.relative(rootAbsolutePath, node.fileAbsolutePath)
74
75 const editUrl = getEditUrl(themeOptions, repo, fileRelativePath, node.frontmatter)
76
@@ -98,10 +92,10 @@ exports.createPages = async ({ graphql, actions }, themeOptions) => {
92 })
93
94 if (node.frontmatter.redirect_from) {
101 - node.frontmatter.redirect_from.forEach((from) => {
95 + for (const from of node.frontmatter.redirect_from) {
96 actions.createRedirect({
97 fromPath: from,
104 - toPath: '/' + pagePath,
98 + toPath: `/${pagePath}`,
99 isPermanent: true,
100 redirectInBrowser: true,
101 })
@@ -109,18 +103,18 @@ exports.createPages = async ({ graphql, actions }, themeOptions) => {
103 if (pagePath.startsWith('cli/') && !from.endsWith('index')) {
104 actions.createRedirect({
105 fromPath: `${from}.html`,
112 - toPath: '/' + pagePath,
106 + toPath: `/${pagePath}`,
107 isPermanent: true,
108 redirectInBrowser: true,
109 })
110 }
117 - })
111 + }
112 }
119 - })
113 + }),
114 )
115 }
116
123 -function getPath (node) {
117 +function getPath(node) {
118 // sites can programmatically override slug, that takes priority
119 if (node.fields && node.fields.slug) {
120 return node.fields.slug
@@ -132,14 +126,12 @@ function getPath (node) {
126 }
127
128 // finally, we'll just use the path on disk
135 - return path.join(
136 - node.parent.relativeDirectory,
137 - node.parent.name === 'index' ? '/' : node.parent.name
138 - )
129 + return path
130 + .join(node.parent.relativeDirectory, node.parent.name === 'index' ? '/' : node.parent.name)
131 .replace(/\\/g, '/') // Windows paths to forward slashes
132 }
133
142 -function getNameWithOwner (url) {
134 +function getNameWithOwner(url) {
135 const nwo = url.match(/^http(?:s)?:\/\/(?:www\.)?github\.com\/([^/]+\/[^/]+)(?:\/)?$/i)
136
137 if (nwo) {
@@ -149,7 +141,7 @@ function getNameWithOwner (url) {
141 return null
142 }
143
152 -function getGitHubData (repo, overrideData, filePath) {
144 +function getGitHubData(repo, overrideData, filePath) {
145 const gh = {
146 nwo: getNameWithOwner(repo.url),
147 branch: 'master',
@@ -168,7 +160,7 @@ function getGitHubData (repo, overrideData, filePath) {
160 if (overrideData.github_path) {
161 gh.path = overrideData.github_path
162 } else if (repo.path) {
171 - gh.path = repo.path + '/' + filePath
163 + gh.path = `${repo.path}/${filePath}`
164 } else {
165 gh.path = filePath
166 }
@@ -176,7 +168,7 @@ function getGitHubData (repo, overrideData, filePath) {
168 return gh
169 }
170
179 -function getEditUrl (themeOptions, repo, filePath, overrideData = { }) {
171 +function getEditUrl(themeOptions, repo, filePath, overrideData = {}) {
172 if (themeOptions.editOnGitHub === false || overrideData.edit_on_github === false) {
173 return null
174 }
@@ -185,7 +177,7 @@ function getEditUrl (themeOptions, repo, filePath, overrideData = { }) {
177 return `https://github.com/${gh.nwo}/edit/${gh.branch}/${gh.path}`
178 }
179
188 -async function fetchContributors (repo, filePath, overrideData = { }, accessToken = '') {
180 +async function fetchContributors(repo, filePath, overrideData = {}, accessToken = '') {
181 const gh = getGitHubData(repo, overrideData, filePath)
182
183 const cached = CONTRIBUTOR_CACHE.get(gh)
@@ -206,7 +198,7 @@ async function fetchContributors (repo, filePath, overrideData = { }, accessToke
198 }
199 }
200
209 - const { data } = await axios.request(req)
201 + const {data} = await axios.request(req)
202
203 const commits = data
204 .map(commit => ({
@@ -222,9 +214,7 @@ async function fetchContributors (repo, filePath, overrideData = { }, accessToke
214 CONTRIBUTOR_CACHE.set(gh, result)
215 return result
216 } catch (error) {
225 - console.error(
226 - `[ERROR] Unable to fetch contributors for ${filePath}. ${error.message}`
227 - )
217 + console.error(`[ERROR] Unable to fetch contributors for ${filePath}. ${error.message}`)
218 return []
219 }
220 }
theme/gatsby-ssr.js
+2 -2
@@ -1,2 +1,2 @@
1 -export { default as wrapPageElement } from './src/components/wrap-page-element'
2 -export { default as wrapRootElement } from './src/components/wrap-root-element'
1 +export {default as wrapPageElement} from './src/components/wrap-page-element'
2 +export {default as wrapRootElement} from './src/components/wrap-root-element'
theme/index.js
+15 -15
@@ -1,15 +1,15 @@
1 -export { default as Caption } from './src/components/caption'
2 -export { default as Container } from './src/components/container'
3 -export { default as Contributors } from './src/components/contributors'
4 -export { Do, DoDontContainer, Dont } from './src/components/do-dont'
5 -export { default as Frame } from './src/components/frame'
6 -export { default as Head } from './src/components/head'
7 -export { default as Header } from './src/components/header'
8 -export { default as Hero } from './src/components/hero'
9 -export { default as HeroLayout } from './src/components/hero-layout'
10 -export { default as Index } from './src/components/index'
11 -export { default as Note } from './src/components/note'
12 -export { default as Screenshot } from './src/components/screenshot'
13 -export { default as Sidebar } from './src/components/sidebar'
14 -export { default as SourceLink } from './src/components/source-link'
15 -export { default as StatusLabel } from './src/components/status-label'
1 +export {default as Caption} from './src/components/caption'
2 +export {default as Container} from './src/components/container'
3 +export {default as Contributors} from './src/components/contributors'
4 +export {Do, DoDontContainer, Dont} from './src/components/do-dont'
5 +export {default as Frame} from './src/components/frame'
6 +export {default as Head} from './src/components/head'
7 +export {default as Header} from './src/components/header'
8 +export {default as Hero} from './src/components/hero'
9 +export {default as HeroLayout} from './src/components/hero-layout'
10 +export {default as Index} from './src/components/index'
11 +export {default as Note} from './src/components/note'
12 +export {default as Screenshot} from './src/components/screenshot'
13 +export {default as Sidebar} from './src/components/sidebar'
14 +export {default as SourceLink} from './src/components/source-link'
15 +export {default as StatusLabel} from './src/components/status-label'
theme/package.json
+6 -2
@@ -9,6 +9,7 @@
9 "private": true,
10 "main": "index.js",
11 "license": "MIT",
12 + "prettier": "@github/prettier-config",
13 "scripts": {
14 "test": "jest",
15 "lint": "eslint \"**/*.js\"",
@@ -70,15 +71,18 @@
71 "styled-system": "^5.1.5"
72 },
73 "devDependencies": {
74 + "@github/prettier-config": "^0.0.6",
75 "@npmcli/template-oss": "4.11.0",
76 "@testing-library/jest-dom": "^5.16.5",
77 "babel-jest": "^29.3.1",
76 - "eslint": "^8.29.0",
78 + "eslint": "^8.33.0",
79 + "eslint-plugin-github": "^4.6.0",
80 "eslint-plugin-jsx-a11y": "^6.6.1",
81 "eslint-plugin-primer-react": "1.0.1",
82 "eslint-plugin-react": "^7.31.11",
83 "jest": "^29.3.1",
81 - "jest-environment-jsdom": "^29.3.1"
84 + "jest-environment-jsdom": "^29.3.1",
85 + "prettier": "^2.8.3"
86 },
87 "author": "GitHub Inc.",
88 "engines": {
theme/scripts/template-oss/index.js
+2 -9
@@ -6,16 +6,9 @@ module.exports = {
6 '.eslintrc.js': false,
7 },
8 },
9 - allowPaths: [
10 - '/src',
11 - '/gatsby-*.js',
12 - '/jest*.js',
13 - '/index.js',
14 - ],
9 + allowPaths: ['/src', '/gatsby-*.js', '/jest*.js', '/index.js'],
10 requiredPackages: {
11 devDependencies: [],
12 },
18 - allowedPackages: [
19 - 'eslint',
20 - ],
13 + allowedPackages: ['eslint'],
14 }
theme/src/aria-live.js
+3 -3
@@ -15,7 +15,7 @@ if (typeof window !== 'undefined') {
15 }
16
17 // Announce message update to screen reader.
18 -function announce (message) {
18 +function announce(message) {
19 if (!container || !container.isConnected) {
20 /* This condition is for when the aria-live container no longer exists due to nav methods like turbo drive
21 which replace the body getting rid of the region. We add the container if it's missing. We then add a delay
@@ -33,7 +33,7 @@ function announce (message) {
33 }
34
35 // Set aria-live container to message.
36 -function setContainerContent (message) {
36 +function setContainerContent(message) {
37 if (!container) {
38 return
39 }
@@ -50,7 +50,7 @@ function setContainerContent (message) {
50 }
51
52 // Get the global screen reader notice container.
53 -function createNoticeContainer () {
53 +function createNoticeContainer() {
54 container = document.createElement('div')
55 container.setAttribute('aria-live', 'polite')
56 container.style.position = 'absolute'
theme/src/components/__tests__/contributors.test.js
+7 -9
@@ -1,9 +1,9 @@
1 -import { render } from '@testing-library/react'
1 +import {render} from '@testing-library/react'
2 import React from 'react'
3 import Contributors from '../contributors'
4
5 test('renders contributors', () => {
6 - const { queryByText } = render(
6 + const {queryByText} = render(
7 <Contributors
8 contributors={[
9 {
@@ -21,7 +21,7 @@ test('renders contributors', () => {
21 },
22 },
23 ]}
24 - />
24 + />,
25 )
26
27 expect(queryByText(/2 contributors/)).toBeInTheDocument()
@@ -31,9 +31,7 @@ test('renders contributors', () => {
31 })
32
33 test('does not render "last edited by" if latest contributor does not have a latest commit', () => {
34 - const { queryByText } = render(
35 - <Contributors contributors={[{ login: 'ashygee' }]} />
36 - )
34 + const {queryByText} = render(<Contributors contributors={[{login: 'ashygee'}]} />)
35
36 expect(queryByText(/1 contributor/)).toBeInTheDocument()
37 expect(queryByText(/Last edited by/)).toBeNull()
@@ -42,13 +40,13 @@ test('does not render "last edited by" if latest contributor does not have a lat
40 // The `Contributors` component is unlikely to be passed an empty array
41 // but it should be able to handle an empty array gracefully just in case.
42 test('handles no contributors', () => {
45 - const { queryByText } = render(<Contributors contributors={[]} />)
43 + const {queryByText} = render(<Contributors contributors={[]} />)
44
45 expect(queryByText(/0 contributors/)).toBeInTheDocument()
46 })
47
48 test('does not render duplicate contributors', () => {
51 - const { queryByText } = render(
49 + const {queryByText} = render(
50 <Contributors
51 contributors={[
52 {
@@ -66,7 +64,7 @@ test('does not render duplicate contributors', () => {
64 },
65 },
66 ]}
69 - />
67 + />,
68 )
69
70 expect(queryByText(/1 contributor/)).toBeInTheDocument()
theme/src/components/__tests__/page-footer.test.js
+6 -10
@@ -1,41 +1,37 @@
1 -import { render } from '@testing-library/react'
1 +import {render} from '@testing-library/react'
2 import React from 'react'
3 import PageFooter from '../page-footer'
4
5 test('renders correctly when editUrl and contributors are defined', () => {
6 - const { queryByText } = render(
7 - <PageFooter editUrl="#" contributors={[{ login: 'broccolini' }]} />
8 - )
6 + const {queryByText} = render(<PageFooter editUrl="#" contributors={[{login: 'broccolini'}]} />)
7
8 expect(queryByText(/Edit this page on GitHub/)).toBeInTheDocument()
9 expect(queryByText(/contributor/)).toBeInTheDocument()
10 })
11
12 test('renders correctly when editUrl and contributors are undefined', () => {
15 - const { queryByText } = render(<PageFooter />)
13 + const {queryByText} = render(<PageFooter />)
14
15 expect(queryByText(/Edit this page on GitHub/)).toBeNull()
16 expect(queryByText(/contributor/)).toBeNull()
17 })
18
19 test('renders correctly when editUrl is defined but contributors is undefined', () => {
22 - const { queryByText } = render(<PageFooter editUrl="#" />)
20 + const {queryByText} = render(<PageFooter editUrl="#" />)
21
22 expect(queryByText(/Edit this page on GitHub/)).toBeInTheDocument()
23 expect(queryByText(/contributor/)).toBeNull()
24 })
25
26 test('renders correctly when contributors is defined but editUrl is undefined', () => {
29 - const { queryByText } = render(
30 - <PageFooter contributors={[{ login: 'broccolini' }]} />
31 - )
27 + const {queryByText} = render(<PageFooter contributors={[{login: 'broccolini'}]} />)
28
29 expect(queryByText(/Edit this page on GitHub/)).toBeNull()
30 expect(queryByText(/contributor/)).toBeInTheDocument()
31 })
32
33 test('does not render contributors if contributors is an empty array', () => {
38 - const { queryByText } = render(<PageFooter contributors={[]} />)
34 + const {queryByText} = render(<PageFooter contributors={[]} />)
35
36 expect(queryByText(/contributor/)).toBeNull()
37 })
theme/src/components/blockquote.js
+1 -1
@@ -1,5 +1,5 @@
1 import styled from 'styled-components'
2 -import themeGet from '@styled-system/theme-get'
2 +import {themeGet} from '@styled-system/theme-get'
3
4 const Blockquote = styled.blockquote`
5 margin: 0 0 ${themeGet('space.3')};
theme/src/components/caption.js
+2 -2
@@ -1,7 +1,7 @@
1 -import { Text } from '@primer/components'
1 +import {Text} from '@primer/components'
2 import React from 'react'
3
4 -function Caption (props) {
4 +function Caption(props) {
5 return <Text as="p" mt={2} mb={3} fontSize={1} color="gray.5" {...props} />
6 }
7
theme/src/components/clipboard-copy.js
+4 -4
@@ -1,9 +1,9 @@
1 -import { Button, StyledOcticon, themeGet } from '@primer/components'
2 -import { CheckIcon, CopyIcon } from '@primer/octicons-react'
1 +import {Button, StyledOcticon, themeGet} from '@primer/components'
2 +import {CheckIcon, CopyIcon} from '@primer/octicons-react'
3 import styled from 'styled-components'
4 import copy from 'copy-to-clipboard'
5 import React from 'react'
6 -import { announce } from '../aria-live'
6 +import {announce} from '../aria-live'
7
8 const CopyToClipboard = styled(Button)`
9 &:focus {
@@ -11,7 +11,7 @@ const CopyToClipboard = styled(Button)`
11 }
12 `
13
14 -function ClipboardCopy ({ value }) {
14 +function ClipboardCopy({value}) {
15 const [copied, setCopied] = React.useState(false)
16
17 React.useEffect(() => {
theme/src/components/code.js
+23 -33
@@ -1,12 +1,12 @@
1 -import { Absolute, BorderBox, Relative, Text } from '@primer/components'
2 -import Highlight, { defaultProps } from 'prism-react-renderer'
1 +import {Absolute, BorderBox, Relative, Text} from '@primer/components'
2 +import Highlight, {defaultProps} from 'prism-react-renderer'
3 import githubTheme from 'prism-react-renderer/themes/github'
4 -import React, { useState, useEffect } from 'react'
4 +import React, {useState, useEffect} from 'react'
5 import ClipboardCopy from './clipboard-copy'
6 import LiveCode from './live-code'
7
8 -function Code ({ className, children, live, noinline }) {
9 - const [scrollHandleStyle, setScrollHandleStyle] = useState({ position: 'absolute' })
8 +function Code({className, children, live, noinline}) {
9 + const [scrollHandleStyle, setScrollHandleStyle] = useState({position: 'absolute'})
10 const language = className ? className.replace(/language-/, '') : ''
11 const code = children.trim()
12 const scrollHandleRef = React.createRef()
@@ -24,34 +24,18 @@ function Code ({ className, children, live, noinline }) {
24 <Absolute top={0} right={0} p={2} zIndex={1}>
25 <ClipboardCopy value={code} />
26 </Absolute>
27 - <Highlight
28 - {...defaultProps}
29 - code={code}
30 - language={language}
31 - theme={githubTheme}
32 - >
33 - {({ className, style, tokens, getLineProps, getTokenProps }) => (
34 - <BorderBox
35 - as="pre"
36 - className={className}
37 - mt={0}
38 - mb={3}
39 - p={3}
40 - border={0}
41 - style={{ ...style, overflow: 'auto' }}
42 - >
27 + <Highlight {...defaultProps} code={code} language={language} theme={githubTheme}>
28 + {({className, style, tokens, getLineProps, getTokenProps}) => (
29 + <BorderBox as="pre" className={className} mt={0} mb={3} p={3} border={0} style={{...style, overflow: 'auto'}}>
30 {/* This is the scroll handle, it is supposed to be focused with keyboard and scroll a wide codebox horizontally */}
31 {/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
45 - <div aria-hidden="true" tabIndex={0} style={scrollHandleStyle} ref={scrollHandleRef} aria-label={code}>&nbsp;</div>
32 + <div aria-hidden="true" tabIndex={0} style={scrollHandleStyle} ref={scrollHandleRef} aria-label={code}>
33 + &nbsp;
34 + </div>
35 {tokens.map((line, i) => (
47 - <div key={i} {...getLineProps({ line, key: i })}>
36 + <div key={i} {...getLineProps({line, key: i})}>
37 {line.map((token, key) => (
49 - <Text
50 - key={key}
51 - fontFamily="mono"
52 - fontSize={1}
53 - {...getTokenProps({ token, key })}
54 - />
38 + <Text key={key} fontFamily="mono" fontSize={1} {...getTokenProps({token, key})} />
39 ))}
40 </div>
41 ))}
@@ -64,7 +48,7 @@ function Code ({ className, children, live, noinline }) {
48 /**
49 * Resize the scroll handle to the size of the code contents, since the former has to be positioned absolutely.
50 */
67 - function resizeScrollHandle () {
51 + function resizeScrollHandle() {
52 // Skip if already resized.
53 if (typeof scrollHandleStyle.width !== 'undefined') {
54 return
@@ -73,9 +57,15 @@ function Code ({ className, children, live, noinline }) {
57 const node = scrollHandleRef.current
58 node.parentElement.style.position = 'relative'
59 const computedStyle = getComputedStyle(node.parentElement)
76 - const height = node.parentElement.clientHeight - parseInt(computedStyle.paddingTop, 10) - parseInt(computedStyle.paddingBottom, 10)
77 - const width = node.parentElement.scrollWidth - parseInt(computedStyle.paddingLeft, 10) - parseInt(computedStyle.paddingRight, 10)
78 - setScrollHandleStyle({ ...scrollHandleStyle, height, width })
60 + const height =
61 + node.parentElement.clientHeight -
62 + parseInt(computedStyle.paddingTop, 10) -
63 + parseInt(computedStyle.paddingBottom, 10)
64 + const width =
65 + node.parentElement.scrollWidth -
66 + parseInt(computedStyle.paddingLeft, 10) -
67 + parseInt(computedStyle.paddingRight, 10)
68 + setScrollHandleStyle({...scrollHandleStyle, height, width})
69 }
70 }
71
theme/src/components/container.js
+2 -2
@@ -1,7 +1,7 @@
1 -import { Box } from '@primer/components'
1 +import {Box} from '@primer/components'
2 import React from 'react'
3
4 -function Container ({ children }) {
4 +function Container({children}) {
5 return (
6 <Box id="skip-nav" width="100%" maxWidth={960} p={5} mx="auto">
7 {children}
theme/src/components/contributors.js
+6 -13
@@ -1,12 +1,12 @@
1 -import { Avatar, Flex, Link, Text, Tooltip } from '@primer/components'
2 -import { format } from 'date-fns'
1 +import {Avatar, Flex, Link, Text, Tooltip} from '@primer/components'
2 +import {format} from 'date-fns'
3 import uniqBy from 'lodash.uniqby'
4 import pluralize from 'pluralize'
5 import React from 'react'
6
7 // The `contributors` array is fetched in gatsby-node.js at build-time.
8
9 -function Contributors ({ contributors }) {
9 +function Contributors({contributors}) {
10 const uniqueContributors = uniqBy(contributors, 'login')
11 const latestContributor = uniqueContributors[0] || {}
12
@@ -14,8 +14,7 @@ function Contributors ({ contributors }) {
14 <div>
15 <Flex alignItems="center">
16 <Text mr={2}>
17 - {uniqueContributors.length}{' '}
18 - {pluralize('contributor', uniqueContributors.length)}
17 + {uniqueContributors.length} {pluralize('contributor', uniqueContributors.length)}
18 </Text>
19 {uniqueContributors.map(contributor => (
20 <Link
@@ -25,10 +24,7 @@ function Contributors ({ contributors }) {
24 mr={2}
25 >
26 <Tooltip key={contributor.login} aria-label={contributor.login}>
28 - <Avatar
29 - src={`https://github.com/${contributor.login}.png?size=40`}
30 - alt={contributor.login}
31 - />
27 + <Avatar src={`https://github.com/${contributor.login}.png?size=40`} alt={contributor.login} />
28 </Tooltip>
29 </Link>
30 ))}
@@ -36,10 +32,7 @@ function Contributors ({ contributors }) {
32
33 {latestContributor.latestCommit ? (
34 <Text fontSize={1} color="gray.7" mt={1}>
39 - Last edited by{' '}
40 - <Link href={`https://github.com/${latestContributor.login}`}>
41 - {latestContributor.login}
42 - </Link>{' '}
35 + Last edited by <Link href={`https://github.com/${latestContributor.login}`}>{latestContributor.login}</Link>{' '}
36 on{' '}
37 <Link href={latestContributor.latestCommit.url}>
38 {format(new Date(latestContributor.latestCommit.date), 'MMMM d, y')}
theme/src/components/dark-button.js
+1 -1
@@ -1,4 +1,4 @@
1 -import { ButtonOutline, themeGet } from '@primer/components'
1 +import {ButtonOutline, themeGet} from '@primer/components'
2 import styled from 'styled-components'
3
4 const DarkButton = styled(ButtonOutline)`
theme/src/components/dark-text-input.js
+1 -1
@@ -1,4 +1,4 @@
1 -import { TextInput, themeGet } from '@primer/components'
1 +import {TextInput, themeGet} from '@primer/components'
2 import styled from 'styled-components'
3
4 const DarkTextInput = styled(TextInput)`
theme/src/components/description-list.js
+1 -1
@@ -1,5 +1,5 @@
1 import styled from 'styled-components'
2 -import themeGet from '@styled-system/theme-get'
2 +import {themeGet} from '@styled-system/theme-get'
3
4 const DescriptionList = styled.dl`
5 padding: 0;
theme/src/components/details.js
+6 -6
@@ -25,14 +25,14 @@ const DetailsReset = styled.details`
25 }
26 `
27
28 -function getRenderer (children) {
28 +function getRenderer(children) {
29 return typeof children === 'function' ? children : () => children
30 }
31
32 -function Details ({ children, overlay, render = getRenderer(children), ...rest }) {
32 +function Details({children, overlay, render = getRenderer(children), ...rest}) {
33 const [open, setOpen] = React.useState(Boolean(rest.open))
34
35 - function toggle (event) {
35 + function toggle(event) {
36 if (event) {
37 event.preventDefault()
38 }
@@ -43,21 +43,21 @@ function Details ({ children, overlay, render = getRenderer(children), ...rest }
43 }
44 }
45
46 - function openMenu () {
46 + function openMenu() {
47 if (!open) {
48 setOpen(true)
49 document.addEventListener('click', closeMenu)
50 }
51 }
52
53 - function closeMenu () {
53 + function closeMenu() {
54 setOpen(false)
55 document.removeEventListener('click', closeMenu)
56 }
57
58 return (
59 <DetailsReset {...rest} open={open}>
60 - {render({ open, toggle })}
60 + {render({open, toggle})}
61 </DetailsReset>
62 )
63 }
theme/src/components/do-dont.js
+8 -12
@@ -1,15 +1,11 @@
1 -import { Flex, Grid, Text, StyledOcticon } from '@primer/components'
2 -import { CheckIcon, XIcon } from '@primer/octicons-react'
1 +import {Flex, Grid, Text, StyledOcticon} from '@primer/components'
2 +import {CheckIcon, XIcon} from '@primer/octicons-react'
3 import React from 'react'
4 import Caption from './caption'
5
6 -export function DoDontContainer ({ stacked, children }) {
6 +export function DoDontContainer({stacked, children}) {
7 return (
8 - <Grid
9 - gridTemplateColumns={['1fr', null, stacked ? '1fr' : '1fr 1fr']}
10 - gridGap={3}
11 - mb={3}
12 - >
8 + <Grid gridTemplateColumns={['1fr', null, stacked ? '1fr' : '1fr 1fr']} gridGap={3} mb={3}>
9 {children}
10 </Grid>
11 )
@@ -19,19 +15,19 @@ DoDontContainer.defaultProps = {
15 stacked: false,
16 }
17
22 -export function Do (props) {
18 +export function Do(props) {
19 return <DoDontBase {...props} text="Do" icon={CheckIcon} iconBg="green.5" />
20 }
21
26 -export function Dont (props) {
22 +export function Dont(props) {
23 return <DoDontBase {...props} text="Don't" icon={XIcon} iconBg="red.5" />
24 }
25
30 -function DoDontBase ({ src, alt, children, text, icon: Icon, iconBg }) {
26 +function DoDontBase({src, alt, children, text, icon: Icon, iconBg}) {
27 return (
28 <Flex flexDirection="column">
29 <Flex alignSelf="start" flexDirection="row" alignItems="center" mb="2">
34 - <Flex bg={iconBg} color="white" p={1} style={{ borderRadius: '50%' }}>
30 + <Flex bg={iconBg} color="white" p={1} style={{borderRadius: '50%'}}>
31 <StyledOcticon icon={Icon} verticalAlign="middle" size={12} />
32 </Flex>
33 <Text fontWeight="bold" color="gray.9" ml={2}>
theme/src/components/drawer.js
+13 -13
@@ -1,9 +1,9 @@
1 -import { Fixed } from '@primer/components'
2 -import { AnimatePresence, motion } from 'framer-motion'
1 +import {Fixed} from '@primer/components'
2 +import {AnimatePresence, motion} from 'framer-motion'
3 import React from 'react'
4 -import { FocusOn } from 'react-focus-on'
4 +import {FocusOn} from 'react-focus-on'
5
6 -function Drawer ({ isOpen, onDismiss, children }) {
6 +function Drawer({isOpen, onDismiss, children}) {
7 return (
8 <AnimatePresence>
9 {isOpen ? (
@@ -19,10 +19,10 @@ function Drawer ({ isOpen, onDismiss, children }) {
19 <Fixed
20 key="overlay"
21 as={motion.div}
22 - initial={{ opacity: 0 }}
23 - animate={{ opacity: 1 }}
24 - exit={{ opacity: 0 }}
25 - transition={{ type: 'tween' }}
22 + initial={{opacity: 0}}
23 + animate={{opacity: 1}}
24 + exit={{opacity: 0}}
25 + transition={{type: 'tween'}}
26 top={0}
27 right={0}
28 bottom={0}
@@ -34,16 +34,16 @@ function Drawer ({ isOpen, onDismiss, children }) {
34 <Fixed
35 key="drawer"
36 as={motion.div}
37 - initial={{ x: '100%' }}
38 - animate={{ x: 0 }}
39 - exit={{ x: '100%' }}
40 - transition={{ type: 'tween', duration: 0.2 }}
37 + initial={{x: '100%'}}
38 + animate={{x: 0}}
39 + exit={{x: '100%'}}
40 + transition={{type: 'tween', duration: 0.2}}
41 width={300}
42 top={0}
43 right={0}
44 bottom={0}
45 bg="gray.0"
46 - style={{ zIndex: 1 }}
46 + style={{zIndex: 1}}
47 >
48 {children}
49 </Fixed>
theme/src/components/frame.js
+6 -6
@@ -1,14 +1,14 @@
1 import React from 'react'
2 -import FrameComponent, { FrameContextConsumer } from 'react-frame-component'
3 -import { StyleSheetManager } from 'styled-components'
2 +import FrameComponent, {FrameContextConsumer} from 'react-frame-component'
3 +import {StyleSheetManager} from 'styled-components'
4 import Measure from 'react-measure'
5
6 -function Frame ({ children }) {
6 +function Frame({children}) {
7 const [height, setHeight] = React.useState('auto')
8 return (
9 - <FrameComponent style={{ width: '100%', border: 0, height }}>
9 + <FrameComponent style={{width: '100%', border: 0, height}}>
10 <FrameContextConsumer>
11 - {({ document }) => {
11 + {({document}) => {
12 // By default, styled-components injects styles in the head of the page.
13 // However, styles from the page's head don't apply inside iframes.
14 // We're using StyleSheetManager to make styled-components inject styles
@@ -22,7 +22,7 @@ function Frame ({ children }) {
22 bounds={true}
23 onResize={rect => setHeight(rect.bounds.height)}
24 >
25 - {({ measureRef }) => <div ref={measureRef}>{children}</div>}
25 + {({measureRef}) => <div ref={measureRef}>{children}</div>}
26 </Measure>
27 </StyleSheetManager>
28 )
theme/src/components/head.js
+3 -5
@@ -1,12 +1,10 @@
1 import React from 'react'
2 -import Helmet from 'react-helmet'
2 +import {Helmet} from 'react-helmet'
3 import useSiteMetdata from '../use-site-metadata'
4
5 -function Head (props) {
5 +function Head(props) {
6 const siteMetadata = useSiteMetdata()
7 - const title = props.title
8 - ? `${props.title} | ${siteMetadata.title}`
9 - : siteMetadata.title
7 + const title = props.title ? `${props.title} | ${siteMetadata.title}` : siteMetadata.title
8 const description = props.description || siteMetadata.description
9 const lang = props.lang || siteMetadata.lang
10
theme/src/components/header.js
+15 -33
@@ -1,17 +1,14 @@
1 -import { Box, Flex, Link, Sticky } from '@primer/components'
2 -import {
3 - SearchIcon,
4 - ThreeBarsIcon,
5 -} from '@primer/octicons-react'
6 -import { Link as GatsbyLink } from 'gatsby'
1 +import {Box, Flex, Link, Sticky} from '@primer/components'
2 +import {SearchIcon, ThreeBarsIcon} from '@primer/octicons-react'
3 +import {Link as GatsbyLink} from 'gatsby'
4 import React from 'react'
8 -import styled, { ThemeContext } from 'styled-components'
5 +import styled, {ThemeContext} from 'styled-components'
6 import headerNavItems from '../header-nav.yml'
7 import useSiteMetadata from '../use-site-metadata'
8 import DarkButton from './dark-button'
9 import MobileSearch from './mobile-search'
13 -import NavDrawer, { useNavDrawerState } from './nav-drawer'
14 -import NavDropdown, { NavDropdownItem } from './nav-dropdown'
10 +import NavDrawer, {useNavDrawerState} from './nav-drawer'
11 +import NavDropdown, {NavDropdownItem} from './nav-dropdown'
12 import Search from './search'
13 import NpmLogo from './npm-logo'
14
@@ -22,16 +19,14 @@ const NpmHeaderBar = styled(Box)`
19 background-image: linear-gradient(139deg, #fb8817, #ff4b01, #c12127, #e02aff);
20 `
21
25 -function Header ({ location, isSearchEnabled = true }) {
22 +function Header({location, isSearchEnabled = true}) {
23 const theme = React.useContext(ThemeContext)
27 - const [isNavDrawerOpen, setIsNavDrawerOpen] = useNavDrawerState(
28 - theme.breakpoints[2]
29 - )
24 + const [isNavDrawerOpen, setIsNavDrawerOpen] = useNavDrawerState(theme.breakpoints[2])
25 const [isMobileSearchOpen, setIsMobileSearchOpen] = React.useState(false)
26 const siteMetadata = useSiteMetadata()
27
33 - const logoStyle = { color: '#cb0000', marginRight: '16px' }
34 - const titleStyle = { color: '#dddddd', fontWeight: '600', display: 'flex', alignItems: 'center' }
28 + const logoStyle = {color: '#cb0000', marginRight: '16px'}
29 + const titleStyle = {color: '#dddddd', fontWeight: '600', display: 'flex', alignItems: 'center'}
30
31 return (
32 <Sticky role="banner">
@@ -69,10 +64,7 @@ function Header ({ location, isSearchEnabled = true }) {
64 >
65 <SearchIcon />
66 </DarkButton>
72 - <MobileSearch
73 - isOpen={isMobileSearchOpen}
74 - onDismiss={() => setIsMobileSearchOpen(false)}
75 - />
67 + <MobileSearch isOpen={isMobileSearchOpen} onDismiss={() => setIsMobileSearchOpen(false)} />
68 </>
69 ) : null}
70 <DarkButton
@@ -83,11 +75,7 @@ function Header ({ location, isSearchEnabled = true }) {
75 >
76 <ThreeBarsIcon />
77 </DarkButton>
86 - <NavDrawer
87 - location={location}
88 - isOpen={isNavDrawerOpen}
89 - onDismiss={() => setIsNavDrawerOpen(false)}
90 - />
78 + <NavDrawer location={location} isOpen={isNavDrawerOpen} onDismiss={() => setIsNavDrawerOpen(false)} />
79 </Flex>
80 </Flex>
81 </Flex>
@@ -95,7 +83,7 @@ function Header ({ location, isSearchEnabled = true }) {
83 )
84 }
85
98 -function HeaderNavItems ({ items }) {
86 +function HeaderNavItems({items}) {
87 return (
88 <Flex alignItems="center" color="gray.2">
89 {items.map((item, index) => {
@@ -103,7 +91,7 @@ function HeaderNavItems ({ items }) {
91 return (
92 <Box ml={4} key={index}>
93 <NavDropdown title={item.title}>
106 - {item.children.map((child) => (
94 + {item.children.map(child => (
95 <NavDropdownItem key={child.title} href={child.url}>
96 {child.title}
97 </NavDropdownItem>
@@ -114,13 +102,7 @@ function HeaderNavItems ({ items }) {
102 }
103
104 return (
117 - <Link
118 - key={index}
119 - href={item.url}
120 - display="block"
121 - color="inherit"
122 - ml={4}
123 - >
105 + <Link key={index} href={item.url} display="block" color="inherit" ml={4}>
106 {item.title}
107 </Link>
108 )
theme/src/components/heading.js
+18 -24
@@ -1,11 +1,11 @@
1 -import { Heading, Link } from '@primer/components'
2 -import { LinkIcon } from '@primer/octicons-react'
3 -import themeGet from '@styled-system/theme-get'
1 +import {Heading, Link} from '@primer/components'
2 +import {LinkIcon} from '@primer/octicons-react'
3 +import {themeGet} from '@styled-system/theme-get'
4 import GithubSlugger from 'github-slugger'
5 import React from 'react'
6 import textContent from 'react-addons-text-content'
7 import styled from 'styled-components'
8 -import { HEADER_HEIGHT } from './header'
8 +import {HEADER_HEIGHT} from './header'
9
10 const StyledHeading = styled(Heading)`
11 margin-top: ${themeGet('space.4')};
@@ -22,20 +22,14 @@ const StyledHeading = styled(Heading)`
22 }
23 `
24
25 -function MarkdownHeading ({ children, ...props }) {
25 +function MarkdownHeading({children, ...props}) {
26 const slugger = new GithubSlugger()
27 const text = children ? textContent(children) : ''
28 const id = text ? slugger.slug(text) : ''
29
30 return (
31 <StyledHeading id={id} {...props}>
32 - <Link
33 - href={`#${id}`}
34 - p={2}
35 - ml={-32}
36 - color="gray.8"
37 - aria-label={`${text} permalink`}
38 - >
32 + <Link href={`#${id}`} p={2} ml={-32} color="gray.8" aria-label={`${text} permalink`}>
33 <LinkIcon className="octicon-link" verticalAlign="middle" />
34 </Link>
35 {children}
@@ -43,38 +37,38 @@ function MarkdownHeading ({ children, ...props }) {
37 )
38 }
39
46 -const StyledH1 = styled(StyledHeading).attrs({ as: 'h1' })`
40 +const StyledH1 = styled(StyledHeading).attrs({as: 'h1'})`
41 padding-bottom: ${themeGet('space.1')};
42 font-size: ${themeGet('fontSizes.5')};
43 border-bottom: 1px solid ${themeGet('colors.gray.2')};
44 `
45
52 -const StyledH2 = styled(StyledHeading).attrs({ as: 'h2' })`
46 +const StyledH2 = styled(StyledHeading).attrs({as: 'h2'})`
47 padding-bottom: ${themeGet('space.1')};
48 font-size: ${themeGet('fontSizes.4')};
49 border-bottom: 1px solid ${themeGet('colors.gray.2')};
50 `
51
58 -const StyledH3 = styled(StyledHeading).attrs({ as: 'h3' })`
52 +const StyledH3 = styled(StyledHeading).attrs({as: 'h3'})`
53 font-size: ${themeGet('fontSizes.3')};
54 `
55
62 -const StyledH4 = styled(StyledHeading).attrs({ as: 'h4' })`
56 +const StyledH4 = styled(StyledHeading).attrs({as: 'h4'})`
57 font-size: ${themeGet('fontSizes.2')};
58 `
59
66 -const StyledH5 = styled(StyledHeading).attrs({ as: 'h5' })`
60 +const StyledH5 = styled(StyledHeading).attrs({as: 'h5'})`
61 font-size: ${themeGet('fontSizes.1')};
62 `
63
70 -const StyledH6 = styled(StyledHeading).attrs({ as: 'h6' })`
64 +const StyledH6 = styled(StyledHeading).attrs({as: 'h6'})`
65 font-size: ${themeGet('fontSizes.1')};
66 color: ${themeGet('colors.gray.5')};
67 `
68
75 -export const H1 = (props) => <MarkdownHeading as={StyledH1} {...props} />
76 -export const H2 = (props) => <MarkdownHeading as={StyledH2} {...props} />
77 -export const H3 = (props) => <MarkdownHeading as={StyledH3} {...props} />
78 -export const H4 = (props) => <MarkdownHeading as={StyledH4} {...props} />
79 -export const H5 = (props) => <MarkdownHeading as={StyledH5} {...props} />
80 -export const H6 = (props) => <MarkdownHeading as={StyledH6} {...props} />
69 +export const H1 = props => <MarkdownHeading as={StyledH1} {...props} />
70 +export const H2 = props => <MarkdownHeading as={StyledH2} {...props} />
71 +export const H3 = props => <MarkdownHeading as={StyledH3} {...props} />
72 +export const H4 = props => <MarkdownHeading as={StyledH4} {...props} />
73 +export const H5 = props => <MarkdownHeading as={StyledH5} {...props} />
74 +export const H6 = props => <MarkdownHeading as={StyledH6} {...props} />
theme/src/components/hero-layout.js
+5 -10
@@ -1,4 +1,4 @@
1 -import { Box, Flex } from '@primer/components'
1 +import {Box, Flex} from '@primer/components'
2 import React from 'react'
3 import Container from './container'
4 import PageFooter from './page-footer'
@@ -7,8 +7,8 @@ import Header from './header'
7 import Hero from './hero'
8 import Sidebar from './sidebar'
9
10 -function HeroLayout ({ children, pageContext, location }) {
11 - const { additionalContributors = [] } = pageContext.frontmatter
10 +function HeroLayout({children, pageContext, location}) {
11 + const {additionalContributors = []} = pageContext.frontmatter
12
13 return (
14 <Flex flexDirection="column" minHeight="100vh">
@@ -17,10 +17,7 @@ function HeroLayout ({ children, pageContext, location }) {
17 <Flex flex="1 1 auto" flexDirection="row" role="main">
18 <Box display={['none', null, null, 'block']}>
19 <Sidebar
20 - editOnGitHub={
21 - pageContext.themeOptions.showSidebarEditLink &&
22 - pageContext.themeOptions.editOnGitHub
23 - }
20 + editOnGitHub={pageContext.themeOptions.showSidebarEditLink && pageContext.themeOptions.editOnGitHub}
21 location={location}
22 />
23 </Box>
@@ -31,9 +28,7 @@ function HeroLayout ({ children, pageContext, location }) {
28 <PageFooter
29 editOnGitHub={pageContext.themeOptions.editOnGitHub}
30 editUrl={pageContext.themeOptions.editUrl}
34 - contributors={pageContext.contributors.concat(
35 - additionalContributors.map(login => ({ login }))
36 - )}
31 + contributors={pageContext.contributors.concat(additionalContributors.map(login => ({login})))}
32 />
33 </Container>
34 </Box>
theme/src/components/hero.js
+3 -3
@@ -1,10 +1,10 @@
1 -import { Box, Heading, Text } from '@primer/components'
1 +import {Box, Heading, Text} from '@primer/components'
2 import React from 'react'
3 import useSiteMetadata from '../use-site-metadata'
4 import Container from './container'
5
6 -function Hero () {
7 - const { title, description } = useSiteMetadata()
6 +function Hero() {
7 + const {title, description} = useSiteMetadata()
8
9 return (
10 <Box bg="black" py={6}>
theme/src/components/horizontal-rule.js
+1 -1
@@ -1,5 +1,5 @@
1 import styled from 'styled-components'
2 -import themeGet from '@styled-system/theme-get'
2 +import {themeGet} from '@styled-system/theme-get'
3
4 const HorizontalRule = styled.hr`
5 height: ${themeGet('space.1')};
theme/src/components/image.js
+1 -1
@@ -1,4 +1,4 @@
1 -import themeGet from '@styled-system/theme-get'
1 +import {themeGet} from '@styled-system/theme-get'
2 import styled from 'styled-components'
3
4 const Image = styled.img`
theme/src/components/index.js
+13 -11
@@ -1,11 +1,11 @@
1 import React from 'react'
2 // eslint-disable-next-line import/no-unresolved
3 -import { Location } from '@reach/router'
4 -import { Box, Link } from '@primer/components'
5 -import { Link as GatsbyLink } from 'gatsby'
3 +import {Location} from '@reach/router'
4 +import {Box, Link} from '@primer/components'
5 +import {Link as GatsbyLink} from 'gatsby'
6 import NavHierarchy from '../nav-hierarchy'
7
8 -function showHierarchy (items, props, depth = 1) {
8 +function showHierarchy(items, props, depth = 1) {
9 let hierarchy
10
11 if (props.depth && depth > props.depth) {
@@ -16,25 +16,27 @@ function showHierarchy (items, props, depth = 1) {
16 <Box as="ul">
17 {items.map(item => (
18 <Box as="li" key={item.url}>
19 - <Link as={GatsbyLink} key={item.title} to={item.url}>{item.title}</Link>
19 + <Link as={GatsbyLink} key={item.title} to={item.url}>
20 + {item.title}
21 + </Link>
22 {item.description != null ? (
23 <>
22 - <Box style={{ fontSize: '0.85em', marginBottom: '0.5em' }}>
23 - {item.description}
24 - </Box>
24 + <Box style={{fontSize: '0.85em', marginBottom: '0.5em'}}>{item.description}</Box>
25 </>
26 ) : null}
27 - {(hierarchy = NavHierarchy.getHierarchy(item, props)) != null ? showHierarchy(hierarchy, props, depth + 1) : null}
27 + {(hierarchy = NavHierarchy.getHierarchy(item, props)) != null
28 + ? showHierarchy(hierarchy, props, depth + 1)
29 + : null}
30 </Box>
31 ))}
32 </Box>
33 )
34 }
35
34 -function Index (props) {
36 +function Index(props) {
37 return (
38 <Location>
37 - {({ location }) => {
39 + {({location}) => {
40 const path = NavHierarchy.getLocation(location.pathname)
41 let root = props.root ? props.root : path
42 root = root.replace(/\/+$/g, '')
theme/src/components/inline-code.js
+1 -1
@@ -1,5 +1,5 @@
1 import styled from 'styled-components'
2 -import themeGet from '@styled-system/theme-get'
2 +import {themeGet} from '@styled-system/theme-get'
3
4 const InlineCode = styled.code`
5 padding: 0.2em 0.4em;
theme/src/components/layout.js
+36 -61
@@ -1,19 +1,9 @@
1 -import {
2 - BorderBox,
3 - Box,
4 - Details,
5 - Flex,
6 - Grid,
7 - Heading,
8 - Position,
9 - StyledOcticon,
10 - Text,
11 -} from '@primer/components'
12 -import { ChevronDownIcon, ChevronRightIcon } from '@primer/octicons-react'
1 +import {BorderBox, Box, Details, Flex, Grid, Heading, Position, StyledOcticon, Text} from '@primer/components'
2 +import {ChevronDownIcon, ChevronRightIcon} from '@primer/octicons-react'
3 import React from 'react'
14 -import { MDXProvider } from '@mdx-js/react'
4 +import {MDXProvider} from '@mdx-js/react'
5 import Head from './head'
16 -import Header, { HEADER_HEIGHT } from './header'
6 +import Header, {HEADER_HEIGHT} from './header'
7 import Index from './index'
8 import Note from './note'
9 import PageFooter from './page-footer'
@@ -27,36 +17,28 @@ import TableOfContents from './table-of-contents'
17 import VariantSelect from './variant-select'
18 import NavHierarchy from '../nav-hierarchy'
19
30 -function Layout ({ children, pageContext, location }) {
31 - const {
32 - title,
33 - description,
34 - status,
35 - source,
36 - additionalContributors = [],
37 - } = pageContext.frontmatter
20 +function Layout({children, pageContext, location}) {
21 + const {title, description, status, source, additionalContributors = []} = pageContext.frontmatter
22
23 const variantRoot = NavHierarchy.getVariantRoot(location.pathname)
24
25 return (
42 - <MDXProvider components={{
43 - Index,
44 - Note,
45 - Prompt,
46 - PromptReply,
47 - Screenshot,
48 - }}>
49 -
26 + <MDXProvider
27 + components={{
28 + Index,
29 + Note,
30 + Prompt,
31 + PromptReply,
32 + Screenshot,
33 + }}
34 + >
35 <Flex flexDirection="column" minHeight="100vh">
36 <Head title={title} description={description} />
37 <Header location={location} isSearchEnabled={pageContext.isSearchEnabled} />
53 - <Flex flex="1 1 auto" flexDirection="row" css={{ zIndex: 0 }} role="main">
38 + <Flex flex="1 1 auto" flexDirection="row" css={{zIndex: 0}} role="main">
39 <Box display={['none', null, null, 'block']}>
40 <Sidebar
56 - editOnGitHub={
57 - pageContext.themeOptions.showSidebarEditLink &&
58 - pageContext.themeOptions.editOnGitHub
59 - }
41 + editOnGitHub={pageContext.themeOptions.showSidebarEditLink && pageContext.themeOptions.editOnGitHub}
42 location={location}
43 />
44 </Box>
@@ -64,25 +46,16 @@ function Layout ({ children, pageContext, location }) {
46 id="skip-nav"
47 maxWidth="100%"
48 gridTemplateColumns={['100%', null, 'minmax(0, 65ch) 220px']}
67 - gridTemplateAreas={[
68 - '"heading" "content"',
69 - null,
70 - '"heading table-of-contents" "content table-of-contents"',
71 - ]}
49 + gridTemplateAreas={['"heading" "content"', null, '"heading table-of-contents" "content table-of-contents"']}
50 gridColumnGap={[null, null, 6, 7]}
51 gridRowGap={3}
52 mx="auto"
53 p={[5, 6, null, 7]}
76 - css={{ alignItems: 'start', alignSelf: 'start' }}
54 + css={{alignItems: 'start', alignSelf: 'start'}}
55 role="region"
56 >
79 - <Box css={{ gridArea: 'heading' }}>
80 - <BorderBox
81 - borderWidth={0}
82 - borderBottomWidth={1}
83 - borderRadius={0}
84 - pb={2}
85 - >
57 + <Box css={{gridArea: 'heading'}}>
58 + <BorderBox borderWidth={0} borderBottomWidth={1} borderRadius={0} pb={2}>
59 <Box>
60 <Box>
61 <Heading as="h1">{title}</Heading>
@@ -91,15 +64,21 @@ function Layout ({ children, pageContext, location }) {
64 </Box>
65 </BorderBox>
66 {variantRoot != null ? (
94 - <Box css={{ 'margin-top': '25px' }}>
95 - <VariantSelect overlay={true} direction="se" menuWidth="min(30ch, 500px)" root={variantRoot} location={location} />
67 + <Box css={{'margin-top': '25px'}}>
68 + <VariantSelect
69 + overlay={true}
70 + direction="se"
71 + menuWidth="min(30ch, 500px)"
72 + root={variantRoot}
73 + location={location}
74 + />
75 </Box>
76 ) : null}
77 </Box>
78 {pageContext.tableOfContents.items ? (
79 <Position
80 display={['none', null, 'block']}
102 - css={{ gridArea: 'table-of-contents', overflow: 'auto' }}
81 + css={{gridArea: 'table-of-contents', overflow: 'auto'}}
82 position="sticky"
83 top={HEADER_HEIGHT + 24}
84 mt="6px"
@@ -108,13 +87,13 @@ function Layout ({ children, pageContext, location }) {
87 pl={1}
88 pb={1}
89 >
111 - <Text display="inline-block" fontWeight="bold" mb={1} id='table-of-content-label'>
90 + <Text display="inline-block" fontWeight="bold" mb={1} id="table-of-content-label">
91 Table of contents
92 </Text>
114 - <TableOfContents items={pageContext.tableOfContents.items} labelId='table-of-content-label'/>
93 + <TableOfContents items={pageContext.tableOfContents.items} labelId="table-of-content-label" />
94 </Position>
95 ) : null}
117 - <Box css={{ gridArea: 'content' }}>
96 + <Box css={{gridArea: 'content'}}>
97 {status || source ? (
98 <Flex mb={3} alignItems="center">
99 {status ? <StatusLabel status={status} /> : null}
@@ -125,7 +104,7 @@ function Layout ({ children, pageContext, location }) {
104 {pageContext.tableOfContents.items ? (
105 <Box display={['block', null, 'none']} mb={3}>
106 <Details>
128 - {({ open }) => (
107 + {({open}) => (
108 <>
109 <Text as="summary" fontWeight="bold">
110 {open ? (
@@ -136,9 +115,7 @@ function Layout ({ children, pageContext, location }) {
115 Table of contents
116 </Text>
117 <Box pt={1}>
139 - <TableOfContents
140 - items={pageContext.tableOfContents.items}
141 - />
118 + <TableOfContents items={pageContext.tableOfContents.items} />
119 </Box>
120 </>
121 )}
@@ -149,9 +126,7 @@ function Layout ({ children, pageContext, location }) {
126 <PageFooter
127 editOnGitHub={pageContext.themeOptions.editOnGitHub}
128 editUrl={pageContext.editUrl}
152 - contributors={pageContext.contributors.concat(
153 - additionalContributors.map((login) => ({ login }))
154 - )}
129 + contributors={pageContext.contributors.concat(additionalContributors.map(login => ({login})))}
130 />
131 </Box>
132 </Grid>
theme/src/components/list.js
+1 -1
@@ -1,5 +1,5 @@
1 import styled from 'styled-components'
2 -import themeGet from '@styled-system/theme-get'
2 +import {themeGet} from '@styled-system/theme-get'
3
4 const List = styled.ul`
5 padding-left: 2em;
theme/src/components/live-code.js
+12 -28
@@ -1,10 +1,10 @@
1 -import { Absolute, BorderBox, Relative, Text } from '@primer/components'
1 +import {Absolute, BorderBox, Relative, Text} from '@primer/components'
2 import htmlReactParser from 'html-react-parser'
3 import githubTheme from 'prism-react-renderer/themes/github'
4 -import React, { useState } from 'react'
4 +import React, {useState} from 'react'
5 import reactElementToJsxString from 'react-element-to-jsx-string'
6 -import { LiveEditor, LiveError, LivePreview, LiveProvider } from 'react-live'
7 -import { ThemeContext } from 'styled-components'
6 +import {LiveEditor, LiveError, LivePreview, LiveProvider} from 'react-live'
7 +import {ThemeContext} from 'styled-components'
8 import scope from '../live-code-scope'
9 import ClipboardCopy from './clipboard-copy'
10 import LivePreviewWrapper from './live-preview-wrapper'
@@ -14,7 +14,7 @@ const languageTransformers = {
14 jsx: jsx => wrapWithFragment(jsx),
15 }
16
17 -function htmlToJsx (html) {
17 +function htmlToJsx(html) {
18 try {
19 const reactElement = htmlReactParser(removeNewlines(html))
20 // The output of htmlReactParser could be a single React element
@@ -26,30 +26,22 @@ function htmlToJsx (html) {
26 }
27 }
28
29 -function removeNewlines (string) {
29 +function removeNewlines(string) {
30 return string.replace(/(\r\n|\n|\r)/gm, '')
31 }
32
33 -function wrapWithFragment (jsx) {
33 +function wrapWithFragment(jsx) {
34 return `<React.Fragment>${jsx}</React.Fragment>`
35 }
36
37 -function LiveCode ({ code, language, noinline }) {
37 +function LiveCode({code, language, noinline}) {
38 const theme = React.useContext(ThemeContext)
39 const [liveCode, setLiveCode] = useState(code)
40 - const handleChange = (updatedLiveCode) => setLiveCode(updatedLiveCode)
40 + const handleChange = updatedLiveCode => setLiveCode(updatedLiveCode)
41
42 return (
43 - <BorderBox
44 - flexDirection="column"
45 - mb={3}
46 - >
47 - <LiveProvider
48 - scope={scope}
49 - code={liveCode}
50 - transformCode={languageTransformers[language]}
51 - noInline={noinline}
52 - >
43 + <BorderBox flexDirection="column" mb={3}>
44 + <LiveProvider scope={scope} code={liveCode} transformCode={languageTransformers[language]} noInline={noinline}>
45 <LivePreviewWrapper>
46 <LivePreview />
47 </LivePreviewWrapper>
@@ -70,15 +62,7 @@ function LiveCode ({ code, language, noinline }) {
62 <ClipboardCopy value={liveCode} />
63 </Absolute>
64 </Relative>
73 - <Text
74 - as={LiveError}
75 - m={0}
76 - p={3}
77 - fontFamily="mono"
78 - fontSize={1}
79 - color="white"
80 - bg="red.5"
81 - />
65 + <Text as={LiveError} m={0} p={3} fontFamily="mono" fontSize={1} color="white" bg="red.5" />
66 </LiveProvider>
67 </BorderBox>
68 )
theme/src/components/live-preview-wrapper.js
+2 -2
@@ -1,10 +1,10 @@
1 -import { BaseStyles, Box } from '@primer/components'
1 +import {BaseStyles, Box} from '@primer/components'
2 import Frame from './frame'
3 import React from 'react'
4
5 // Users can shadow this file to wrap live previews.
6 // This is useful for applying global styles.
7 -function LivePreviewWrapper ({ children }) {
7 +function LivePreviewWrapper({children}) {
8 return (
9 <Frame>
10 <BaseStyles>
theme/src/components/mobile-search.js
+23 -34
@@ -1,38 +1,38 @@
1 -import { Absolute, Fixed, Flex } from '@primer/components'
2 -import { XIcon } from '@primer/octicons-react'
1 +import {Absolute, Fixed, Flex} from '@primer/components'
2 +import {XIcon} from '@primer/octicons-react'
3 import Downshift from 'downshift'
4 -import { AnimatePresence, motion } from 'framer-motion'
5 -import { navigate } from 'gatsby'
4 +import {AnimatePresence, motion} from 'framer-motion'
5 +import {navigate} from 'gatsby'
6 import React from 'react'
7 -import { FocusOn } from 'react-focus-on'
7 +import {FocusOn} from 'react-focus-on'
8 import useSearch from '../use-search'
9 import DarkButton from './dark-button'
10 import DarkTextInput from './dark-text-input'
11 import SearchResults from './search-results'
12 import useSiteMetadata from '../use-site-metadata'
13
14 -function stateReducer (state, changes) {
14 +function stateReducer(state, changes) {
15 switch (changes.type) {
16 case Downshift.stateChangeTypes.changeInput:
17 if (!changes.inputValue) {
18 // Close the menu if the input is empty.
19 - return { ...changes, isOpen: false }
19 + return {...changes, isOpen: false}
20 }
21 return changes
22 case Downshift.stateChangeTypes.blurInput:
23 // Don't let a blur event change the state of `inputValue` or `isOpen`.
24 - return { ...changes, inputValue: state.inputValue, isOpen: state.isOpen }
24 + return {...changes, inputValue: state.inputValue, isOpen: state.isOpen}
25 default:
26 return changes
27 }
28 }
29
30 -function MobileSearch ({ isOpen, onDismiss }) {
30 +function MobileSearch({isOpen, onDismiss}) {
31 const [query, setQuery] = React.useState('')
32 const results = useSearch(query)
33 const siteMetadata = useSiteMetadata()
34
35 - function handleDismiss () {
35 + function handleDismiss() {
36 setQuery('')
37 onDismiss()
38 }
@@ -44,9 +44,9 @@ function MobileSearch ({ isOpen, onDismiss }) {
44 <Fixed top={0} left={0} right={0} bottom={0} zIndex={1}>
45 <Absolute
46 as={motion.div}
47 - initial={{ opacity: 0 }}
48 - animate={{ opacity: 1 }}
49 - exit={{ opacity: 0 }}
47 + initial={{opacity: 0}}
48 + animate={{opacity: 1}}
49 + exit={{opacity: 0}}
50 top={0}
51 left={0}
52 right={0}
@@ -57,25 +57,18 @@ function MobileSearch ({ isOpen, onDismiss }) {
57 />
58 <Downshift
59 inputValue={query}
60 - onInputValueChange={(inputValue) => setQuery(inputValue)}
60 + onInputValueChange={inputValue => setQuery(inputValue)}
61 selectedItem={null}
62 - onSelect={(item) => {
62 + onSelect={item => {
63 if (item) {
64 navigate(item.path)
65 handleDismiss()
66 }
67 }}
68 - itemToString={(item) => (item ? item.title : '')}
68 + itemToString={item => (item ? item.title : '')}
69 stateReducer={stateReducer}
70 >
71 - {({
72 - getInputProps,
73 - getItemProps,
74 - getMenuProps,
75 - getRootProps,
76 - isOpen: isMenuOpen,
77 - highlightedIndex,
78 - }) => (
71 + {({getInputProps, getItemProps, getMenuProps, getRootProps, isOpen: isMenuOpen, highlightedIndex}) => (
72 <Flex
73 {...getRootProps({
74 flexDirection: 'column',
@@ -84,11 +77,11 @@ function MobileSearch ({ isOpen, onDismiss }) {
77 >
78 <Flex bg="gray.9" color="white" p={3} flex="0 0 auto">
79 <motion.div
87 - initial={{ scaleX: 0.1 }}
88 - animate={{ scaleX: 1 }}
89 - exit={{ scaleX: 0.1, transition: { duration: 0.1 } }}
90 - transition={{ type: 'tween', duration: 0.2 }}
91 - style={{ width: '100%', originX: '100%' }}
80 + initial={{scaleX: 0.1}}
81 + animate={{scaleX: 1}}
82 + exit={{scaleX: 0.1, transition: {duration: 0.1}}}
83 + transition={{type: 'tween', duration: 0.2}}
84 + style={{width: '100%', originX: '100%'}}
85 >
86 <DarkTextInput
87 {...getInputProps({
@@ -97,11 +90,7 @@ function MobileSearch ({ isOpen, onDismiss }) {
90 })}
91 />
92 </motion.div>
100 - <DarkButton
101 - ml={3}
102 - aria-label="Cancel"
103 - onClick={handleDismiss}
104 - >
93 + <DarkButton ml={3} aria-label="Cancel" onClick={handleDismiss}>
94 <XIcon />
95 </DarkButton>
96 </Flex>
theme/src/components/nav-drawer.js
+16 -48
@@ -1,6 +1,6 @@
1 -import { BorderBox, Flex, Link, Text } from '@primer/components'
2 -import { ChevronDownIcon, ChevronUpIcon, XIcon } from '@primer/octicons-react'
3 -import { Link as GatsbyLink } from 'gatsby'
1 +import {BorderBox, Flex, Link, Text} from '@primer/components'
2 +import {ChevronDownIcon, ChevronUpIcon, XIcon} from '@primer/octicons-react'
3 +import {Link as GatsbyLink} from 'gatsby'
4 import debounce from 'lodash.debounce'
5 import React from 'react'
6 import navItems from '../nav.yml'
@@ -11,7 +11,7 @@ import Details from './details'
11 import Drawer from './drawer'
12 import NavItems from './nav-items'
13
14 -export function useNavDrawerState (breakpoint) {
14 +export function useNavDrawerState(breakpoint) {
15 // Handle string values from themes with units at the end
16 if (typeof breakpoint === 'string') {
17 breakpoint = parseInt(breakpoint, 10)
@@ -24,9 +24,7 @@ export function useNavDrawerState (breakpoint) {
24 }
25 }, [setOpen])
26
27 - const debouncedOnResize = React.useCallback(debounce(onResize, 250), [
28 - onResize,
29 - ])
27 + const debouncedOnResize = React.useCallback(debounce(onResize, 250), [onResize])
28
29 React.useEffect(() => {
30 if (isOpen) {
@@ -42,7 +40,7 @@ export function useNavDrawerState (breakpoint) {
40 return [isOpen, setOpen]
41 }
42
45 -function NavDrawer ({ location, isOpen, onDismiss }) {
43 +function NavDrawer({location, isOpen, onDismiss}) {
44 const siteMetadata = useSiteMetadata()
45 return (
46 <Drawer isOpen={isOpen} onDismiss={onDismiss}>
@@ -50,30 +48,12 @@ function NavDrawer ({ location, isOpen, onDismiss }) {
48 flexDirection="column"
49 height="100%"
50 bg="gray.0"
53 - style={{ overflow: 'auto', WebkitOverflowScrolling: 'touch' }}
51 + style={{overflow: 'auto', WebkitOverflowScrolling: 'touch'}}
52 >
53 <Flex flexDirection="column" flex="1 0 auto" color="gray.7" bg="gray.0">
56 - <BorderBox
57 - borderWidth={0}
58 - borderRadius={0}
59 - borderBottomWidth={1}
60 - borderColor="gray.7"
61 - >
62 - <Flex
63 - py={3}
64 - pl={4}
65 - pr={3}
66 - alignItems="center"
67 - justifyContent="space-between"
68 - color="gray.1"
69 - bg="gray.9"
70 - >
71 - <Link
72 - as={GatsbyLink}
73 - to="/"
74 - display="inline-block"
75 - color="inherit"
76 - >
54 + <BorderBox borderWidth={0} borderRadius={0} borderBottomWidth={1} borderColor="gray.7">
55 + <Flex py={3} pl={4} pr={3} alignItems="center" justifyContent="space-between" color="gray.1" bg="gray.9">
56 + <Link as={GatsbyLink} to="/" display="inline-block" color="inherit">
57 {siteMetadata.title}
58 </Link>
59 <DarkButton aria-label="Close" onClick={onDismiss}>
@@ -88,12 +68,7 @@ function NavDrawer ({ location, isOpen, onDismiss }) {
68 ) : null}
69 </Flex>
70 {headerNavItems.length > 0 ? (
91 - <Flex
92 - flexDirection="column"
93 - flex="1 0 auto"
94 - color="gray.1"
95 - bg="gray.9"
96 - >
71 + <Flex flexDirection="column" flex="1 0 auto" color="gray.1" bg="gray.9">
72 <HeaderNavItems items={headerNavItems} />
73 </Flex>
74 ) : null}
@@ -102,7 +77,7 @@ function NavDrawer ({ location, isOpen, onDismiss }) {
77 )
78 }
79
105 -function HeaderNavItems ({ items }) {
80 +function HeaderNavItems({items}) {
81 return items.map((item, index) => {
82 return (
83 <BorderBox
@@ -115,24 +90,17 @@ function HeaderNavItems ({ items }) {
90 >
91 {item.children ? (
92 <Details key={index}>
118 - {({ open, toggle }) => (
93 + {({open, toggle}) => (
94 <>
120 - <summary onClick={toggle} style={{ cursor: 'pointer' }}>
95 + <summary onClick={toggle} style={{cursor: 'pointer'}}>
96 <Flex alignItems="center" justifyContent="space-between">
97 <Text>{item.title}</Text>
98 {open ? <ChevronUpIcon /> : <ChevronDownIcon />}
99 </Flex>
100 </summary>
101 <Flex flexDirection="column" mt={2}>
127 - {item.children.map((child) => (
128 - <Link
129 - key={child.title}
130 - href={child.url}
131 - py={1}
132 - mt={2}
133 - fontSize={1}
134 - color="inherit"
135 - >
102 + {item.children.map(child => (
103 + <Link key={child.title} href={child.url} py={1} mt={2} fontSize={1} color="inherit">
104 {child.title}
105 </Link>
106 ))}
theme/src/components/nav-dropdown.js
+6 -12
@@ -1,26 +1,20 @@
1 -import { Absolute, BorderBox, StyledOcticon, Text, themeGet } from '@primer/components'
2 -import { ChevronDownIcon } from '@primer/octicons-react'
1 +import {Absolute, BorderBox, StyledOcticon, Text, themeGet} from '@primer/components'
2 +import {ChevronDownIcon} from '@primer/octicons-react'
3 import React from 'react'
4 import styled from 'styled-components'
5 import Details from './details'
6
7 -function NavDropdown ({ title, children }) {
7 +function NavDropdown({title, children}) {
8 return (
9 <Details overlay={true}>
10 - {({ toggle }) => (
10 + {({toggle}) => (
11 <>
12 - <summary style={{ cursor: 'pointer' }} onClick={toggle}>
12 + <summary style={{cursor: 'pointer'}} onClick={toggle}>
13 <Text>{title}</Text>
14 <StyledOcticon icon={ChevronDownIcon} ml={1} />
15 </summary>
16 <Absolute>
17 - <BorderBox
18 - bg="white"
19 - py={1}
20 - mt={2}
21 - boxShadow="medium"
22 - color="gray.8"
23 - >
17 + <BorderBox bg="white" py={1} mt={2} boxShadow="medium" color="gray.8">
18 {children}
19 </BorderBox>
20 </Absolute>
theme/src/components/nav-items.js
+27 -29
@@ -1,6 +1,6 @@
1 -import { BorderBox, Box, Flex, StyledOcticon, Link, themeGet } from '@primer/components'
2 -import { LinkExternalIcon } from '@primer/octicons-react'
3 -import { Link as GatsbyLink } from 'gatsby'
1 +import {BorderBox, Box, Flex, StyledOcticon, Link, themeGet} from '@primer/components'
2 +import {LinkExternalIcon} from '@primer/octicons-react'
3 +import {Link as GatsbyLink} from 'gatsby'
4 import preval from 'preval.macro'
5 import React from 'react'
6 import styled from 'styled-components'
@@ -18,18 +18,18 @@ const repositoryUrl = preval`
18 }
19 `
20
21 -const getActiveProps = (className) => (props) => {
21 +const getActiveProps = className => props => {
22 const location = NavHierarchy.getLocation(props.location.pathname)
23 const href = NavHierarchy.getLocation(props.href)
24
25 if (NavHierarchy.isActiveUrl(location, href)) {
26 - return { className: `${className} active` }
26 + return {className: `${className} active`}
27 }
28
29 - return { className: `${className}` }
29 + return {className: `${className}`}
30 }
31
32 -const ActiveLink = ({ className, children, ...props }) => (
32 +const ActiveLink = ({className, children, ...props}) => (
33 <Link as={GatsbyLink} getProps={getActiveProps(className)} {...props}>
34 {children}
35 </Link>
@@ -87,28 +87,24 @@ const Description = styled(Box)`
87 }
88 `
89
90 -function topLevelItems (items, path) {
90 +function topLevelItems(items, path) {
91 if (items == null) {
92 return null
93 }
94
95 return (
96 <>
97 - {items.map((item) => {
98 - const children = NavHierarchy.isActiveUrl(path, item.url) ? NavHierarchy.getHierarchy(item, { path: path, hideVariants: true }) : null
97 + {items.map(item => {
98 + const children = NavHierarchy.isActiveUrl(path, item.url)
99 + ? NavHierarchy.getHierarchy(item, {path, hideVariants: true})
100 + : null
101
102 return (
101 - <BorderBox
102 - key={item.title}
103 - borderWidth={0}
104 - borderRadius={0}
105 - borderTopWidth={1}
106 - py={3}
107 - px={4}
108 - role="listitem"
109 - >
103 + <BorderBox key={item.title} borderWidth={0} borderRadius={0} borderTopWidth={1} py={3} px={4} role="listitem">
104 <Flex flexDirection="column">
111 - <TopLevelLink to={item.url} key={item.title}>{item.title}</TopLevelLink>
105 + <TopLevelLink to={item.url} key={item.title}>
106 + {item.title}
107 + </TopLevelLink>
108 {secondLevelItems(children, path)}
109 </Flex>
110 </BorderBox>
@@ -118,15 +114,17 @@ function topLevelItems (items, path) {
114 )
115 }
116
121 -function secondLevelItems (items, path) {
117 +function secondLevelItems(items, path) {
118 if (items == null) {
119 return null
120 }
121
122 return (
123 <Flex flexDirection="column" mt={2} role="list">
128 - {items.map((item) => {
129 - const children = NavHierarchy.isActiveUrl(path, item.url) ? NavHierarchy.getHierarchy(item, { path: path, hideVariants: true }) : null
124 + {items.map(item => {
125 + const children = NavHierarchy.isActiveUrl(path, item.url)
126 + ? NavHierarchy.getHierarchy(item, {path, hideVariants: true})
127 + : null
128 return (
129 <Box key={item.title} role="listitem">
130 <SecondLevelLink key={item.url} to={item.url}>
@@ -145,14 +143,14 @@ function secondLevelItems (items, path) {
143 )
144 }
145
148 -function thirdLevelItems (items) {
146 +function thirdLevelItems(items) {
147 if (items == null) {
148 return null
149 }
150
151 return (
152 <Flex flexDirection="column" mt={2} role="list">
155 - {items.map((item) => (
153 + {items.map(item => (
154 <Box key={item.title} role="listitem">
155 <ThirdLevelLink key={item.url} to={item.url}>
156 {item.title}
@@ -163,7 +161,7 @@ function thirdLevelItems (items) {
161 )
162 }
163
166 -function githubLink () {
164 +function githubLink() {
165 if (!repositoryUrl) {
166 return null
167 }
@@ -172,7 +170,7 @@ function githubLink () {
170 <BorderBox borderWidth={0} borderTopWidth={1} borderRadius={0} py={5} px={4}>
171 <Link href={repositoryUrl} color="inherit">
172 <Flex justifyContent="space-between" alignItems="center" color="gray.5">
175 - Edit on GitHub
173 + Edit on GitHub
174 <StyledOcticon icon={LinkExternalIcon} color="gray.5" />
175 </Flex>
176 </Link>
@@ -180,9 +178,9 @@ function githubLink () {
178 )
179 }
180
183 -function NavItems (props) {
181 +function NavItems(props) {
182 const path = NavHierarchy.getLocation(props.location.pathname)
185 - const items = NavHierarchy.getHierarchy(null, { path: path, hideVariants: true })
183 + const items = NavHierarchy.getHierarchy(null, {path, hideVariants: true})
184
185 return (
186 <>
theme/src/components/note.js
+7 -15
@@ -1,22 +1,14 @@
1 import React from 'react'
2 -import { BorderBox } from '@primer/components'
2 +import {BorderBox} from '@primer/components'
3
4 -function Note ({ children }) {
4 +function Note({children}) {
5 return (
6 - <BorderBox
7 - borderWidth={1}
8 - borderRadius={0}
9 - borderColor='blue.1'
10 - backgroundColor='blue.0'
11 - px={3}
12 - py={2}
13 - my={4}
14 - >
15 - {React.Children.toArray(children).map((child, index, list) => (
6 + <BorderBox borderWidth={1} borderRadius={0} borderColor="blue.1" backgroundColor="blue.0" px={3} py={2} my={4}>
7 + {React.Children.toArray(children).map((child, index, list) =>
8 React.cloneElement(child, {
17 - style: index === list.length - 1 ? { marginBottom: '0' } : null,
18 - })
19 - ))}
9 + style: index === list.length - 1 ? {marginBottom: '0'} : null,
10 + }),
11 + )}
12 </BorderBox>
13 )
14 }
theme/src/components/npm-logo.js
+10 -3
@@ -1,14 +1,21 @@
1 import React from 'react'
2
3 export default class NpmLogo extends React.Component {
4 - render () {
4 + render() {
5 const bgcolor = this.props.bg || '#cb0000'
6 const fgcolor = this.props.fg || '#ffffff'
7
8 return (
9 - <svg height={this.props.size} width={this.props.size} viewBox="0 0 700 700" fill="currentColor" style={this.props.style} aria-hidden="true">
9 + <svg
10 + height={this.props.size}
11 + width={this.props.size}
12 + viewBox="0 0 700 700"
13 + fill="currentColor"
14 + style={this.props.style}
15 + aria-hidden="true"
16 + >
17 <polygon fill={bgcolor} points="0,700 700,700 700,0 0,0" />
11 - <polygon fill={fgcolor} points="150,550 350,550 350,250 450,250 450,550 550,550 550,150 150,150 "/>
18 + <polygon fill={fgcolor} points="150,550 350,550 350,250 450,250 450,550 550,550 550,150 150,150 " />
19 </svg>
20 )
21 }
theme/src/components/page-footer.js
+4 -6
@@ -1,9 +1,9 @@
1 -import { BorderBox, Grid, StyledOcticon, Link } from '@primer/components'
2 -import { PencilIcon } from '@primer/octicons-react'
1 +import {BorderBox, Grid, StyledOcticon, Link} from '@primer/components'
2 +import {PencilIcon} from '@primer/octicons-react'
3 import React from 'react'
4 import Contributors from './contributors'
5
6 -function PageFooter ({ editOnGitHub, editUrl, contributors }) {
6 +function PageFooter({editOnGitHub, editUrl, contributors}) {
7 return editUrl || contributors.length > 0 ? (
8 <BorderBox borderWidth={0} borderTopWidth={1} mt={8} py={5}>
9 <Grid gridGap={4}>
@@ -14,9 +14,7 @@ function PageFooter ({ editOnGitHub, editUrl, contributors }) {
14 </Link>
15 ) : null}
16
17 - {contributors.length > 0 ? (
18 - <Contributors contributors={contributors} />
19 - ) : null}
17 + {contributors.length > 0 ? <Contributors contributors={contributors} /> : null}
18 </Grid>
19 </BorderBox>
20 ) : null
theme/src/components/paragraph.js
+1 -1
@@ -1,5 +1,5 @@
1 import styled from 'styled-components'
2 -import themeGet from '@styled-system/theme-get'
2 +import {themeGet} from '@styled-system/theme-get'
3
4 const Paragraph = styled.p`
5 margin: 0 0 ${themeGet('space.3')};
theme/src/components/prompt-reply.js
+2 -2
@@ -1,7 +1,7 @@
1 import React from 'react'
2
3 -function PromptReply ({ children }) {
4 - return (<strong>{children}</strong>)
3 +function PromptReply({children}) {
4 + return <strong>{children}</strong>
5 }
6
7 export default PromptReply
theme/src/components/prompt.js
+6 -4
@@ -1,7 +1,7 @@
1 import React from 'react'
2 -import { BorderBox, Text } from '@primer/components'
2 +import {BorderBox, Text} from '@primer/components'
3
4 -function Prompt ({ children }) {
4 +function Prompt({children}) {
5 return (
6 <BorderBox
7 as="pre"
@@ -9,9 +9,11 @@ function Prompt ({ children }) {
9 mb={3}
10 p={3}
11 border={0}
12 - style={{ color: 'rgb(57, 58, 52)', backgroundColor: 'rgb(246, 248, 250)', overflow: 'auto' }}
12 + style={{color: 'rgb(57, 58, 52)', backgroundColor: 'rgb(246, 248, 250)', overflow: 'auto'}}
13 >
14 - <Text fontFamily="mono" fontSize={1}>{children}</Text>
14 + <Text fontFamily="mono" fontSize={1}>
15 + {children}
16 + </Text>
17 </BorderBox>
18 )
19 }
theme/src/components/screenshot.js
+9 -3
@@ -1,7 +1,7 @@
1 import React from 'react'
2 -import { withPrefix } from 'gatsby'
2 +import {withPrefix} from 'gatsby'
3
4 -function Screenshot (props) {
4 +function Screenshot(props) {
5 if (!props.src) {
6 throw new Error('src is required')
7 }
@@ -11,7 +11,13 @@ function Screenshot (props) {
11 }
12
13 return (
14 - <div><img src={withPrefix(props.src)} alt={props.alt} style={{ border: 'solid 1px #999999', marginTop: '15px', maxWidth: 'min(100%, 525px)', maxHeight: '300px' }} /></div>
14 + <div>
15 + <img
16 + src={withPrefix(props.src)}
17 + alt={props.alt}
18 + style={{border: 'solid 1px #999999', marginTop: '15px', maxWidth: 'min(100%, 525px)', maxHeight: '300px'}}
19 + />
20 + </div>
21 )
22 }
23
theme/src/components/search-results.js
+6 -9
@@ -1,9 +1,9 @@
1 -import { Flex, Text } from '@primer/components'
1 +import {Flex, Text} from '@primer/components'
2 import React from 'react'
3 import useSiteMetadata from '../use-site-metadata'
4 import NavHierarchy from '../nav-hierarchy'
5
6 -function SearchResults ({ results, getItemProps, highlightedIndex }) {
6 +function SearchResults({results, getItemProps, highlightedIndex}) {
7 const siteMetadata = useSiteMetadata()
8
9 if (results.length === 0) {
@@ -25,13 +25,10 @@ function SearchResults ({ results, getItemProps, highlightedIndex }) {
25 py: 2,
26 color: highlightedIndex === index ? 'white' : 'gray.8',
27 bg: highlightedIndex === index ? 'blue.5' : 'transparent',
28 - style: { cursor: 'pointer' },
28 + style: {cursor: 'pointer'},
29 })}
30 >
31 - <Text
32 - fontSize={0}
33 - color={highlightedIndex === index ? 'blue.2' : 'gray.7'}
34 - >
31 + <Text fontSize={0} color={highlightedIndex === index ? 'blue.2' : 'gray.7'}>
32 {getBreadcrumbs(siteMetadata.shortName, item.path).join(' / ')}
33 </Text>
34 {item.title}
@@ -39,12 +36,12 @@ function SearchResults ({ results, getItemProps, highlightedIndex }) {
36 ))
37 }
38
42 -function getBreadcrumbs (siteTitle, path) {
39 +function getBreadcrumbs(siteTitle, path) {
40 const hierarchy = NavHierarchy.getItemHierarchy(path)
41
42 if (hierarchy) {
43 hierarchy.pop()
47 - return hierarchy.map(item => item.shortName ? item.shortName : item.title)
44 + return hierarchy.map(item => (item.shortName ? item.shortName : item.title))
45 } else {
46 return [siteTitle]
47 }
theme/src/components/search.js
+9 -20
@@ -1,18 +1,18 @@
1 -import { BorderBox, Position } from '@primer/components'
1 +import {BorderBox, Position} from '@primer/components'
2 import Downshift from 'downshift'
3 -import { navigate } from 'gatsby'
3 +import {navigate} from 'gatsby'
4 import React from 'react'
5 import useSearch from '../use-search'
6 import useSiteMetadata from '../use-site-metadata'
7 import DarkTextInput from './dark-text-input'
8 import SearchResults from './search-results'
9
10 -function stateReducer (state, changes) {
10 +function stateReducer(state, changes) {
11 switch (changes.type) {
12 case Downshift.stateChangeTypes.changeInput:
13 if (!changes.inputValue) {
14 // Close the menu if the input is empty.
15 - return { ...changes, isOpen: false }
15 + return {...changes, isOpen: false}
16 }
17 return changes
18 default:
@@ -20,7 +20,7 @@ function stateReducer (state, changes) {
20 }
21 }
22
23 -function Search () {
23 +function Search() {
24 const [query, setQuery] = React.useState('')
25 const results = useSearch(query)
26 const siteMetadata = useSiteMetadata()
@@ -43,15 +43,8 @@ function Search () {
43 itemToString={item => (item ? item.title : '')}
44 stateReducer={stateReducer}
45 >
46 - {({
47 - getInputProps,
48 - getItemProps,
49 - getMenuProps,
50 - getRootProps,
51 - isOpen,
52 - highlightedIndex,
53 - }) => (
54 - <Position {...getRootProps({ position: 'relative' })}>
46 + {({getInputProps, getItemProps, getMenuProps, getRootProps, isOpen, highlightedIndex}) => (
47 + <Position {...getRootProps({position: 'relative'})}>
48 <DarkTextInput
49 {...getInputProps({
50 placeholder: `Search ${siteMetadata.title}`,
@@ -73,13 +66,9 @@ function Search () {
66 py={1}
67 boxShadow="medium"
68 bg="white"
76 - style={{ overflow: 'auto' }}
69 + style={{overflow: 'auto'}}
70 >
78 - <SearchResults
79 - results={results}
80 - getItemProps={getItemProps}
81 - highlightedIndex={highlightedIndex}
82 - />
71 + <SearchResults results={results} getItemProps={getItemProps} highlightedIndex={highlightedIndex} />
72 </BorderBox>
73 </Position>
74 ) : null}
theme/src/components/sidebar.js
+4 -10
@@ -1,10 +1,10 @@
1 -import { BorderBox, Flex, Position } from '@primer/components'
1 +import {BorderBox, Flex, Position} from '@primer/components'
2 import React from 'react'
3 import navItems from '../nav.yml'
4 -import { HEADER_HEIGHT } from './header'
4 +import {HEADER_HEIGHT} from './header'
5 import NavItems from './nav-items'
6
7 -function Sidebar ({ location, editOnGitHub }) {
7 +function Sidebar({location, editOnGitHub}) {
8 return (
9 <Position
10 position="sticky"
@@ -15,13 +15,7 @@ function Sidebar ({ location, editOnGitHub }) {
15 bg="gray.0"
16 role="navigation"
17 >
18 - <BorderBox
19 - borderWidth={0}
20 - borderRightWidth={1}
21 - borderRadius={0}
22 - height="100%"
23 - style={{ overflow: 'auto' }}
24 - >
18 + <BorderBox borderWidth={0} borderRightWidth={1} borderRadius={0} height="100%" style={{overflow: 'auto'}}>
19 <Flex flexDirection="column" role="list">
20 <NavItems location={location} items={navItems} editOnGitHub={editOnGitHub} />
21 </Flex>
theme/src/components/skip-link.js
+3 -10
@@ -1,17 +1,10 @@
1 -import { Link } from '@primer/components'
1 +import {Link} from '@primer/components'
2 import styled from 'styled-components'
3 import React from 'react'
4
5 -function SkipLinkBase (props) {
5 +function SkipLinkBase(props) {
6 return (
7 - <Link
8 - {...props}
9 - backgroundColor="blue.6"
10 - color="white"
11 - p={3}
12 - href="#skip-nav"
13 - fontSize={1}
14 - >
7 + <Link {...props} backgroundColor="blue.6" color="white" p={3} href="#skip-nav" fontSize={1}>
8 Skip to content
9 </Link>
10 )
theme/src/components/source-link.js
+3 -3
@@ -1,8 +1,8 @@
1 -import { Link, StyledOcticon } from '@primer/components'
2 -import { CodeIcon } from '@primer/octicons-react'
1 +import {Link, StyledOcticon} from '@primer/components'
2 +import {CodeIcon} from '@primer/octicons-react'
3 import React from 'react'
4
5 -function SourceLink ({ href }) {
5 +function SourceLink({href}) {
6 return (
7 <Link href={href} lineHeight="condensedUltra" fontSize={1}>
8 <StyledOcticon icon={CodeIcon} mr={2} />
theme/src/components/status-label.js
+4 -4
@@ -1,5 +1,5 @@
1 -import { BorderBox, StyledOcticon, Flex, Text } from '@primer/components'
2 -import { DotFillIcon } from '@primer/octicons-react'
1 +import {BorderBox, StyledOcticon, Flex, Text} from '@primer/components'
2 +import {DotFillIcon} from '@primer/octicons-react'
3 import React from 'react'
4
5 const STATUS_COLORS = {
@@ -10,11 +10,11 @@ const STATUS_COLORS = {
10 deprecated: 'red.6',
11 }
12
13 -function getStatusColor (status) {
13 +function getStatusColor(status) {
14 return STATUS_COLORS[status.toLowerCase()] || 'gray.5'
15 }
16
17 -function StatusLabel ({ status }) {
17 +function StatusLabel({status}) {
18 return (
19 <BorderBox display="inline-block" px={2} py={1}>
20 <Flex alignItems="center">
theme/src/components/table-of-contents.js
+13 -7
@@ -1,17 +1,23 @@
1 -import { Box, Link } from '@primer/components'
1 +import {Box, Link} from '@primer/components'
2 import React from 'react'
3
4 -function TableOfContents ({ items, depth, labelId }) {
4 +function TableOfContents({items, depth, labelId}) {
5 return (
6 - <Box key={items} as="ul" role='list' m={0} p={0} css={{ listStyle: 'none', lineHeight: '1.4em' }} aria-labelledby={labelId}>
6 + <Box
7 + key={items}
8 + as="ul"
9 + role="list"
10 + m={0}
11 + p={0}
12 + css={{listStyle: 'none', lineHeight: '1.4em'}}
13 + aria-labelledby={labelId}
14 + >
15 {items.map(item => (
8 - <Box as="li" role='listitem' key={item.url} pl={depth > 0 ? 3 : 0}>
16 + <Box as="li" role="listitem" key={item.url} pl={depth > 0 ? 3 : 0}>
17 <Link key={item.title} display="inline-block" py={1} href={item.url} color="gray.6">
18 {item.title}
19 </Link>
12 - {item.items ? (
13 - <TableOfContents items={item.items} depth={depth + 1} />
14 - ) : null}
20 + {item.items ? <TableOfContents items={item.items} depth={depth + 1} /> : null}
21 </Box>
22 ))}
23 </Box>
theme/src/components/table.js
+1 -1
@@ -1,5 +1,5 @@
1 import styled from 'styled-components'
2 -import themeGet from '@styled-system/theme-get'
2 +import {themeGet} from '@styled-system/theme-get'
3
4 const Table = styled.table`
5 display: block;
theme/src/components/variant-select.js
+25 -18
@@ -5,10 +5,10 @@
5 // then you'll get a selection for the different variants (v1.0, v2.0).
6
7 import React from 'react'
8 -import { ActionList, ActionMenu, ThemeProvider } from '@primer/react'
8 +import {ActionList, ActionMenu, ThemeProvider} from '@primer/react'
9 import NavHierarchy from '../nav-hierarchy'
10
11 -function VariantSelect (props) {
11 +function VariantSelect(props) {
12 const [open, setOpen] = React.useState(false)
13 const path = NavHierarchy.getPath(props.location.pathname)
14 const vp = NavHierarchy.getVariantAndPage(props.root, path)
@@ -25,40 +25,47 @@ function VariantSelect (props) {
25 return null
26 }
27
28 - function anchorClickHandler (event, url) {
28 + function anchorClickHandler(event, url) {
29 event.preventDefault()
30 - window.location.href = url + '?v=true'
30 + window.location.href = `${url}?v=true`
31 }
32
33 - function onItemEnterKey (event, url) {
33 + function onItemEnterKey(event, url) {
34 if (event.key === 'Enter') {
35 - window.location.href = url + '?v=true'
35 + window.location.href = `${url}?v=true`
36 }
37 }
38
39 - variantPages.forEach((match, index) => {
39 + for (const [index, match] of variantPages.entries()) {
40 let active = false
41 if (match.page.url === path) {
42 selectedItem = match
43 active = true
44 }
45 - items.push(<ActionList.Item
46 - onKeyDown={e => onItemEnterKey(e, match.page.url)}
47 - onClick={e => anchorClickHandler(e, match.page.url)}
48 - id={match.variant.shortName}
49 - key={index}
50 - active={active}>
51 - {match.variant.title}
52 - </ActionList.Item>)
53 - })
45 + items.push(
46 + <ActionList.Item
47 + onKeyDown={e => onItemEnterKey(e, match.page.url)}
48 + onClick={e => anchorClickHandler(e, match.page.url)}
49 + id={match.variant.shortName}
50 + key={index}
51 + active={active}
52 + >
53 + {match.variant.title}
54 + </ActionList.Item>,
55 + )
56 + }
57
58 const ariaLabelMenuButton = open ? 'Version release' : selectedItem.variant.title
59
60 return (
61 <ThemeProvider>
59 - <label id="label-versions-list-item" htmlFor='versions-list-item'>Select CLI Version:</label>
62 + <label id="label-versions-list-item" htmlFor="versions-list-item">
63 + Select CLI Version:
64 + </label>
65 <ActionMenu open={open} onOpenChange={setOpen}>
61 - <ActionMenu.Button autofocus="true" aria-label={ariaLabelMenuButton}>{selectedItem.variant.title}</ActionMenu.Button>
66 + <ActionMenu.Button autofocus="true" aria-label={ariaLabelMenuButton}>
67 + {selectedItem.variant.title}
68 + </ActionMenu.Button>
69 <ActionMenu.Overlay width="medium" onEscape={() => setOpen(false)}>
70 <ActionList id="versions-list-item" aria-labelledby="label-versions-list-item">
71 {items}
theme/src/components/wrap-page-element.js
+2 -2
@@ -1,8 +1,8 @@
1 -import { BaseStyles } from '@primer/components'
1 +import {BaseStyles} from '@primer/components'
2 import React from 'react'
3 import SkipLink from './skip-link'
4
5 -function wrapPageElement ({ element }) {
5 +function wrapPageElement({element}) {
6 return (
7 <BaseStyles>
8 <SkipLink />
theme/src/components/wrap-root-element.js
+5 -5
@@ -1,11 +1,11 @@
1 -import { MDXProvider } from '@mdx-js/react'
2 -import { Link, theme } from '@primer/components'
1 +import {MDXProvider} from '@mdx-js/react'
2 +import {Link, theme} from '@primer/components'
3 import React from 'react'
4 -import { ThemeProvider } from 'styled-components'
4 +import {ThemeProvider} from 'styled-components'
5 import Blockquote from './blockquote'
6 import Code from './code'
7 import DescriptionList from './description-list'
8 -import { H1, H2, H3, H4, H5, H6 } from './heading'
8 +import {H1, H2, H3, H4, H5, H6} from './heading'
9 import HorizontalRule from './horizontal-rule'
10 import Image from './image'
11 import InlineCode from './inline-code'
@@ -34,7 +34,7 @@ const components = {
34 dl: DescriptionList,
35 }
36
37 -function wrapRootElement ({ element }) {
37 +function wrapRootElement({element}) {
38 return (
39 <MDXProvider components={components}>
40 <ThemeProvider theme={theme}>{element}</ThemeProvider>
theme/src/nav-hierarchy.js
+39 -37
@@ -1,8 +1,8 @@
1 import navItems from './nav.yml'
2 -import { withPrefix } from 'gatsby'
2 +import {withPrefix} from 'gatsby'
3
4 export default {
5 - getLocation (path) {
5 + getLocation(path) {
6 const pathPrefix = withPrefix('/')
7
8 if (!pathPrefix || pathPrefix === '/') {
@@ -13,7 +13,7 @@ export default {
13 return path.replace(match, '/')
14 },
15
16 - getPath (path) {
16 + getPath(path) {
17 while (path && path.endsWith('/')) {
18 path = path.substring(0, path.length - 1)
19 }
@@ -21,11 +21,11 @@ export default {
21 return path
22 },
23
24 - getVariantRoot (path) {
24 + getVariantRoot(path) {
25 path = this.getPath(path)
26
27 - return this.findItem((item) => {
28 - if (item.variants && path.startsWith(item.url + '/')) {
27 + return this.findItem(item => {
28 + if (item.variants && path.startsWith(`${item.url}/`)) {
29 return item.url
30 }
31
@@ -33,7 +33,7 @@ export default {
33 })
34 },
35
36 - findItem (fn, items = navItems) {
36 + findItem(fn, items = navItems) {
37 for (let i = 0; i < items.length; i++) {
38 const item = items[i]
39 let result = fn(item)
@@ -50,7 +50,7 @@ export default {
50 return null
51 },
52
53 - getItemHierarchy (path, items = navItems) {
53 + getItemHierarchy(path, items = navItems) {
54 if (!path) {
55 return null
56 }
@@ -76,9 +76,9 @@ export default {
76 return null
77 },
78
79 - getItem (path, items = navItems) {
79 + getItem(path, items = navItems) {
80 if (!path) {
81 - return { url: '/', children: items }
81 + return {url: '/', children: items}
82 }
83
84 for (let i = 0; i < items.length; i++) {
@@ -102,19 +102,19 @@ export default {
102 return null
103 },
104
105 - isPathForItem (path, item) {
106 - return (this.getPath(item.url) === this.getPath(path))
105 + isPathForItem(path, item) {
106 + return this.getPath(item.url) === this.getPath(path)
107 },
108
109 - isChildItem (path, items = navItems) {
109 + isChildItem(path, items = navItems) {
110 if (!path) {
111 return false
112 }
113
114 - return (this.findItem((item) => this.isPathForItem(path, item) ? item : null, items) != null)
114 + return this.findItem(item => (this.isPathForItem(path, item) ? item : null), items) != null
115 },
116
117 - getHierarchy (root, props = { }) {
117 + getHierarchy(root, props = {}) {
118 let children
119
120 if (!root) {
@@ -135,7 +135,7 @@ export default {
135 return children
136 },
137
138 - hideVariantsForItems (items, props) {
138 + hideVariantsForItems(items, props) {
139 if (!items) {
140 return null
141 }
@@ -144,7 +144,7 @@ export default {
144
145 for (const item of items) {
146 if (item.variants) {
147 - const cloned = { }
147 + const cloned = {}
148 Object.assign(cloned, item)
149
150 const variant = this.getCurrentOrDefaultVariant(item, props.path)
@@ -160,7 +160,7 @@ export default {
160 return updated
161 },
162
163 - getCurrentOrDefaultVariant (root, path) {
163 + getCurrentOrDefaultVariant(root, path) {
164 let variant = path ? this.getCurrentVariant(root, path) : null
165
166 if (!variant) {
@@ -170,7 +170,7 @@ export default {
170 return variant
171 },
172
173 - getCurrentVariant (root, path) {
173 + getCurrentVariant(root, path) {
174 for (const v of root.variants) {
175 if (this.isActiveItem(path, v)) {
176 return v
@@ -180,7 +180,7 @@ export default {
180 return null
181 },
182
183 - getDefaultVariant (root) {
183 + getDefaultVariant(root) {
184 for (const v of root.variants) {
185 if (v.default) {
186 return v
@@ -190,8 +190,8 @@ export default {
190 return root.variants[0]
191 },
192
193 - getVariantAndPage (root, path) {
194 - if (!path.startsWith(root + '/')) {
193 + getVariantAndPage(root, path) {
194 + if (!path.startsWith(`${root}/`)) {
195 return null
196 }
197
@@ -203,17 +203,17 @@ export default {
203 return null
204 }
205
206 - return { variant: match[1], page: match[2] }
206 + return {variant: match[1], page: match[2]}
207 },
208
209 - getVariantsForPage (root, page) {
209 + getVariantsForPage(root, page) {
210 const pages = []
211 - const rootItem = this.findItem((item) => this.getPath(item.url) === this.getPath(root) ? item : null)
211 + const rootItem = this.findItem(item => (this.getPath(item.url) === this.getPath(root) ? item : null))
212
213 if (rootItem && rootItem.variants) {
214 - rootItem.variants.forEach((variant) => {
214 + for (const variant of rootItem.variants) {
215 if (!variant.children) {
216 - return
216 + continue
217 }
218
219 const vp = this.getVariantAndPage(root, variant.url)
@@ -222,30 +222,32 @@ export default {
222 if (vp.page === page) {
223 variantPage = variant
224 } else {
225 - variantPage = this.findItem((item) => {
225 + variantPage = this.findItem(item => {
226 const vp = this.getVariantAndPage(root, item.url)
227 - return (vp && vp.page === page) ? item : null
227 + return vp && vp.page === page ? item : null
228 }, variant.children)
229 }
230
231 if (!variantPage) {
232 - return
232 + continue
233 }
234
235 - pages.push({ variant: variant, page: variantPage })
236 - })
235 + pages.push({variant, page: variantPage})
236 + }
237 }
238
239 return pages
240 },
241
242 - isActiveItem (currentPath, linkItem) {
243 - return (this.isPathForItem(currentPath, linkItem) ||
244 - (linkItem.children && this.isChildItem(currentPath, linkItem.children)) ||
245 - (linkItem.variants && this.isChildItem(currentPath, linkItem.variants)))
242 + isActiveItem(currentPath, linkItem) {
243 + return (
244 + this.isPathForItem(currentPath, linkItem) ||
245 + (linkItem.children && this.isChildItem(currentPath, linkItem.children)) ||
246 + (linkItem.variants && this.isChildItem(currentPath, linkItem.variants))
247 + )
248 },
249
248 - isActiveUrl (currentPath, linkPath) {
250 + isActiveUrl(currentPath, linkPath) {
251 const linkItem = this.getItem(linkPath)
252 return linkItem ? this.isActiveItem(currentPath, linkItem) : false
253 },
theme/src/search.worker.js
+10 -7
@@ -1,7 +1,6 @@
1 import Fuse from 'fuse.js'
2 import debounce from 'lodash.debounce'
3 -
4 -(function searchWorker () {
3 +;(function searchWorker() {
4 let fuse = null
5
6 // [MKT]: I landed on the debouce wait value of 50 based mostly on
@@ -13,12 +12,16 @@ import debounce from 'lodash.debounce'
12 // > Note: If `leading` and `trailing` options are `true`, `func` is invoked
13 // > on the trailing edge of the timeout only if the debounced function is
14 // > invoked more than once during the wait timeout.
16 - const performSearch = debounce(function performSearch (query) {
17 - const results = fuse.search(query).slice(0, 20)
18 - postMessage({ results: results, query: query })
19 - }, 50, { leading: true, trailing: true })
15 + const performSearch = debounce(
16 + function performSearch(query) {
17 + const results = fuse.search(query).slice(0, 20)
18 + postMessage({results, query})
19 + },
20 + 50,
21 + {leading: true, trailing: true},
22 + )
23
21 - onmessage = function ({ data }) {
24 + onmessage = function ({data}) {
25 if (data.list) {
26 fuse = new Fuse(data.list, {
27 threshold: 0.2,
theme/src/use-search.js
+20 -19
@@ -1,7 +1,7 @@
1 -import { graphql, useStaticQuery } from 'gatsby'
1 +import {graphql, useStaticQuery} from 'gatsby'
2 import React from 'react'
3
4 -function useSearch (query) {
4 +function useSearch(query) {
5 const latestQuery = React.useRef(query)
6 const workerRef = React.useRef()
7
@@ -28,29 +28,30 @@ function useSearch (query) {
28 const mdxNodes = data.allMdx.nodes.reduce((map, obj) => {
29 map[obj.id] = obj
30 return map
31 - }, { })
31 + }, {})
32
33 const list = React.useMemo(
34 () =>
35 - data.allSitePage.nodes.filter(node => {
36 - return (node.pageContext && node.pageContext.mdxId && mdxNodes[node.pageContext.mdxId] != null)
37 - }).map(node => {
38 - const mdxNode = mdxNodes[node.pageContext.mdxId]
35 + data.allSitePage.nodes
36 + .filter(node => {
37 + return node.pageContext && node.pageContext.mdxId && mdxNodes[node.pageContext.mdxId] != null
38 + })
39 + .map(node => {
40 + const mdxNode = mdxNodes[node.pageContext.mdxId]
41
40 - const obj =
41 - {
42 - path: node.path,
43 - title: mdxNode.frontmatter.title,
44 - rawBody: mdxNode.rawBody,
45 - }
46 - return obj
47 - }),
48 - [data]
42 + const obj = {
43 + path: node.path,
44 + title: mdxNode.frontmatter.title,
45 + rawBody: mdxNode.rawBody,
46 + }
47 + return obj
48 + }),
49 + [data],
50 )
51
52 const [results, setResults] = React.useState(list)
53
53 - const handleSearchResults = React.useCallback(({ data }) => {
54 + const handleSearchResults = React.useCallback(({data}) => {
55 if (data.query && data.results && data.query === latestQuery.current) {
56 setResults(data.results)
57 }
@@ -59,7 +60,7 @@ function useSearch (query) {
60 React.useEffect(() => {
61 const worker = new Worker(new URL('./search.worker.js', import.meta.url))
62 worker.addEventListener('message', handleSearchResults)
62 - worker.postMessage({ list })
63 + worker.postMessage({list})
64 workerRef.current = worker
65
66 return () => {
@@ -70,7 +71,7 @@ function useSearch (query) {
71 React.useEffect(() => {
72 latestQuery.current = query
73 if (query && workerRef.current) {
73 - workerRef.current.postMessage({ query: query })
74 + workerRef.current.postMessage({query})
75 } else {
76 setResults(list)
77 }
theme/src/use-site-metadata.js
+2 -2
@@ -1,6 +1,6 @@
1 -import { useStaticQuery, graphql } from 'gatsby'
1 +import {useStaticQuery, graphql} from 'gatsby'
2
3 -function useSiteMetadata () {
3 +function useSiteMetadata() {
4 const data = useStaticQuery(graphql`
5 {
6 site {