@primer/gatsby-theme-doctocat 2.1.0 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @primer/gatsby-theme-doctocat
2
2
 
3
+ ## 3.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`45e8748`](https://github.com/primer/doctocat/commit/45e8748a547903b8f7091fafb5b13e5c197b0dae) [#324](https://github.com/primer/doctocat/pull/324) Thanks [@rezrah](https://github.com/rezrah)! - Only add pages that have `componentId` and `status` to `components.json`
8
+
9
+ ## 3.1.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [`3767651`](https://github.com/primer/doctocat/commit/37676515f1d7485ca7b5e932e115d96e3ef0285b) [#318](https://github.com/primer/doctocat/pull/318) Thanks [@colebemis](https://github.com/colebemis)! - Add a step to build process that will output a static `components.json` file with component status info if the site that its building has markdown files containing `componentId` frontmatter.
14
+
15
+ ## 3.0.1
16
+
17
+ ### Patch Changes
18
+
19
+ - [`ff74ece`](https://github.com/primer/doctocat/commit/ff74ecea1b373469034c2122d94a54ca3e964158) [#301](https://github.com/primer/doctocat/pull/301) Thanks [@jfuchs](https://github.com/jfuchs)! - Removed styled system prop usage on Primer React components.
20
+
21
+ ## 3.0.0
22
+
23
+ ### Major Changes
24
+
25
+ - [`c2037d8`](https://github.com/primer/doctocat/commit/c2037d8352fca4ce3055e801b365d4ff1b5eefe9) [#295](https://github.com/primer/doctocat/pull/295) Thanks [@colebemis](https://github.com/colebemis)! - Remove checklist feature
26
+
27
+ ### Minor Changes
28
+
29
+ - [`a94e0a9`](https://github.com/primer/doctocat/commit/a94e0a962e8013901e4285c7a3cabc3a0b691a92) [#294](https://github.com/primer/doctocat/pull/294) Thanks [@colebemis](https://github.com/colebemis)! - You can now make custom React components globally available (no import required) to all markdown files in your site.
30
+
31
+ ### Patch Changes
32
+
33
+ - [`31a62df`](https://github.com/primer/doctocat/commit/31a62dfb7eb7a467a4e03a991adad995564ae4d1) [#262](https://github.com/primer/doctocat/pull/262) Thanks [@SferaDev](https://github.com/SferaDev)! - Fix scroll flickering of table of contents
34
+
35
+ * [`9972de8`](https://github.com/primer/doctocat/commit/9972de88224e1b868dad051abe62a92daf8796ef) [#291](https://github.com/primer/doctocat/pull/291) Thanks [@jonrohan](https://github.com/jonrohan)! - Fix release
36
+
3
37
  ## 2.1.0
4
38
 
5
39
  ### Minor Changes
package/gatsby-node.js CHANGED
@@ -1,41 +1,11 @@
1
1
  const path = require('path')
2
+ const fs = require('fs')
2
3
  const readPkgUp = require('read-pkg-up')
3
4
  const getPkgRepo = require('get-pkg-repo')
4
5
  const axios = require('axios')
5
6
  const uniqBy = require('lodash.uniqby')
6
7
  const extractExports = require(`gatsby-plugin-mdx/utils/extract-exports`)
7
8
  const mdx = require(`gatsby-plugin-mdx/utils/mdx`)
8
- const requireGlob = require('require-glob')
9
- const {validateChecklistSchema, validateChecklist} = require('./src/validate-checklists')
10
- const checklistSchemas = requireGlob.sync('./src/checklists/*.schema.js')
11
-
12
- exports.sourceNodes = ({actions, createNodeId, createContentDigest}) => {
13
- const {createNode} = actions
14
-
15
- // Add checklist schemas to GraphQL API
16
- for (const schemaKey in checklistSchemas) {
17
- try {
18
- validateChecklistSchema(checklistSchemas[schemaKey])
19
- } catch (error) {
20
- throw new Error(`Invalid checklist schema: ${schemaKey.replace('Schema', '')}.schema.js\n${error.message}`)
21
- }
22
-
23
- const name = schemaKey.replace('Schema', '')
24
- const data = {name, ...checklistSchemas[schemaKey]}
25
-
26
- const node = {
27
- id: createNodeId(schemaKey),
28
- parent: null,
29
- children: [],
30
- internal: {
31
- type: 'ChecklistSchema',
32
- contentDigest: createContentDigest(data)
33
- },
34
- ...data
35
- }
36
- createNode(node)
37
- }
38
- }
39
9
 
40
10
  const CONTRIBUTOR_CACHE = new Map()
41
11
 
@@ -43,7 +13,7 @@ exports.createPages = async ({graphql, actions}, themeOptions) => {
43
13
  const repo = getPkgRepo(readPkgUp.sync().package)
44
14
 
45
15
  const {data} = await graphql(`
46
- {
16
+ query {
47
17
  allMdx {
48
18
  nodes {
49
19
  fileAbsolutePath
@@ -65,7 +35,7 @@ exports.createPages = async ({graphql, actions}, themeOptions) => {
65
35
  }
66
36
 
67
37
  // Turn every MDX file into a page.
68
- return Promise.all(
38
+ await Promise.all(
69
39
  data.allMdx.nodes.map(async node => {
70
40
  const pagePath = path
71
41
  .join(node.parent.relativeDirectory, node.parent.name === 'index' ? '/' : node.parent.name)
@@ -87,18 +57,6 @@ exports.createPages = async ({graphql, actions}, themeOptions) => {
87
57
  const code = await mdx(node.rawBody)
88
58
  const {frontmatter} = extractExports(code)
89
59
 
90
- // Validate checklist frontmatter
91
- for (const schemaKey in checklistSchemas) {
92
- const checklistKey = schemaKey.replace('Schema', 'Checklist')
93
- if (checklistKey in frontmatter) {
94
- try {
95
- validateChecklist(frontmatter[checklistKey], checklistSchemas[schemaKey])
96
- } catch (error) {
97
- throw new Error(`Invalid checklist: ${checklistKey} in ${fileRelativePath}\n${error.message}`)
98
- }
99
- }
100
- }
101
-
102
60
  actions.createPage({
103
61
  path: pagePath,
104
62
  component: node.fileAbsolutePath,
@@ -117,6 +75,40 @@ exports.createPages = async ({graphql, actions}, themeOptions) => {
117
75
  )
118
76
  }
119
77
 
78
+ exports.onPostBuild = async ({graphql}) => {
79
+ try {
80
+ const {data} = await graphql(`
81
+ query {
82
+ allSitePage(filter: {context: {frontmatter: {componentId: {ne: null}, status: {ne: null}}}}) {
83
+ nodes {
84
+ path
85
+ context {
86
+ frontmatter {
87
+ componentId
88
+ status
89
+ }
90
+ }
91
+ }
92
+ }
93
+ }
94
+ `)
95
+
96
+ const components = data.allSitePage.nodes.map(node => {
97
+ return {
98
+ id: node.context.frontmatter.componentId,
99
+ path: node.path,
100
+ status: node.context.frontmatter.status.toLowerCase()
101
+ }
102
+ })
103
+
104
+ fs.writeFileSync(path.resolve(process.cwd(), 'public/components.json'), JSON.stringify(components))
105
+ } catch (error) {
106
+ // This is not necessarily an error, so we just log a warning instead of failing the build.
107
+ // Some sites won't have any markdown files with `componentId` frontmatter and that's okay.
108
+ console.warn('Unable to build components.json')
109
+ }
110
+ }
111
+
120
112
  function getEditUrl(repo, filePath, defaultBranch) {
121
113
  return `https://github.com/${repo.user}/${repo.project}/edit/${defaultBranch}/${filePath}`
122
114
  }
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@primer/gatsby-theme-doctocat",
3
- "version": "2.1.0",
3
+ "version": "3.1.1",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "scripts": {
7
7
  "test": "jest",
8
- "lint": "eslint '**/*.js'",
8
+ "lint": "eslint '**/*.{js,ts,tsx}'",
9
9
  "lint:fix": "yarn lint -- --fix"
10
10
  },
11
11
  "prettier": "@github/prettier-config",
@@ -60,7 +60,6 @@
60
60
  "github-slugger": "^1.2.1",
61
61
  "html-react-parser": "^1.4.0",
62
62
  "jest": "^24.9.0",
63
- "jsonschema": "^1.4.0",
64
63
  "lodash.debounce": "4.0.8",
65
64
  "lodash.uniqby": "^4.7.0",
66
65
  "pkg-up": "^3.1.0",
@@ -76,7 +75,6 @@
76
75
  "react-live": "^2.1.2",
77
76
  "react-measure": "^2.3.0",
78
77
  "read-pkg-up": "^6.0.0",
79
- "require-glob": "^4.0.0",
80
78
  "sentence-case": "^2.1.1",
81
79
  "styled-components": "^4.3.2",
82
80
  "styled-system": "^5.0.18",
@@ -24,9 +24,9 @@ function ClipboardCopy({value}) {
24
24
  sx={{px: 2}}
25
25
  >
26
26
  {copied ? (
27
- <StyledOcticon icon={CheckIcon} color="success.fg" />
27
+ <StyledOcticon icon={CheckIcon} sx={{color: 'success.fg'}} />
28
28
  ) : (
29
- <StyledOcticon icon={CopyIcon} color="fg.muted" />
29
+ <StyledOcticon icon={CopyIcon} sx={{color: 'fg.muted'}} />
30
30
  )}
31
31
  </Button>
32
32
  )
@@ -24,7 +24,7 @@ function Code({className, children, live, noinline}) {
24
24
  width: '100%'
25
25
  }}
26
26
  >
27
- <Absolute top={0} right={0} p={2}>
27
+ <Absolute sx={{top: 0, right: 0, p: 2}}>
28
28
  <ClipboardCopy value={code} />
29
29
  </Absolute>
30
30
  <Highlight {...defaultProps} Prism={Prism} code={code} language={language} theme={githubTheme}>
@@ -20,8 +20,7 @@ function Contributors({contributors}) {
20
20
  <Link
21
21
  key={contributor.login}
22
22
  href={`https://github.com/${contributor.login}`}
23
- lineHeight="condensedUltra"
24
- sx={{mr: 2}}
23
+ sx={{mr: 2, lineHeight: 'condensedUltra'}}
25
24
  >
26
25
  <Tooltip key={contributor.login} aria-label={contributor.login}>
27
26
  <Avatar src={`https://github.com/${contributor.login}.png?size=40`} alt={contributor.login} />
@@ -26,7 +26,7 @@ function DoDontBase({children, title, icon: Icon, iconBg}) {
26
26
  return (
27
27
  <Box display="flex" flexDirection="column">
28
28
  <Box display="flex" alignSelf="start" flexDirection="row" alignItems="center" mb="2">
29
- <StyledOcticon icon={Icon} color={iconBg} />
29
+ <StyledOcticon icon={Icon} sx={{color: iconBg}} />
30
30
  <Text fontWeight="bold" color="fg.default" ml={2}>
31
31
  {title}
32
32
  </Text>
@@ -23,12 +23,8 @@ function Drawer({isOpen, onDismiss, children}) {
23
23
  animate={{opacity: 1}}
24
24
  exit={{opacity: 0}}
25
25
  transition={{type: 'tween'}}
26
- top={0}
27
- right={0}
28
- bottom={0}
29
- left={0}
30
- bg="rgba(0, 0, 0, 0.5)"
31
26
  onClick={() => onDismiss()}
27
+ sx={{top: 0, right: 0, bottom: 0, left: 0, bg: 'rgba(0, 0, 0, 0.5)'}}
32
28
  />
33
29
 
34
30
  <Fixed
@@ -38,12 +34,8 @@ function Drawer({isOpen, onDismiss, children}) {
38
34
  animate={{x: 0}}
39
35
  exit={{x: '100%'}}
40
36
  transition={{type: 'tween', duration: 0.2}}
41
- width={300}
42
- top={0}
43
- right={0}
44
- bottom={0}
45
- bg="gray.0"
46
37
  style={{zIndex: 1}}
38
+ sx={{width: 300, top: 0, right: 0, bottom: 0, bg: 'gray.0'}}
47
39
  >
48
40
  {children}
49
41
  </Fixed>
@@ -15,10 +15,10 @@ function HeroLayout({children, pageContext}) {
15
15
  }
16
16
 
17
17
  return (
18
- <Flex flexDirection="column" minHeight="100vh">
18
+ <Flex sx={{flexDirection: 'column', minHeight: '100vh'}}>
19
19
  <Head />
20
20
  <Header />
21
- <Flex flex="1 1 auto" flexDirection="row">
21
+ <Flex sx={{flex: '1 1 auto', flexDirection: 'row'}}>
22
22
  <Box display={['none', null, null, 'block']}>
23
23
  <Sidebar />
24
24
  </Box>
@@ -10,7 +10,7 @@ function Hero() {
10
10
  <ThemeProvider colorMode="night" nightScheme="dark_dimmed">
11
11
  <Box bg="canvas.default" py={6}>
12
12
  <Container>
13
- <Heading as="h1" color="accent.fg" fontSize={7} m={0}>
13
+ <Heading as="h1" sx={{color: 'accent.fg', fontSize: 7, m: 0}}>
14
14
  {title}
15
15
  </Heading>
16
16
  <Text as="p" m={0} color="fg.default" fontSize={4}>
@@ -3,10 +3,8 @@ import React from 'react'
3
3
 
4
4
  function ImageContainer({children}) {
5
5
  return (
6
- <BorderBox p={6} bg="gray.1">
7
- <Flex justifyContent="center" sx={{img: {maxWidth: '100%'}}}>
8
- {children}
9
- </Flex>
6
+ <BorderBox sx={{p: 6, bg: 'gray.1'}}>
7
+ <Flex sx={{img: {maxWidth: '100%'}, justifyContent: 'center'}}>{children}</Flex>
10
8
  </BorderBox>
11
9
  )
12
10
  }
@@ -1,7 +1,6 @@
1
1
  import componentMetadata from '@primer/component-metadata'
2
2
  import {BorderBox, Box, Flex, Grid, Heading, Position, Text} from '@primer/components'
3
3
  import React from 'react'
4
- import Checklists from './checklists'
5
4
  import Head from './head'
6
5
  import Header, {HEADER_HEIGHT} from './header'
7
6
  import PageFooter from './page-footer'
@@ -27,10 +26,10 @@ function Layout({children, pageContext}) {
27
26
  }
28
27
 
29
28
  return (
30
- <Flex flexDirection="column" minHeight="100vh">
29
+ <Flex sx={{flexDirection: 'column', minHeight: '100vh'}}>
31
30
  <Head title={title} description={description} />
32
31
  <Header />
33
- <Flex flex="1 1 auto" flexDirection="row" css={{zIndex: 0}}>
32
+ <Flex css={{zIndex: 0}} sx={{flex: '1 1 auto', flexDirection: 'row'}}>
34
33
  <Box display={['none', null, null, 'block']}>
35
34
  <Sidebar />
36
35
  </Box>
@@ -46,12 +45,16 @@ function Layout({children, pageContext}) {
46
45
  >
47
46
  {pageContext.tableOfContents.items ? (
48
47
  <Position
49
- sx={{width: 220, flex: '0 0 auto', marginLeft: 6}}
50
- display={['none', null, 'block']}
48
+ sx={{
49
+ width: 220,
50
+ flex: '0 0 auto',
51
+ marginLeft: 6,
52
+ display: ['none', null, 'block'],
53
+ position: 'sticky',
54
+ top: HEADER_HEIGHT + 48,
55
+ maxHeight: `calc(100vh - ${HEADER_HEIGHT}px - 48px)`
56
+ }}
51
57
  css={{gridArea: 'table-of-contents', overflow: 'auto'}}
52
- position="sticky"
53
- top={HEADER_HEIGHT + 24}
54
- maxHeight={`calc(100vh - ${HEADER_HEIGHT}px - 24px)`}
55
58
  >
56
59
  <Text display="inline-block" fontWeight="bold" mb={1}>
57
60
  On this page
@@ -62,7 +65,7 @@ function Layout({children, pageContext}) {
62
65
  <Box width="100%" maxWidth="960px">
63
66
  <Box mb={4}>
64
67
  <Flex sx={{alignItems: 'center'}}>
65
- <Heading as="h1" mr={2}>
68
+ <Heading as="h1" sx={{mr: 2}}>
66
69
  {title}
67
70
  </Heading>{' '}
68
71
  {status ? <StatusLabel status={status} /> : null}
@@ -74,11 +77,13 @@ function Layout({children, pageContext}) {
74
77
  ) : null}
75
78
  {source || storybook ? (
76
79
  <Grid
77
- py={2}
78
- gridGap={[1, null, 3]}
79
- gridAutoFlow={['row', null, 'column']}
80
- gridAutoColumns="max-content"
81
- gridAutoRows="max-content"
80
+ sx={{
81
+ py: 2,
82
+ gridGap: [1, null, 3],
83
+ gridAutoFlow: ['row', null, 'column'],
84
+ gridAutoColumns: 'max-content',
85
+ gridAutoRows: 'max-content'
86
+ }}
82
87
  >
83
88
  {source ? <SourceLink href={source} /> : null}
84
89
  {storybook ? <StorybookLink href={storybook} /> : null}
@@ -86,9 +91,11 @@ function Layout({children, pageContext}) {
86
91
  ) : null}
87
92
  </Box>
88
93
  {pageContext.tableOfContents.items ? (
89
- <BorderBox display={['block', null, 'none']} mb={5} borderColor="border.muted" bg="canvas.subtle">
94
+ <BorderBox
95
+ sx={{display: ['block', null, 'none'], mb: 5, borderColor: 'border.muted', bg: 'canvas.subtle'}}
96
+ >
90
97
  <Box p={3}>
91
- <Flex flexDirection="row" justifyContent="space-between" alignItems="center">
98
+ <Flex sx={{flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center'}}>
92
99
  <Text fontWeight="bold">On this page</Text>
93
100
  </Flex>
94
101
  </Box>
@@ -98,7 +105,6 @@ function Layout({children, pageContext}) {
98
105
  </BorderBox>
99
106
  ) : null}
100
107
  {children}
101
- <Checklists frontmatter={pageContext.frontmatter} />
102
108
  <PageFooter
103
109
  editUrl={pageContext.editUrl}
104
110
  contributors={pageContext.contributors.concat(additionalContributors.map(login => ({login})))}
@@ -40,7 +40,7 @@ function LiveCode({code, language, noinline}) {
40
40
  const handleChange = updatedLiveCode => setLiveCode(updatedLiveCode)
41
41
 
42
42
  return (
43
- <Flex flexDirection="column" mb={3}>
43
+ <Flex sx={{flexDirection: 'column', mb: 3}}>
44
44
  <LiveProvider scope={scope} code={liveCode} transformCode={languageTransformers[language]} noInline={noinline}>
45
45
  <Flex
46
46
  sx={{
@@ -70,7 +70,7 @@ function LiveCode({code, language, noinline}) {
70
70
  borderColor: theme.colors.border.default
71
71
  }}
72
72
  />
73
- <Absolute top={0} right={0} p={2}>
73
+ <Absolute sx={{top: 0, right: 0, p: 2}}>
74
74
  <ClipboardCopy value={liveCode} />
75
75
  </Absolute>
76
76
  </Relative>
@@ -38,19 +38,14 @@ function MobileSearch({isOpen, onDismiss}) {
38
38
  <AnimatePresence>
39
39
  {isOpen ? (
40
40
  <FocusOn returnFocus={true} onEscapeKey={() => handleDismiss()}>
41
- <Fixed top={0} left={0} right={0} bottom={0} zIndex={1}>
41
+ <Fixed sx={{top: 0, left: 0, right: 0, bottom: 0, zIndex: 1}}>
42
42
  <Absolute
43
43
  as={motion.div}
44
44
  initial={{opacity: 0}}
45
45
  animate={{opacity: 1}}
46
46
  exit={{opacity: 0}}
47
- top={0}
48
- left={0}
49
- right={0}
50
- bottom={0}
51
- bg="primer.canvas.backdrop"
52
- zIndex={-1}
53
47
  onClick={handleDismiss}
48
+ sx={{top: 0, left: 0, right: 0, bottom: 0, bg: 'primer.canvas.backdrop', zIndex: -1}}
54
49
  />
55
50
  <Downshift
56
51
  inputValue={query}
@@ -72,7 +67,7 @@ function MobileSearch({isOpen, onDismiss}) {
72
67
  height: isMenuOpen ? '100%' : 'auto'
73
68
  })}
74
69
  >
75
- <Flex bg="canvas.default" color="fg.default" p={3} flex="0 0 auto">
70
+ <Flex sx={{bg: 'canvas.default', color: 'fg.default', p: 3, flex: '0 0 auto'}}>
76
71
  <motion.div
77
72
  initial={{scaleX: 0.1}}
78
73
  animate={{scaleX: 1}}
@@ -83,7 +78,7 @@ function MobileSearch({isOpen, onDismiss}) {
83
78
  <TextInput
84
79
  {...getInputProps({
85
80
  placeholder: `Search`,
86
- width: '100%'
81
+ sx: {width: '100%'}
87
82
  })}
88
83
  />
89
84
  </motion.div>
@@ -44,15 +44,13 @@ function NavDrawer({isOpen, onDismiss}) {
44
44
  return (
45
45
  <Drawer isOpen={isOpen} onDismiss={onDismiss}>
46
46
  <Flex
47
- flexDirection="column"
48
- height="100%"
49
- bg="canvas.default"
50
47
  style={{overflow: 'auto', WebkitOverflowScrolling: 'touch'}}
48
+ sx={{flexDirection: 'column', height: '100%', bg: 'canvas.default'}}
51
49
  >
52
- <Flex flexDirection="column" flex="0 0 auto" color="fg.default" bg="canvas.default">
53
- <BorderBox borderWidth={0} borderRadius={0} borderBottomWidth={1} borderColor="border.muted">
54
- <Flex py={3} pl={4} pr={3} alignItems="center" justifyContent="space-between">
55
- <Link href="https://primer.style" fontFamily="mono" color="inherit">
50
+ <Flex sx={{flexDirection: 'column', flex: '0 0 auto', color: 'fg.default', bg: 'canvas.default'}}>
51
+ <BorderBox sx={{borderWidth: 0, borderRadius: 0, borderBottomWidth: 1, borderColor: 'border.muted'}}>
52
+ <Flex sx={{py: 3, pl: 4, pr: 3, alignItems: 'center', justifyContent: 'space-between'}}>
53
+ <Link href="https://primer.style" sx={{fontFamily: 'mono', color: 'inherit'}}>
56
54
  Primer
57
55
  </Link>
58
56
  <Button aria-label="Close" onClick={onDismiss}>
@@ -60,14 +58,18 @@ function NavDrawer({isOpen, onDismiss}) {
60
58
  </Button>
61
59
  </Flex>
62
60
  </BorderBox>
63
- <Flex flexDirection="column">
61
+ <Flex sx={{flexDirection: 'column'}}>
64
62
  <PrimerNavItems items={primerNavItems} />
65
63
  </Flex>
66
64
  </Flex>
67
65
  {navItems.length > 0 ? (
68
66
  <ThemeProvider colorMode="day">
69
- <Flex flexDirection="column" flex="1 0 auto" color="fg.default" bg="canvas.default">
70
- <Link as={GatsbyLink} to="/" display="inline-block" color="inherit" fontFamily="mono" mx={4} my={4}>
67
+ <Flex sx={{flexDirection: 'column', flex: '1 0 auto', color: 'fg.default', bg: 'canvas.default'}}>
68
+ <Link
69
+ as={GatsbyLink}
70
+ to="/"
71
+ sx={{display: 'inline-block', color: 'inherit', fontFamily: 'mono', mx: 4, my: 4}}
72
+ >
71
73
  {siteMetadata.title}
72
74
  </Link>
73
75
  <NavItems items={navItems} />
@@ -84,25 +86,21 @@ function PrimerNavItems({items}) {
84
86
  return (
85
87
  <BorderBox
86
88
  key={item.title}
87
- borderWidth={0}
88
- borderRadius={0}
89
- borderTopWidth={index !== 0 ? 1 : 0}
90
- borderColor="border.muted"
91
- p={4}
89
+ sx={{borderWidth: 0, borderRadius: 0, borderTopWidth: index !== 0 ? 1 : 0, borderColor: 'border.muted', p: 4}}
92
90
  >
93
91
  {item.children ? (
94
92
  <Details key={index}>
95
93
  {({open, toggle}) => (
96
94
  <>
97
95
  <summary onClick={toggle} style={{cursor: 'pointer'}}>
98
- <Flex alignItems="center" justifyContent="space-between">
96
+ <Flex sx={{alignItems: 'center', justifyContent: 'space-between'}}>
99
97
  <Text>{item.title}</Text>
100
98
  {open ? <ChevronUpIcon /> : <ChevronDownIcon />}
101
99
  </Flex>
102
100
  </summary>
103
- <Flex flexDirection="column" mt={2}>
101
+ <Flex sx={{flexDirection: 'column', mt: 2}}>
104
102
  {item.children.map(child => (
105
- <Link key={child.title} href={child.url} py={1} mt={2} fontSize={1} color="inherit">
103
+ <Link key={child.title} href={child.url} sx={{py: 1, mt: 2, fontSize: 1, color: 'inherit'}}>
106
104
  {child.title}
107
105
  </Link>
108
106
  ))}
@@ -111,7 +109,7 @@ function PrimerNavItems({items}) {
111
109
  )}
112
110
  </Details>
113
111
  ) : (
114
- <Link key={index} href={item.url} color="inherit" display="block">
112
+ <Link key={index} href={item.url} sx={{color: 'inherit', display: 'block'}}>
115
113
  {item.title}
116
114
  </Link>
117
115
  )}
@@ -9,7 +9,7 @@ function NavDropdown({title, children}) {
9
9
  <Details {...getDetailsProps()}>
10
10
  <summary style={{cursor: 'pointer'}}>
11
11
  <Text>{title}</Text>
12
- <StyledOcticon icon={TriangleDownIcon} ml={1} />
12
+ <StyledOcticon icon={TriangleDownIcon} sx={{ml: 1}} />
13
13
  </summary>
14
14
  <Box position="absolute">
15
15
  <Box
@@ -38,7 +38,13 @@ function NavItems({items}) {
38
38
  p={4}
39
39
  >
40
40
  <Box display="flex" flexDirection="column">
41
- <NavLink as={GatsbyLink} to={item.url} activeClassName="active" partiallyActive={true} color="inherit">
41
+ <NavLink
42
+ as={GatsbyLink}
43
+ to={item.url}
44
+ activeClassName="active"
45
+ partiallyActive={true}
46
+ sx={{color: 'inherit'}}
47
+ >
42
48
  {item.title}
43
49
  </NavLink>
44
50
  {item.children ? (
@@ -49,10 +55,12 @@ function NavItems({items}) {
49
55
  as={GatsbyLink}
50
56
  to={child.url}
51
57
  activeClassName="active"
52
- display="block"
53
- py={1}
54
- mt={2}
55
- fontSize={1}
58
+ sx={{
59
+ display: 'block',
60
+ py: 1,
61
+ mt: 2,
62
+ fontSize: 1
63
+ }}
56
64
  >
57
65
  {child.title}
58
66
  </NavLink>
@@ -64,10 +72,10 @@ function NavItems({items}) {
64
72
  ))}
65
73
  {repositoryUrl ? (
66
74
  <Box borderWidth={0} borderTopWidth={1} borderRadius={0} borderStyle="solid" borderColor="border.default" p={4}>
67
- <Link href={repositoryUrl} color="inherit">
75
+ <Link href={repositoryUrl} sx={{color: 'inherit'}}>
68
76
  <Box display="flex" justifyContent="space-between" alignItems="center">
69
77
  GitHub
70
- <StyledOcticon icon={LinkExternalIcon} color="fg.muted" />
78
+ <StyledOcticon icon={LinkExternalIcon} sx={{color: 'fg.muted'}} />
71
79
  </Box>
72
80
  </Link>
73
81
  </Box>
@@ -5,11 +5,11 @@ import Contributors from './contributors'
5
5
 
6
6
  function PageFooter({editUrl, contributors}) {
7
7
  return editUrl || contributors.length > 0 ? (
8
- <BorderBox borderWidth={0} borderTopWidth={1} borderRadius={0} mt={8} py={5}>
9
- <Grid gridGap={4}>
8
+ <BorderBox sx={{borderWidth: 0, borderTopWidth: 1, borderRadius: 0, mt: 8, py: 5}}>
9
+ <Grid sx={{gridGap: 4}}>
10
10
  {editUrl ? (
11
11
  <Link href={editUrl}>
12
- <StyledOcticon icon={PencilIcon} mr={2} />
12
+ <StyledOcticon icon={PencilIcon} sx={{mr: 2}} />
13
13
  Edit this page on GitHub
14
14
  </Link>
15
15
  ) : null}
@@ -64,14 +64,16 @@ function Search() {
64
64
  >
65
65
  <ThemeProvider colorMode="day">
66
66
  <BorderBox
67
- minWidth={300}
68
- maxHeight="70vh"
69
- p={2}
70
- boxShadow="shadow.large"
71
- borderColor="border.muted"
72
- bg="canvas.overlay"
73
- borderRadius="12px"
74
67
  style={{overflow: 'auto'}}
68
+ sx={{
69
+ minWidth: 300,
70
+ maxHeight: '70vh',
71
+ p: 2,
72
+ boxShadow: 'shadow.large',
73
+ borderColor: 'border.muted',
74
+ bg: 'canvas.overlay',
75
+ borderRadius: '12px'
76
+ }}
75
77
  >
76
78
  <SearchResults results={results} getItemProps={getItemProps} highlightedIndex={highlightedIndex} />
77
79
  </BorderBox>
@@ -33,21 +33,20 @@ function Sidebar() {
33
33
 
34
34
  return (
35
35
  <Position
36
- position="sticky"
37
- top={HEADER_HEIGHT}
38
- height={`calc(100vh - ${HEADER_HEIGHT}px)`}
39
- minWidth={260}
40
- bg="canvas.subtle"
36
+ sx={{
37
+ position: 'sticky',
38
+ top: HEADER_HEIGHT,
39
+ height: `calc(100vh - ${HEADER_HEIGHT}px)`,
40
+ minWidth: 260,
41
+ bg: 'canvas.subtle'
42
+ }}
41
43
  >
42
44
  <BorderBox
43
45
  {...scrollContainerProps}
44
- borderWidth={0}
45
- borderRightWidth={1}
46
- borderRadius={0}
47
- height="100%"
48
46
  style={{overflow: 'auto'}}
47
+ sx={{borderWidth: 0, borderRightWidth: 1, borderRadius: 0, height: '100%'}}
49
48
  >
50
- <Flex flexDirection="column">
49
+ <Flex sx={{flexDirection: 'column'}}>
51
50
  <NavItems items={navItems} />
52
51
  </Flex>
53
52
  </BorderBox>
@@ -14,7 +14,7 @@ function getStatusColor(status) {
14
14
 
15
15
  function StatusLabel({status}) {
16
16
  return (
17
- <Label outline color={getStatusColor(status)} borderColor={getStatusColor(status)}>
17
+ <Label outline sx={{color: getStatusColor(status), borderColor: getStatusColor(status)}}>
18
18
  {status}
19
19
  </Label>
20
20
  )
@@ -1,6 +1,7 @@
1
1
  import {MDXProvider} from '@mdx-js/react'
2
2
  import {Link, ThemeProvider} from '@primer/components'
3
3
  import React from 'react'
4
+ import mdxComponents from '../mdx-components'
4
5
  import Blockquote from './blockquote'
5
6
  import Caption from './caption'
6
7
  import Code from './code'
@@ -36,13 +37,14 @@ const components = {
36
37
  ol: List.withComponent('ol'),
37
38
  dl: DescriptionList,
38
39
 
39
- // Shortcodes (https://mdxjs.com/blog/shortcodes)
40
+ // Custom components
40
41
  Note,
41
42
  Do,
42
43
  Dont,
43
44
  DoDontContainer,
44
45
  Caption,
45
- ImageContainer
46
+ ImageContainer,
47
+ ...mdxComponents
46
48
  }
47
49
 
48
50
  function wrapRootElement({element}) {
@@ -0,0 +1,2 @@
1
+ // Users can shadow this file to add custom components to scope of all MDX files.
2
+ export default {}
@@ -1,96 +0,0 @@
1
- import {validateChecklistSchema, validateChecklist} from '../validate-checklists'
2
-
3
- describe('validateChecklistSchema()', () => {
4
- const valid = [
5
- {
6
- title: 'Example checklist',
7
- items: []
8
- },
9
- {
10
- title: 'Example checklist',
11
- items: [{id: 'example', description: 'Example item'}]
12
- },
13
- {
14
- title: 'Example checklist',
15
- items: [{id: 'example', description: 'Example item', someMetadata: 1}]
16
- }
17
- ]
18
-
19
- const invalid = [
20
- {
21
- title: 'Example checklist'
22
- },
23
- {
24
- title: 'Example checklist',
25
- items: [{description: 'Example item'}]
26
- },
27
- {
28
- title: 1,
29
- items: []
30
- },
31
- {
32
- title: 'Example checklist',
33
- items: 1
34
- }
35
- ]
36
-
37
- for (const checklistSchema of valid) {
38
- test(`should validate ${JSON.stringify(checklistSchema)}`, () => {
39
- expect(() => validateChecklistSchema(checklistSchema)).not.toThrow()
40
- })
41
- }
42
-
43
- for (const checklistSchema of invalid) {
44
- test(`should not validate ${JSON.stringify(checklistSchema)}`, () => {
45
- expect(() => validateChecklistSchema(checklistSchema)).toThrow()
46
- })
47
- }
48
- })
49
-
50
- describe('validateChecklist()', () => {
51
- const valid = [
52
- {
53
- checklist: {dependenciesReviewed: true},
54
- checklistSchema: {
55
- title: 'Example checklist',
56
- items: [{id: 'dependenciesReviewed', description: 'Third-party dependencies have been reviewed'}]
57
- }
58
- }
59
- ]
60
-
61
- const invalid = [
62
- {
63
- checklist: {reviewed: true},
64
- checklistSchema: {
65
- title: 'Example checklist',
66
- items: [{id: 'dependenciesReviewed', description: 'Third-party dependencies have been reviewed'}]
67
- }
68
- },
69
- {
70
- checklist: {dependenciesReviewed: 1},
71
- checklistSchema: {
72
- title: 'Example checklist',
73
- items: [{id: 'dependenciesReviewed', description: 'Third-party dependencies have been reviewed'}]
74
- }
75
- },
76
- {
77
- checklist: ['dependenciesReviewed'],
78
- checklistSchema: {
79
- title: 'Example checklist',
80
- items: [{id: 'dependenciesReviewed', description: 'Third-party dependencies have been reviewed'}]
81
- }
82
- }
83
- ]
84
-
85
- for (const {checklist, checklistSchema} of valid) {
86
- test(`should validate ${JSON.stringify(checklist)}`, () => {
87
- expect(() => validateChecklist(checklist, checklistSchema)).not.toThrow()
88
- })
89
- }
90
-
91
- for (const {checklist, checklistSchema} of invalid) {
92
- test(`should not validate ${JSON.stringify(checklist)}`, () => {
93
- expect(() => validateChecklist(checklist, checklistSchema)).toThrow()
94
- })
95
- }
96
- })
@@ -1,13 +0,0 @@
1
- module.exports = {
2
- title: 'Component checklist',
3
- items: [
4
- {
5
- id: 'dependenciesReviewed',
6
- description: 'All third-party dependencies have been reviewed.'
7
- },
8
- {
9
- id: 'componentStatusDocumented',
10
- description: 'Component status is documented.'
11
- }
12
- ]
13
- }
@@ -1,58 +0,0 @@
1
- import React from 'react'
2
- import {H2} from './heading'
3
- import {Box, StyledOcticon} from '@primer/components'
4
- import {CheckCircleFillIcon, CircleIcon} from '@primer/octicons-react'
5
- import GithubSlugger from 'github-slugger'
6
-
7
- export type ChecklistSchema = {
8
- title: string
9
- items: Array<{id: string; description: string}>
10
- }
11
-
12
- type ChecklistProps = {
13
- checklist: {[id: string]: boolean}
14
- schema: ChecklistSchema
15
- }
16
-
17
- function Checklist({checklist, schema}: ChecklistProps) {
18
- const id = React.useMemo(() => {
19
- const slugger = new GithubSlugger()
20
- return slugger.slug(schema.title)
21
- }, [schema.title])
22
- return (
23
- <>
24
- <H2 id={id}>{schema.title}</H2>
25
- <Box aria-describedby={id} as="ul" display="grid" gridGap={2} p={0} m={0}>
26
- {schema.items.map(({id, description}) => {
27
- const checked = Boolean(checklist[id])
28
- return (
29
- <ChecklistItem checked={checked} key={id}>
30
- {description}
31
- </ChecklistItem>
32
- )
33
- })}
34
- </Box>
35
- </>
36
- )
37
- }
38
-
39
- type ChecklistItemProps = {
40
- checked: boolean
41
- }
42
-
43
- function ChecklistItem({checked, children}: React.PropsWithChildren<ChecklistItemProps>) {
44
- return (
45
- <Box as="li" display="grid" gridTemplateColumns="auto 1fr" gridGap={2} sx={{listStyleType: 'none'}}>
46
- <Box height="24px" display="flex" alignItems="center">
47
- {checked ? (
48
- <StyledOcticon aria-label="Completed" icon={CheckCircleFillIcon} color="success.fg" />
49
- ) : (
50
- <StyledOcticon aria-label="To do" icon={CircleIcon} color="border.default" />
51
- )}
52
- </Box>
53
- <span>{children}</span>
54
- </Box>
55
- )
56
- }
57
-
58
- export default Checklist
@@ -1,48 +0,0 @@
1
- import {graphql, useStaticQuery} from 'gatsby'
2
- import React from 'react'
3
- import Checklist from './checklist'
4
-
5
- type ChecklistSchemaQuery = {
6
- allChecklistSchema: {
7
- nodes: Array<{
8
- name: string
9
- title: string
10
- items: Array<{id: string; description: string}>
11
- }>
12
- }
13
- }
14
-
15
- function Checklists({frontmatter}: {frontmatter: Record<string, any>}) {
16
- const data = useStaticQuery<ChecklistSchemaQuery>(graphql`
17
- query ChecklistSchemaQuery {
18
- allChecklistSchema {
19
- nodes {
20
- name
21
- title
22
- items {
23
- id
24
- description
25
- }
26
- }
27
- }
28
- }
29
- `)
30
-
31
- const checklistSchemas = data.allChecklistSchema.nodes
32
-
33
- const checklists = checklistSchemas
34
- .map(schema => {
35
- const key = `${schema.name}Checklist`
36
-
37
- if (!(key in frontmatter)) {
38
- return null
39
- }
40
-
41
- return <Checklist checklist={frontmatter[key]} schema={schema} />
42
- })
43
- .filter(Boolean)
44
-
45
- return checklists
46
- }
47
-
48
- export default Checklists
@@ -1,62 +0,0 @@
1
- const validate = require('jsonschema').validate
2
-
3
- exports.validateChecklistSchema = checklistSchema => {
4
- const jsonSchema = {
5
- type: 'object',
6
- properties: {
7
- title: {
8
- type: 'string'
9
- },
10
- items: {
11
- type: 'array',
12
- items: {
13
- type: 'object',
14
- properties: {
15
- id: {
16
- type: 'string'
17
- },
18
- description: {
19
- type: 'string'
20
- }
21
- },
22
- required: ['id', 'description']
23
- }
24
- }
25
- },
26
- required: ['title', 'items']
27
- }
28
-
29
- const {errors} = validate(checklistSchema, jsonSchema)
30
-
31
- if (errors.length > 0) {
32
- const errorMessage = errors.map(error => `• ${error.message}`).join('\n')
33
- throw new Error(`Errors:\n${errorMessage}`)
34
- }
35
- }
36
-
37
- exports.validateChecklist = (checklist, checklistSchema) => {
38
- const jsonSchema = checklistSchemaToJsonSchema(checklistSchema)
39
-
40
- const {errors} = validate(checklist, jsonSchema)
41
-
42
- if (errors.length > 0) {
43
- const errorMessage = errors.map(error => `• ${error.message}`).join('\n')
44
- throw new Error(`Errors:\n${errorMessage}`)
45
- }
46
- }
47
-
48
- function checklistSchemaToJsonSchema(checklistSchema) {
49
- const ids = checklistSchema.items.map(item => item.id)
50
-
51
- const properties = ids.reduce((properties, id) => {
52
- properties[id] = {type: 'boolean'}
53
- return properties
54
- }, {})
55
-
56
- return {
57
- type: 'object',
58
- properties,
59
- required: ids,
60
- additionalProperties: false
61
- }
62
- }