Skip to content

Commit bdaf24d

Browse files
committed
Display contributors at the bottom of every page (#67)
* Create contributors component * Fix import * Create PageFooter component * Use correct pluralization of "contributors" * Format the date * Update page footer component * Add comment about contributors array * Get avatar url by login * Fix page footer variable references * Accept additional contributors through frontmatter * Add error handling * Check for latestCommit before rendering * Add tests for the contributors component * Run tests during CI * Add test for page footer * Add documentation * Don't render duplicate contributors * Reduce padding
1 parent 44d6421 commit bdaf24d

File tree

17 files changed

+3243
-1277
lines changed

17 files changed

+3243
-1277
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ jobs:
88
- uses: actions/setup-node@master
99
with:
1010
version: 10
11-
- run: yarn install
11+
- name: install
12+
run: yarn install
13+
- name: test
14+
run: yarn workspace @primer/gatsby-theme-doctocat test
1215
- uses: primer/publish@master
1316
env:
1417
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

docs/content/getting-started/index.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
---
22
title: Getting started
3+
additionalContributors:
4+
- ashygee
5+
- emplums
6+
- shawnbot
37
---
48

59
This guide will walk you through creating, customizing, and deploying a new site with Doctocat using our [template repository](https://github.com/primer/doctocat-template). If you have an existing repository where you would like to create a new site, we recommend using the Gatsby CLI instead. Check out the [Gatsby CLI guide](/getting-started/gatsby-cli) for more information.

docs/content/usage/customization.mdx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
title: Customization
33
---
44

5+
import {BorderBox} from '@primer/components'
6+
import {Contributors} from '@primer/gatsby-theme-doctocat'
7+
58
Here are a few ways you can customize your Doctocat site:
69

710
## Site metadata
@@ -66,6 +69,33 @@ module.exports = {
6669
}
6770
```
6871

72+
## Contributors
73+
74+
If you have the `repository` in `package.json` and `repoRootPath` in `gatsby-config.js` set up correctly (as described [above](#edit-on-github-link)), Doctocat will automatically display contributors on the bottom of every page, like so:
75+
76+
<BorderBox p={4} mb={3}>
77+
<Contributors
78+
contributors={[
79+
{
80+
login: 'colebemis',
81+
latestCommit: {
82+
url: '#',
83+
date: '2019-08-15T23:40:19Z',
84+
},
85+
},
86+
{
87+
login: 'emplums',
88+
latestCommit: {
89+
url: '#',
90+
date: '2019-08-14T00:19:54Z',
91+
},
92+
},
93+
]}
94+
/>
95+
</BorderBox>
96+
97+
These contributors are determined by commits. However, we know that commits aren't the only way to contribute. You can use [front matter](/usage/front-matter#additional-contributors) to give credit to people who aren't listed in the commit history but still contributed.
98+
6999
## Hero
70100

71101
To add a hero section to a page, you'll need to override the default layout component with Doctocat's `HeroLayout` component by exporting it from your MDX file:

docs/content/usage/front-matter.mdx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,15 @@ Doctocat comes with a few predefined statuses that have colors associated with t
4848
Custom statuses will render a gray dot:
4949

5050
<StatusLabel status="My custom status" />
51+
52+
## Additional contributors
53+
54+
If you have the `repository` in `package.json` and `repoRootPath` in `gatsby-config.js` setup correctly (as desribed in the [customization](/usage/customization#contributors) guide), Doctocat will automatically display contributors on the bottom of every page. These contributors are determined by commits. However, we know that commits aren't the only way to contribute. To give credit to people who aren't listed in the commit history but still contributed, use the `additionalContributors` front matter variable to list their GitHub usernames, for example:
55+
56+
```markdown
57+
---
58+
additionalContributors:
59+
- ashygee
60+
- emplums
61+
---
62+
```

theme/babel.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
presets: ['@babel/preset-env', '@babel/preset-react'],
3+
}

theme/gatsby-node.js

Lines changed: 65 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,12 @@
11
const path = require('path')
22
const readPkgUp = require('read-pkg-up')
33
const getPkgRepo = require('get-pkg-repo')
4-
const memoize = require('lodash.memoize')
5-
6-
const getRepo = memoize(() => {
7-
return getPkgRepo(readPkgUp.sync().package)
8-
})
9-
10-
function generateEditUrl(rootAbsolutePath, fileAbsolutePath) {
11-
try {
12-
const {domain, user, project} = getRepo()
13-
const fileRelativePath = path.relative(rootAbsolutePath, fileAbsolutePath)
14-
return `https://${domain}/${user}/${project}/edit/master/${fileRelativePath}`
15-
} catch (error) {
16-
console.warn(
17-
`[warning] An edit url could not be generated for ${fileAbsolutePath}`,
18-
)
19-
return null
20-
}
21-
}
4+
const axios = require('axios')
5+
const uniqBy = require('lodash.uniqby')
226

237
exports.createPages = async ({graphql, actions}, themeOptions) => {
8+
const repo = getPkgRepo(readPkgUp.sync().package)
9+
2410
const {data} = await graphql(`
2511
{
2612
allMdx {
@@ -38,29 +24,69 @@ exports.createPages = async ({graphql, actions}, themeOptions) => {
3824
}
3925
`)
4026

41-
data.allMdx.nodes.forEach(node => {
42-
const pagePath = path.join(
43-
node.parent.relativeDirectory,
44-
node.parent.name === 'index' ? '/' : node.parent.name,
45-
)
27+
// Turn every MDX file into a page.
28+
return Promise.all(
29+
data.allMdx.nodes.map(async node => {
30+
const pagePath = path.join(
31+
node.parent.relativeDirectory,
32+
node.parent.name === 'index' ? '/' : node.parent.name,
33+
)
34+
35+
const rootAbsolutePath = path.resolve(
36+
process.cwd(),
37+
themeOptions.repoRootPath || '.',
38+
)
39+
40+
const fileRelativePath = path.relative(
41+
rootAbsolutePath,
42+
node.fileAbsolutePath,
43+
)
4644

47-
const rootAbsolutePath = path.resolve(
48-
process.cwd(),
49-
themeOptions.repoRootPath || '.',
45+
const editUrl = getEditUrl(repo, fileRelativePath)
46+
47+
const contributors = await fetchContributors(repo, fileRelativePath)
48+
49+
actions.createPage({
50+
path: pagePath,
51+
component: node.fileAbsolutePath,
52+
context: {
53+
editUrl,
54+
contributors,
55+
tableOfContents: node.tableOfContents,
56+
// We don't need to add `frontmatter` to the page context here
57+
// because gatsby-plugin-mdx automatically does that.
58+
// Source: https://git.io/fjQDa
59+
},
60+
})
61+
}),
62+
)
63+
}
64+
65+
function getEditUrl(repo, filePath) {
66+
return `https://github.com/${repo.user}/${repo.project}/edit/master/${filePath}`
67+
}
68+
69+
async function fetchContributors(repo, filePath) {
70+
try {
71+
const {data} = await axios.get(
72+
`https://api.github.com/repos/${repo.user}/${repo.project}/commits?path=${filePath}`,
5073
)
5174

52-
const editUrl = generateEditUrl(rootAbsolutePath, node.fileAbsolutePath)
75+
const commits = data
76+
.map(commit => ({
77+
login: commit.author && commit.author.login,
78+
latestCommit: {
79+
date: commit.commit.author.date,
80+
url: commit.html_url,
81+
},
82+
}))
83+
.filter(contributor => Boolean(contributor.login))
5384

54-
actions.createPage({
55-
path: pagePath,
56-
component: node.fileAbsolutePath,
57-
context: {
58-
editUrl,
59-
tableOfContents: node.tableOfContents,
60-
// We don't need to add `frontmatter` to the page context here
61-
// because gatsby-plugin-mdx automatically does that.
62-
// Source: https://git.io/fjQDa
63-
},
64-
})
65-
})
85+
return uniqBy(commits, 'login')
86+
} catch (error) {
87+
console.error(
88+
`[ERROR] Unable to fetch contributors for ${filePath}. ${error.message}`,
89+
)
90+
return []
91+
}
6692
}

theme/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ export {default as Hero} from './src/components/hero'
77
export {default as HeroLayout} from './src/components/hero-layout'
88
export {default as Sidebar} from './src/components/sidebar'
99
export {default as StatusLabel} from './src/components/status-label'
10+
export {default as Contributors} from './src/components/contributors'

theme/jest.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
collectCoverage: true,
3+
collectCoverageFrom: ['src/**/*.js'],
4+
setupFilesAfterEnv: ['<rootDir>/setup-tests.js'],
5+
}

theme/package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
"version": "0.13.0",
44
"main": "index.js",
55
"license": "MIT",
6+
"scripts": {
7+
"test": "jest"
8+
},
69
"devDependencies": {
710
"gatsby": "^2.13.52",
811
"react": "^16.8.6",
@@ -14,12 +17,19 @@
1417
"react-dom": "16.8.x"
1518
},
1619
"dependencies": {
20+
"@babel/preset-env": "^7.5.5",
21+
"@babel/preset-react": "^7.0.0",
1722
"@mdx-js/mdx": "^1.0.21",
1823
"@mdx-js/react": "^1.0.21",
1924
"@primer/components": "^13.3.1",
2025
"@primer/octicons-react": "^9.1.1",
2126
"@styled-system/theme-get": "^5.0.12",
27+
"@testing-library/jest-dom": "^4.1.0",
28+
"@testing-library/react": "^9.1.3",
29+
"axios": "^0.19.0",
30+
"babel-jest": "^24.9.0",
2231
"copy-to-clipboard": "^3.2.0",
32+
"date-fns": "^2.0.1",
2333
"details-element-polyfill": "^2.4.0",
2434
"downshift": "^3.2.10",
2535
"find-up": "^4.1.0",
@@ -37,7 +47,10 @@
3747
"get-pkg-repo": "^4.1.0",
3848
"github-slugger": "^1.2.1",
3949
"html-react-parser": "^0.9.1",
50+
"jest": "^24.9.0",
51+
"lodash.uniqby": "^4.7.0",
4052
"pkg-up": "^3.1.0",
53+
"pluralize": "^8.0.0",
4154
"prism-react-renderer": "^0.1.7",
4255
"react-addons-text-content": "^0.0.4",
4356
"react-element-to-jsx-string": "^14.0.3",

theme/setup-tests.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import '@testing-library/jest-dom/extend-expect'

0 commit comments

Comments
 (0)