mirror of
https://github.com/zhigang1992/react.git
synced 2026-01-31 09:08:41 +08:00
Merge pull request #96 from unix/contributors
docs: show contributors on document site
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
version: 2
|
||||
jobs:
|
||||
docs:
|
||||
lint:
|
||||
docker:
|
||||
- image: circleci/node:12.0
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
- node_modules
|
||||
key: v2-dependencies-{{ checksum "package.json" }}
|
||||
|
||||
- run: yarn run now-build
|
||||
- run: yarn run lint
|
||||
|
||||
build:
|
||||
docker:
|
||||
@@ -49,5 +49,5 @@ workflows:
|
||||
version: 2
|
||||
build_and_test:
|
||||
jobs:
|
||||
- docs
|
||||
- lint
|
||||
- build
|
||||
|
||||
6
.nowignore
Normal file
6
.nowignore
Normal file
@@ -0,0 +1,6 @@
|
||||
.idea
|
||||
.git
|
||||
.DS_Store
|
||||
.env
|
||||
examples
|
||||
.circleci
|
||||
@@ -1,20 +1,35 @@
|
||||
import React, { useMemo } from 'react'
|
||||
import { Card, Link, Spacer, useTheme } from 'components'
|
||||
import { Card, Link, Spacer, Avatar, Tooltip, useTheme } from 'components'
|
||||
import AttributesTitle from './attributes-title'
|
||||
import VirtualAnchor from 'lib/components/anchor'
|
||||
import { useConfigs } from '../../config-context'
|
||||
import ContributorMetadatas from 'lib/data/contributors.json'
|
||||
const GithubURL = 'https://github.com/zeit-ui/react/blob/master'
|
||||
|
||||
export interface AttributesProps {
|
||||
edit: string
|
||||
}
|
||||
|
||||
export interface Contributor {
|
||||
name: string
|
||||
avatar: string
|
||||
url: string
|
||||
}
|
||||
|
||||
export type ContributorMeta = {
|
||||
[key: string]: Array<Contributor>
|
||||
}
|
||||
|
||||
const Attributes: React.FC<React.PropsWithChildren<AttributesProps>> = React.memo(({
|
||||
edit, children,
|
||||
}) => {
|
||||
const theme = useTheme()
|
||||
const { isChinese } = useConfigs()
|
||||
const link = useMemo(() => {
|
||||
return `https://github.com/zeit-ui/react/blob/master${edit || '/pages'}`
|
||||
const link = useMemo(() => `${GithubURL}${edit || '/pages'}`, [])
|
||||
const contributors = useMemo(() => {
|
||||
const key = edit.replace('/pages', 'pages')
|
||||
const users = (ContributorMetadatas as ContributorMeta)[key]
|
||||
return users || []
|
||||
}, [])
|
||||
|
||||
return (
|
||||
@@ -24,10 +39,22 @@ const Attributes: React.FC<React.PropsWithChildren<AttributesProps>> = React.mem
|
||||
<Card className="attr">
|
||||
{children}
|
||||
</Card>
|
||||
<Spacer y={1} />
|
||||
<Link color target="_blank" className="attributes-link" href={link} rel="nofollow">
|
||||
{isChinese ? '在 GitHub 上编辑此页面' : 'Edit this page on GitHub'}
|
||||
</Link>
|
||||
<Spacer y={3} />
|
||||
<h4 className="contributor-title">{isChinese ? '文档贡献者' : 'Contributors'}</h4>
|
||||
<div className="contributors">
|
||||
{contributors.map((user, index) => (
|
||||
<Tooltip text={<b>{user.name}</b>} key={`${user.url}-${index}`}>
|
||||
<Link color pure target="_blank" rel="nofollow" href={user.url}>
|
||||
<Avatar src={user.avatar} />
|
||||
</Link>
|
||||
</Tooltip>
|
||||
))}
|
||||
<Tooltip text={isChinese ? '在 GitHub 上编辑此页面' : 'Edit this page on GitHub'} type="dark">
|
||||
<Link color pure target="_blank" rel="nofollow" href={link}>
|
||||
<Avatar text="Add" />
|
||||
</Link>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<style global jsx>{`
|
||||
.attr table {
|
||||
@@ -46,10 +73,6 @@ const Attributes: React.FC<React.PropsWithChildren<AttributesProps>> = React.mem
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.attributes-link {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.attr table {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
@@ -105,6 +128,25 @@ const Attributes: React.FC<React.PropsWithChildren<AttributesProps>> = React.mem
|
||||
border-left: 1px solid transparent;
|
||||
}
|
||||
|
||||
.contributor-title {
|
||||
text-transform: uppercase;
|
||||
font-size: 1rem;
|
||||
letter-spacing: 1.5px;
|
||||
}
|
||||
|
||||
.contributors {
|
||||
padding-left: ${theme.layout.gap};
|
||||
padding-top: ${theme.layout.gap};
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.contributors :global(.tooltip) {
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: ${theme.layout.breakpointMobile}) {
|
||||
.attr {
|
||||
overflow-x: scroll;
|
||||
|
||||
1
lib/data/contributors.json
Normal file
1
lib/data/contributors.json
Normal file
File diff suppressed because one or more lines are too long
5
now.json
5
now.json
@@ -1,5 +1,10 @@
|
||||
{
|
||||
"github": {
|
||||
"silent": true
|
||||
},
|
||||
"build": {
|
||||
"env": {
|
||||
"GIT_ORG_READONLY": "@git-org-readonly"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,11 @@
|
||||
"types": "dist/index.d.ts",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "yarn run docs-collect && next dev",
|
||||
"docs-build": "yarn run docs-collect && next build",
|
||||
"dev": "yarn docs-collect && next dev",
|
||||
"docs-build": "yarn docs-collect && yarn contributor-collect && next build",
|
||||
"docs-start": "next start",
|
||||
"docs-collect": "node scripts/collect-meta.js",
|
||||
"contributor-collect": "node scripts/collect-contributors.js",
|
||||
"clear": "rm -rf dist",
|
||||
"lint": "eslint \"{components,lib}/**/*.{js,ts,tsx}\"",
|
||||
"now-build": "yarn run docs-build",
|
||||
@@ -55,11 +56,13 @@
|
||||
"@typescript-eslint/eslint-plugin": "^2.24.0",
|
||||
"@typescript-eslint/parser": "^2.24.0",
|
||||
"babel-loader": "^8.0.6",
|
||||
"dotenv": "^8.2.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-ts-lambdas": "^1.2.0",
|
||||
"eslint-plugin-react": "^7.19.0",
|
||||
"extract-mdx-metadata": "^1.0.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
"graphql-request": "^1.8.2",
|
||||
"next": "^9.3.4",
|
||||
"react": "^16.13.0",
|
||||
"react-color": "^2.18.0",
|
||||
@@ -71,4 +74,4 @@
|
||||
"webpack-cli": "^3.3.11"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
|
||||
102
scripts/collect-contributors.js
Normal file
102
scripts/collect-contributors.js
Normal file
@@ -0,0 +1,102 @@
|
||||
const token = process.env.GIT_ORG_READONLY
|
||||
if (!token) require('dotenv').config()
|
||||
const fs = require('fs-extra')
|
||||
const path = require('path')
|
||||
const { GraphQLClient } = require('graphql-request')
|
||||
const target = path.join(__dirname, '../lib/data/', 'contributors.json')
|
||||
|
||||
if (!token) {
|
||||
console.error('> Not found "GIT_ORG_READONLY" in "process.env".\n')
|
||||
console.log(' Env variables are automatically injected at production.')
|
||||
console.log(' If you want to test, run [echo "GIT_ORG_READONLY=your_git_token" > .env ]\n')
|
||||
process.exit(1)
|
||||
}
|
||||
const client = new GraphQLClient('https://api.github.com/graphql', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
const pagePrefix = path.join(__dirname, '../pages')
|
||||
|
||||
const filterContributors = data => {
|
||||
if (!data || !data.repository) return []
|
||||
const nodes = data.repository.object.history.nodes
|
||||
let users = [], keys = {}
|
||||
for (const item of nodes) {
|
||||
const key = item.author.user.url
|
||||
if (!keys[key]) {
|
||||
keys[key] = 1
|
||||
users.push({
|
||||
name: item.author.name,
|
||||
avatar: item.author.user.avatarUrl,
|
||||
url: item.author.user.url,
|
||||
})
|
||||
}
|
||||
}
|
||||
return users
|
||||
}
|
||||
|
||||
const getContributors = async repoFilePath => {
|
||||
const query = `query($path: String!) {
|
||||
repository(owner: "zeit-ui", name: "react") {
|
||||
object(expression: "master") {
|
||||
... on Commit {
|
||||
history(first: 100, path: $path) {
|
||||
nodes {
|
||||
author {
|
||||
name
|
||||
user {
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
const data = await client.request(query, { path: repoFilePath })
|
||||
return filterContributors(data)
|
||||
}
|
||||
|
||||
const getFiles = async dirPath => {
|
||||
const files = await fs.readdir(dirPath)
|
||||
return files.filter(name => name.endsWith('.mdx'))
|
||||
}
|
||||
|
||||
const getUrls = async () => {
|
||||
const en = path.join(pagePrefix, 'en-us', 'components')
|
||||
const zh = path.join(pagePrefix, 'zh-cn', 'components')
|
||||
const enFiles = await getFiles(en)
|
||||
const zhFiles = await getFiles(zh)
|
||||
|
||||
return enFiles
|
||||
.map(name => `pages/en-us/components/${name}`)
|
||||
.concat(zhFiles.map(name => `pages/zh-cn/components/${name}`))
|
||||
}
|
||||
|
||||
;(async () => {
|
||||
const urls = await getUrls()
|
||||
|
||||
const users = await Promise.all(urls.map(async url => {
|
||||
try {
|
||||
return {
|
||||
name: url,
|
||||
users: await getContributors(url),
|
||||
}
|
||||
} catch (e) {
|
||||
return {}
|
||||
}
|
||||
}))
|
||||
|
||||
const contributors = users.reduce((pre, current) => {
|
||||
if (!current.name) return pre
|
||||
return {
|
||||
...pre,
|
||||
[current.name]: current.users,
|
||||
}
|
||||
}, {})
|
||||
|
||||
fs.writeJSONSync(target, contributors)
|
||||
})()
|
||||
30
yarn.lock
30
yarn.lock
@@ -2288,6 +2288,14 @@ create-react-context@0.2.2:
|
||||
fbjs "^0.8.0"
|
||||
gud "^1.0.0"
|
||||
|
||||
cross-fetch@2.2.2:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.2.tgz#a47ff4f7fc712daba8f6a695a11c948440d45723"
|
||||
integrity sha1-pH/09/xxLauo9qaVoRyUhEDUVyM=
|
||||
dependencies:
|
||||
node-fetch "2.1.2"
|
||||
whatwg-fetch "2.0.4"
|
||||
|
||||
cross-fetch@3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.0.4.tgz#7bef7020207e684a7638ef5f2f698e24d9eb283c"
|
||||
@@ -2530,6 +2538,11 @@ dot-case@^2.1.0:
|
||||
dependencies:
|
||||
no-case "^2.2.0"
|
||||
|
||||
dotenv@^8.2.0:
|
||||
version "8.2.0"
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a"
|
||||
integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==
|
||||
|
||||
duplexify@^3.4.2, duplexify@^3.6.0:
|
||||
version "3.7.1"
|
||||
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
|
||||
@@ -3231,6 +3244,13 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
|
||||
integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
|
||||
|
||||
graphql-request@^1.8.2:
|
||||
version "1.8.2"
|
||||
resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-1.8.2.tgz#398d10ae15c585676741bde3fc01d5ca948f8fbe"
|
||||
integrity sha512-dDX2M+VMsxXFCmUX0Vo0TopIZIX4ggzOtiCsThgtrKR4niiaagsGTDIHj3fsOMFETpa064vzovI+4YV4QnMbcg==
|
||||
dependencies:
|
||||
cross-fetch "2.2.2"
|
||||
|
||||
gud@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0"
|
||||
@@ -4410,6 +4430,11 @@ no-case@^2.2.0, no-case@^2.3.2:
|
||||
dependencies:
|
||||
lower-case "^1.1.1"
|
||||
|
||||
node-fetch@2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5"
|
||||
integrity sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=
|
||||
|
||||
node-fetch@2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
|
||||
@@ -6588,6 +6613,11 @@ webpack@4.42.0, webpack@^4.41.6:
|
||||
watchpack "^1.6.0"
|
||||
webpack-sources "^1.4.1"
|
||||
|
||||
whatwg-fetch@2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f"
|
||||
integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==
|
||||
|
||||
whatwg-fetch@3.0.0, whatwg-fetch@>=0.10.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
|
||||
|
||||
Reference in New Issue
Block a user