├── .babelrc
├── .circleci
└── config.yml
├── .github
└── banner.svg
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── config
└── webpack.config.js
├── jsconfig.json
├── package-lock.json
├── package.json
├── public
├── 404.html
└── data
│ ├── .gitkeep
│ ├── repos.json
│ └── users.json
└── src
└── client
├── App
└── App.js
├── Root.js
├── components
├── developer-list
│ ├── DeveloperList.js
│ └── developer-card
│ │ └── DeveloperCard.js
├── filter
│ └── Filter.js
├── floating-button
│ └── FloatingButton.js
├── github-avatar
│ └── GithubAvatar.js
├── infinite-scroll
│ └── InfiniteScroll.js
├── loading
│ └── Loading.js
├── nav-bar
│ ├── NavBar.js
│ └── navbar-item
│ │ └── NavBarItem.js
├── page-view-tracker
│ └── PageViewTracker.js
├── repository-list
│ ├── RepositoryList.js
│ └── repository-card
│ │ └── RepositoryCard.js
└── sub-nav-link
│ └── SubNavLink.js
├── images
├── logo.png
└── logo.svg
├── index.html
├── pages
├── about
│ └── About.js
├── developers
│ └── Developers.js
├── new-repositories
│ └── NewRepositories.js
├── popular-developers
│ └── PopularDevelopers.js
├── popular-languages
│ └── PopularLanguages.js
├── popular-repositories
│ └── PopularRepositories.js
├── recently-joined-developers
│ └── RecentlyJoinedDevelopers.js
├── repositories-by-language
│ └── RepositoriesByLanguage.js
├── repositories
│ └── Repositories.js
├── statistics
│ └── Statistics.js
└── trending-repositories
│ └── TrendingRepositories.js
├── store
├── colors.json
└── store.js
└── utils
├── colors.js
└── index.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "env",
4 | "react"
5 | ],
6 | "plugins": [
7 | "transform-class-properties",
8 | "transform-object-rest-spread"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | jobs:
4 | deploy:
5 | docker:
6 | - image: circleci/node:10
7 | working_directory: ~/repo
8 | environment:
9 | - SOURCE_BRANCH: master
10 | - TARGET_BRANCH: gh-pages
11 | steps:
12 | - checkout
13 | - restore_cache:
14 | keys:
15 | - v2-dependencies-{{ checksum "package-lock.json" }}
16 | - v2-dependencies-
17 | - run: npm install
18 | - save_cache:
19 | paths:
20 | - node_modules
21 | key: v2-dependencies-{{ checksum "package-lock.json" }}
22 | - run: npm test
23 | - run: npm run build
24 | - deploy:
25 | name: Deploy to Github Pages
26 | command: |
27 | if [ $CIRCLE_BRANCH == $SOURCE_BRANCH ]; then
28 | git config --global user.email $GH_EMAIL
29 | git config --global user.name $GH_NAME
30 |
31 | git clone https://${GH_TOKEN}@github.com/developersdo/opensource.git out
32 |
33 | cd out
34 | git checkout $TARGET_BRANCH || git checkout --orphan $TARGET_BRANCH
35 | git rm -rf .
36 | cd ..
37 |
38 | cp -a public/. out/.
39 |
40 | mkdir -p out/.circleci && cp -a .circleci/. out/.circleci/.
41 |
42 | cd out
43 | git add -A
44 | git commit -m "Deployed: website to Github Pages (automatic): ${CIRCLE_SHA1}" --allow-empty
45 | git push -q https://${GH_TOKEN}@github.com/developersdo/opensource.git $TARGET_BRANCH
46 | fi
47 |
48 | workflows:
49 | version: 2
50 | deploy:
51 | jobs:
52 | - deploy:
53 | filters:
54 | branches:
55 | ignore:
56 | - gh-pages
57 | - master
58 |
--------------------------------------------------------------------------------
/.github/banner.svg:
--------------------------------------------------------------------------------
1 | Dominican Open Source Discover the open source ecosystem related to the Dominican Republic!
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (http://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # Typescript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Visual Studio Code
55 | .vscode/*
56 | !.vscode/settings.json
57 | !.vscode/tasks.json
58 | !.vscode/launch.json
59 | !.vscode/extensions.json
60 |
61 | # Yarn Integrity file
62 | .yarn-integrity
63 |
64 | # dotenv environment variables file
65 | .env
66 |
67 | config/development.json
68 | public/*
69 | !public/404.html
70 | !public/data
71 |
72 | # mac os ds store files
73 | .DS_Store
74 |
75 | \.idea/
76 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at rubens@mariuzzo.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 |
Thank you for your time, effort and willingness
2 | “I see you're a man or woman of culture as well”
3 |
4 | ## A few notes to consider...
5 |
6 | 1. Create your PRs pointing to `develop` branch.
7 | 2. Respect the code-style already in-place.
8 |
9 | That's it! I told you it was just a “few notes”. Happy coding!
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Developers Dominicanos
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | [](https://github.com/developersdo/opensource/blob/develop/LICENSE)
4 | [](https://circleci.com/gh/developersdo/opensource)
5 |
6 | **Dominican Open Source** is an initiative to gather all possible public data about projects and their contributors related to the Dominican Republic in GitHub using the [GraphQL API](https://developer.github.com/v4/).
7 |
8 | ## Want to join?
9 |
10 | There are different ways to participate in this local effort:
11 |
12 | - You can include your GitHub users by adding the term “Dominican” to your profile's location. (Note: Dominicana is also accepted)
13 | - You can improve the code of the [public website](src/client) or [the scraper](src/server).
14 | - And if you don't code you can check the grammar, the UX, the graphic design, [report bugs](https://github.com/developersdo/opensource/issues/new) - it is up to you ;)
15 |
16 | ## Development
17 |
18 | If you want to run this project locally you will need: [NodeJS 8+](https://nodejs.org/en/). After git-cloning this project do:
19 |
20 | **Note:** If you just want to develop the website then skip step 3 and 4.
21 |
22 | 1. `npm install`
23 | 2. Copy `config/default.json` to `config/development.json`.
24 | 3. [Generate a GitHub personal access token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/).
25 | 4. Add your GitHub personal access token to `config/development.json` (this file is [git-ignored](.gitignore)).
26 | 5. `npm run serve` and open http://localhost:8080/opensource
27 |
28 | That's it! Happy coding.
29 |
30 | ### Scripts
31 |
32 | - `npm run scrape` – scrape for all GitHub users and repos as configured.
33 | - `npm run scrape -- --only=users` – scrape for all GitHub repos.
34 | - `npm run scrape -- --only=repos` – scrape for all GitHub users.
35 | - `npm run generate-data` – generate GitHub users and repos for front-end usage.
36 | - `npm run generate-data -- --only users` – generate JSON data for users.
37 | - `npm run generate-data -- --only repos` – generate JSON data for repos.
38 | - `npm run sequelize` – to use sequelize, pass cli args as follow: `npm run sequelize -- db:migrate`.
39 | - `npm run sequelize -- db:migrate` – Run all pending database migrations.
40 | - `npm run sequelize -- db:migrate:undo` – Rollback last database migration.
41 | - `npm run sequelize -- db:migrate:undo:all` – Rollback all database migrations.
42 | - `npm run sequelize:debug` – to use sequelize in debug mode.
43 | - `npm run refresh` – to run the scraper and generate frontend data.
44 | - `npm run build` – to run static assets for production usage.
45 |
46 | ### Deployment
47 |
48 | The deployment is done by [CirceCI](https://circleci.com/gh/developersdo/opensource) which listen to pushes in [`master`](https://github.com/developersdo/opensource/tree/master) branch, then build website assets and finally pushes the site into [`gh-pages`](https://github.com/developersdo/opensource/tree/gh-pages) branch. All details are specified at [.circleci/config.yml](.circleci/config.yml).
49 |
50 |
53 |
--------------------------------------------------------------------------------
/config/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const webpack = require('webpack')
3 | const HtmlPlugin = require('html-webpack-plugin')
4 | const FaviconsPlugin = require('favicons-webpack-plugin')
5 | const DefinePlugin = webpack.DefinePlugin
6 | const CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin
7 |
8 | const pathTo = {
9 | app: path.join(__dirname, '../src/client/Root.js'),
10 | public: path.join(__dirname, '../public'),
11 | index: path.join(__dirname, '../src/client/index.html'),
12 | client: path.join(__dirname, '../src/client/'),
13 | logo: path.join(__dirname, '../src/client/images/logo.png')
14 | }
15 |
16 | module.exports = {
17 | entry: {
18 | app: pathTo.app
19 | },
20 | output: {
21 | path: pathTo.public,
22 | filename: '[name].js',
23 | publicPath: '/opensource'
24 | },
25 | resolve: {
26 | alias: {
27 | '~': pathTo.client
28 | }
29 | },
30 | module: {
31 | rules: [
32 | {
33 | test: /\.js$/,
34 | use: ['babel-loader'],
35 | exclude: /node_modules/
36 | },
37 | {
38 | test: /\.scss$/,
39 | use: [
40 | { loader: 'style-loader' },
41 | { loader: 'css-loader', options: { importLoaders: 1, modules: 1 } },
42 | { loader: 'sass-loader' }
43 | ]
44 | },
45 | {
46 | test: /\.svg$/,
47 | loader: 'svg-sprite-loader'
48 | }
49 | ],
50 | },
51 | plugins: [
52 | new DefinePlugin({
53 | 'process.env': {
54 | NODE_ENV: JSON.stringify(process.env.NODE_ENV)
55 | }
56 | }),
57 | new HtmlPlugin({
58 | template: pathTo.index,
59 | inject: 'body',
60 | hash: true,
61 | filename: 'index.html',
62 | env: process.NODE_ENV
63 | }),
64 | new CommonsChunkPlugin({
65 | name: 'vendor',
66 | minChunks: (module) => /node_modules/.test(module.context),
67 | }),
68 | new FaviconsPlugin(pathTo.logo)
69 | ],
70 | devServer: {
71 | contentBase: pathTo.public,
72 | historyApiFallback: {
73 | index: '/opensource/index.html'
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "./src/",
4 | "paths": {
5 | "~/*": ["client/*"]
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "opensource",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "author": "Rubens Mariuzzo ",
6 | "license": "MIT",
7 | "dependencies": {
8 | "classnames": "^2.2.5",
9 | "config": "^1.26.1",
10 | "cross-env": "^5.0.1",
11 | "debug": "4.0.1",
12 | "favicons-webpack-plugin": "^0.0.7",
13 | "fs-extra": "^4.0.1",
14 | "isomorphic-fetch": "^2.2.1",
15 | "lodash": "^4.17.5",
16 | "prop-types": "^15.6.0",
17 | "react": "^16.0.0",
18 | "react-document-title": "^2.0.3",
19 | "react-dom": "^16.0.0",
20 | "react-ga": "^2.3.5",
21 | "react-infinite-scroller": "^1.0.15",
22 | "react-router-dom": "^4.2.2",
23 | "unorm": "^1.4.1"
24 | },
25 | "devDependencies": {
26 | "babel-core": "^6.25.0",
27 | "babel-loader": "^7.1.0",
28 | "babel-plugin-transform-class-properties": "^6.24.1",
29 | "babel-plugin-transform-object-rest-spread": "^6.26.0",
30 | "babel-preset-env": "^1.6.0",
31 | "babel-preset-react": "^6.24.1",
32 | "css-loader": "^0.28.4",
33 | "graphql-request": "^1.8.2",
34 | "html-webpack-plugin": "^2.29.0",
35 | "node-sass": "^4.10.0",
36 | "sass-loader": "^6.0.7",
37 | "style-loader": "0.19",
38 | "svg-sprite-loader": "^4.1.2",
39 | "webpack": "^3.0.0",
40 | "webpack-dev-server": "^2.5.0"
41 | },
42 | "scripts": {
43 | "scrape": "./src/server/scripts/scraper.js",
44 | "generate-data": "./src/server/scripts/generate-data.js",
45 | "refresh": "npm run scrape; npm run generate-data",
46 | "build": "cross-env NODE_ENV=\"production\" webpack -p --config config/webpack.config.js",
47 | "serve": "cross-env NODE_ENV=\"development\" webpack-dev-server --config config/webpack.config.js --watch --progress --colors --inline",
48 | "test": "echo \"We should write some tests!\""
49 | },
50 | "browserlist": ">1%, last 2 versions"
51 | }
--------------------------------------------------------------------------------
/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Dominican Open Source
9 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/public/data/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/developersdo/opensource/6fef037edf565560e8888332b99452572f682c1a/public/data/.gitkeep
--------------------------------------------------------------------------------
/src/client/App/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { BrowserRouter, Route, Redirect } from 'react-router-dom'
3 | import About from '~/pages/about/About'
4 | import NavBar from '~/components/nav-bar/NavBar'
5 | import Developers from '~/pages/developers/Developers'
6 | import Repositories from '~/pages/repositories/Repositories'
7 | import FloatingButton from '~/components/floating-button/FloatingButton'
8 | import PageViewTracker from '~/components/page-view-tracker/PageViewTracker'
9 |
10 | const basename = '/opensource'
11 |
12 | const App = () => (
13 |
14 |
15 |
16 |
17 |
18 | } />
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | )
27 |
28 | export default App
29 |
--------------------------------------------------------------------------------
/src/client/Root.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import ReactGA from 'react-ga'
4 | import App from './App/App'
5 |
6 | ReactGA.initialize('UA-53810134-2')
7 |
8 | const Root =
9 | ReactDOM.render(Root, document.getElementById('root'))
10 |
--------------------------------------------------------------------------------
/src/client/components/developer-list/DeveloperList.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { filter } from 'lodash'
3 | import utils from '~/utils'
4 | import Filter from '~/components/filter/Filter'
5 | import InfiniteScroll from '~/components/infinite-scroll/InfiniteScroll'
6 | import DeveloperCard from '~/components/developer-list/developer-card/DeveloperCard'
7 |
8 | /**
9 | * The DeveloperList object class.
10 | */
11 | class DeveloperList extends React.Component {
12 |
13 | // Initial state.
14 | state = {
15 | filteredUsers: this.props.users
16 | }
17 |
18 | static defaultProps = {
19 | users: [],
20 | }
21 |
22 | /**
23 | * Render this component.
24 | */
25 | render() {
26 | const { filteredUsers } = this.state
27 | return (
28 |
29 |
this.filterChanged(value)}
32 | />
33 | (
37 |
41 |
42 |
43 | )}
44 | />
45 |
46 | )
47 | }
48 |
49 | /**
50 | * Handle filter value changes.
51 | * @param {String} value The new filter value.
52 | */
53 | filterChanged(value) {
54 | const { users } = this.props
55 |
56 | // Filter users.
57 | const query = utils.unicodeNormalize(value)
58 | const matcher = new RegExp(utils.escapeRegExp(query), 'i')
59 | const filteredUsers = filter(users, (user) => {
60 | return matcher.test(user.normalizedName)
61 | })
62 |
63 | // Update the state.
64 | this.setState((state) => ({
65 | filteredUsers,
66 | }))
67 | }
68 | }
69 |
70 | export default DeveloperList
71 |
--------------------------------------------------------------------------------
/src/client/components/developer-list/developer-card/DeveloperCard.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { OutboundLink } from 'react-ga'
3 | import GithubAvatar from '~/components/github-avatar/GithubAvatar'
4 |
5 | const style = {
6 | avatar: {
7 | width: 64,
8 | height: 64,
9 | verticalAlign: 'middle',
10 | marginRight: 16,
11 | },
12 | action: {
13 | display: 'inline-block',
14 | textTransform: 'none',
15 | },
16 | fact: {
17 | display: 'block'
18 | },
19 | cardNumber: {
20 | display: 'block',
21 | fontWeight: 'bold',
22 | fontSize: '110%',
23 | position: 'absolute',
24 | right: 20,
25 | top: 20
26 | }
27 | }
28 |
29 | const DeveloperCard = ({ user, index }) => (
30 |
31 |
32 |
#{index}
33 |
39 |
40 |
46 |
47 |
48 | {user.name || user.login}
49 |
50 |
51 |
Followed by: {user.followers}
52 |
{user.description}
53 |
54 |
55 |
61 | {user.url}
62 |
63 |
64 |
65 | )
66 |
67 | export default DeveloperCard
68 |
--------------------------------------------------------------------------------
/src/client/components/filter/Filter.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | const style = {
4 | input: {
5 | borderBottomColor: '#2196f3',
6 | boxShadow: '0 1px 0 0 #2196f3'
7 | }
8 | }
9 |
10 | class Filter extends React.Component {
11 |
12 | /**
13 | * Render this component.
14 | */
15 | render() {
16 | const { placeholder } = this.props
17 |
18 | return (
19 |
20 |
21 | this.filterChanged(event.target.value)}
28 | />
29 |
30 | search
31 |
32 |
33 |
34 | )
35 | }
36 |
37 | filterChanged(value) {
38 | const { onChange } = this.props
39 | onChange.call(null, value)
40 | }
41 | }
42 |
43 | export default Filter
44 |
--------------------------------------------------------------------------------
/src/client/components/floating-button/FloatingButton.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { OutboundLink } from 'react-ga'
3 |
4 | class FloatingButton extends React.Component {
5 |
6 | componentDidMount() {
7 | const elems = document.querySelectorAll('.fixed-action-btn')
8 | window.M.FloatingActionButton.init(elems)
9 | }
10 |
11 | render() {
12 | return (
13 |
14 |
15 | more_vert
16 |
17 |
18 |
19 |
27 | bug_report
28 |
29 |
30 |
31 |
39 | code
40 |
41 |
42 |
43 |
44 | )
45 | }
46 | }
47 |
48 | export default FloatingButton
49 |
--------------------------------------------------------------------------------
/src/client/components/github-avatar/GithubAvatar.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | const GithubAvatar = ({ user, size, ...otherProps }) => (
4 |
11 | )
12 |
13 | export default GithubAvatar
14 |
--------------------------------------------------------------------------------
/src/client/components/infinite-scroll/InfiniteScroll.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import InfiniteScroller from 'react-infinite-scroller'
3 | import { get } from 'lodash'
4 | import Loading from '~/components/loading/Loading'
5 |
6 | /**
7 | * The InfiniteScroll class object acts as a wrapper around `react-infinite-scroller`
8 | * specialized for static array (that doesn't need to be fetched). Also, it detect
9 | * changes in that static array and then force remount (key-hack-ish).
10 | */
11 | class InfiniteScroll extends React.Component {
12 |
13 | // Initial state.
14 | state = {
15 | page: 0,
16 | hasMore: true,
17 | renderCount: 0,
18 | renderedItems: [],
19 | }
20 |
21 | /**
22 | * Return default props.
23 | */
24 | static defaultProps = {
25 | size: 10,
26 | render: (item) => {item}
,
27 | }
28 |
29 | componentWillReceiveProps(nextProps) {
30 | const currItems = get(this.props, 'items', [])
31 | const nextItems = get(nextProps, 'items', [])
32 |
33 | if (currItems.length !== nextItems.length) {
34 | this.setState({
35 | page: 0,
36 | hasMore: true,
37 | renderedItems: [],
38 | renderCount: this.state.renderCount + 1,
39 | })
40 | }
41 | }
42 |
43 | /**
44 | * Render this component.
45 | */
46 | render() {
47 | const { hasMore, renderedItems, renderCount } = this.state
48 | const { render } = this.props
49 | return (
50 | }
53 | hasMore={ hasMore }
54 | loadMore={ () => this.loadMore() }
55 | >
56 | { renderedItems.map(render) }
57 |
58 | )
59 | }
60 |
61 | /**
62 | * Load more items.
63 | */
64 | loadMore() {
65 | const { items, size } = this.props
66 | const { renderedItems, page } = this.state
67 |
68 | const nextItems = items.slice(page * size, (page * size) + size)
69 | const moreRenderedItems = renderedItems.concat(nextItems)
70 |
71 | this.setState({
72 | page: page + 1,
73 | hasMore: moreRenderedItems.length < items.length,
74 | renderedItems: moreRenderedItems,
75 | })
76 | }
77 | }
78 |
79 | export default InfiniteScroll
80 |
--------------------------------------------------------------------------------
/src/client/components/loading/Loading.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | const Loading = () => (
4 |
7 | )
8 |
9 | export default Loading
10 |
--------------------------------------------------------------------------------
/src/client/components/nav-bar/NavBar.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { withRouter } from 'react-router-dom'
3 | import NavBarItem from '~/components/nav-bar/navbar-item/NavBarItem'
4 |
5 | import '../../images/logo.svg'
6 |
7 | const style = {
8 | menu: {
9 | cursor: 'pointer'
10 | },
11 | dev_do_logo: {
12 | color: '#fff',
13 | fill: 'currentColor',
14 | width: '1.3em',
15 | height: '1.3em',
16 | verticalAlign: 'middle',
17 | overflow: 'hidden',
18 | }
19 | }
20 |
21 | class NavBar extends React.Component {
22 |
23 | componentDidMount() {
24 | const sidenav = document.querySelector('.side-nav')
25 | M.Sidenav.init(sidenav, {closeOnClick: true})
26 | }
27 |
28 | render() {
29 | return (
30 |
31 |
32 |
33 |
34 |
35 | Dominican Open Source
36 |
37 |
38 |
39 |
40 |
41 |
menu
46 |
47 | Repositories
48 | Developers
49 | About
50 |
51 |
52 | Repositories
53 | Developers
54 | About
55 |
56 |
57 |
58 | )
59 | }
60 |
61 | }
62 |
63 | export default withRouter(NavBar)
64 |
--------------------------------------------------------------------------------
/src/client/components/nav-bar/navbar-item/NavBarItem.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import classnames from 'classnames'
3 | import { Link, withRouter, matchPath } from 'react-router-dom'
4 |
5 | const NavBarItem = ({ to, children, location }) => {
6 | const active = !!matchPath(location.pathname, { path: to })
7 | return (
8 |
9 | {children}
10 |
11 | )
12 | }
13 |
14 | export default withRouter(NavBarItem)
15 |
--------------------------------------------------------------------------------
/src/client/components/page-view-tracker/PageViewTracker.js:
--------------------------------------------------------------------------------
1 | import ReactGA from 'react-ga'
2 |
3 | const PageViewTracker = () => {
4 | const page = window.location.pathname + window.location.search
5 | ReactGA.set({ page })
6 | ReactGA.pageview(page)
7 | return null
8 | }
9 |
10 | export default PageViewTracker
11 |
--------------------------------------------------------------------------------
/src/client/components/repository-list/RepositoryList.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { filter, get } from 'lodash'
3 | import utils from '~/utils'
4 | import Filter from '~/components/filter/Filter'
5 | import InfiniteScroll from '~/components/infinite-scroll/InfiniteScroll'
6 | import RepositoryCard from '~/components/repository-list/repository-card/RepositoryCard'
7 |
8 | /**
9 | * The RepositoryList object class.
10 | */
11 | class RepositoryList extends React.Component {
12 |
13 | // Initial state.
14 | state = {
15 | repos: this.props.repos,
16 | filteredRepos: this.props.repos,
17 | }
18 |
19 | // Default props.
20 | static defaultProps = {
21 | repos: [],
22 | }
23 |
24 | /**
25 | * Update the internal state when this component receive new repos prop.
26 | * @param {Object} nextProps
27 | */
28 | componentWillReceiveProps(nextProps) {
29 | const currRepos = get(this.props, 'repos', [])
30 | const nextRepos = get(nextProps, 'repos', [])
31 |
32 | if (currRepos.length !== nextRepos.length) {
33 | this.setState({
34 | repos: nextRepos,
35 | filteredRepos: nextRepos,
36 | })
37 | }
38 | }
39 |
40 | /**
41 | * Render this component.
42 | */
43 | render() {
44 | const { filteredRepos } = this.state
45 |
46 | return (
47 |
48 | this.filterChanged(value) }
51 | />
52 | (
55 |
59 | ) }
60 | />
61 |
62 | )
63 | }
64 |
65 | /**
66 | * Handle filter value changes.
67 | * @param {String} value The new filter value.
68 | */
69 | filterChanged(value) {
70 | const { repos } = this.state
71 |
72 | // Filter repos.
73 | const query = utils.unicodeNormalize(value)
74 | const matcher = new RegExp(utils.escapeRegExp(query), 'i')
75 | const filteredRepos = filter(repos, (repo) => {
76 | return matcher.test(repo.normalizedName) || matcher.test(repo.normalizedDescription) || matcher.test(repo.user.normalizedName)
77 | })
78 |
79 | // Update the state.
80 | this.setState((state) => ({
81 | filteredRepos,
82 | }))
83 | }
84 | }
85 |
86 | export default RepositoryList
87 |
--------------------------------------------------------------------------------
/src/client/components/repository-list/repository-card/RepositoryCard.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link } from 'react-router-dom'
3 | import { OutboundLink } from 'react-ga'
4 | import GithubAvatar from '~/components/github-avatar/GithubAvatar'
5 | import { languageColor } from '~/utils/colors'
6 |
7 | const style = {
8 | avatar: {
9 | width: 32,
10 | height: 32,
11 | verticalAlign: 'middle',
12 | marginRight: 16,
13 | },
14 | action: {
15 | display: 'inline-block',
16 | },
17 | languages: {
18 | paddingBottom: 6,
19 | },
20 | cardTitle: {
21 | wordWrap: 'break-word',
22 | },
23 | cardAction: {
24 | whiteSpace: 'initial',
25 | },
26 | }
27 |
28 | const languageStyle = (language) => {
29 | let color = languageColor(language)
30 | return {
31 | display: 'inline-block',
32 | margin: '0 10px 10px 0',
33 | color: color.textColor,
34 | backgroundColor: color.backgroundColor
35 | }
36 | }
37 |
38 | const RepositoryCard = ({repo}) => {
39 | return (
40 |
41 |
42 |
43 |
44 | star {repo.stargazers}
45 |
46 | {repo.position && #{repo.position} }
47 |
52 | {repo.name}
53 |
54 |
55 |
{repo.description}
56 |
57 |
58 | {repo.languages.length === 0
59 | ? '(no languages)'
60 | : repo.languages.map((lang, index) => (
61 | {lang.name}
67 | ))
68 | }
69 |
70 |
71 |
77 |
83 | {repo.user.name || repo.user.login}
84 |
85 |
91 | link GitHub Project
92 |
93 |
94 |
95 | )
96 | }
97 |
98 | export default RepositoryCard
99 |
--------------------------------------------------------------------------------
/src/client/components/sub-nav-link/SubNavLink.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { NavLink } from 'react-router-dom'
3 |
4 | const style = {
5 | default: {
6 | display: 'inline-block',
7 | margin: '40px',
8 | fontSize: '20px',
9 | color: '#000'
10 | },
11 | active: {
12 | textDecoration: 'underline',
13 | fontWeight: 'bold'
14 | }
15 | }
16 |
17 | const SubNavLink = ({ to, children }) => (
18 | {children}
19 | )
20 |
21 | export default SubNavLink
22 |
--------------------------------------------------------------------------------
/src/client/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/developersdo/opensource/6fef037edf565560e8888332b99452572f682c1a/src/client/images/logo.png
--------------------------------------------------------------------------------
/src/client/images/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
10 | Dominican Open Source
11 |
40 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/src/client/pages/about/About.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import DocumentTitle from 'react-document-title'
3 | import { OutboundLink } from 'react-ga'
4 | import PopularLanguages from '~/pages/popular-languages/PopularLanguages'
5 | import Statistics from '~/pages/statistics/Statistics'
6 |
7 | const About = () => (
8 |
9 |
10 |
About this website
11 |
12 | Dominican Open Source is an initiative to gather all possible public data about projects in GitHub from developers of the Dominican Republic using the
13 |
17 | GitHub GraphQL API
18 | .
19 |
20 |
21 |
22 | The main purpose of this website is to show local efforts that Dominicans are contributing toward open source communities.
23 |
24 |
32 |
33 |
34 | )
35 |
36 | export default About
37 |
--------------------------------------------------------------------------------
/src/client/pages/developers/Developers.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Route, Redirect } from 'react-router-dom'
3 | import Popular from '~/pages/popular-developers/PopularDevelopers'
4 | import RecentlyJoined from '~/pages/recently-joined-developers/RecentlyJoinedDevelopers'
5 | import SubNavLink from '~/components/sub-nav-link/SubNavLink'
6 |
7 | const Developers = (props) => (
8 |
9 |
10 | Popular
11 | Recently Joined
12 |
13 |
} />
14 |
15 |
16 |
17 | )
18 |
19 | export default Developers
20 |
--------------------------------------------------------------------------------
/src/client/pages/new-repositories/NewRepositories.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import DocumentTitle from 'react-document-title'
3 | import { orderBy, each, filter } from 'lodash'
4 | import store from '~/store/store'
5 | import Loading from '~/components/loading/Loading'
6 | import RepositoryList from '~/components/repository-list/RepositoryList'
7 |
8 | /**
9 | * The NewRepositories class object list all repositories by creation date.
10 | */
11 | class NewRepositories extends React.Component {
12 |
13 | // Initial state.
14 | state = {
15 | repos: [],
16 | loading: true,
17 | error: false
18 | }
19 |
20 | /**
21 | * When component did mount request respository data.
22 | */
23 | componentDidMount() {
24 | store.getRepos().then((response) => {
25 | const orderedRepos = orderBy(response.items, ['createdAt'], ['desc'])
26 | each(orderedRepos, (repo, index) => repo.position = index + 1)
27 | this.setState({
28 | repos: orderedRepos,
29 | loading: !response.ready,
30 | error: response.error
31 | })
32 | })
33 | }
34 |
35 | /**
36 | * Render this component.
37 | */
38 | render() {
39 | const { repos, loading } = this.state
40 |
41 | if (loading) {
42 | return
43 | }
44 |
45 | const now = new Date()
46 | const recently = new Date(now.setDate(now.getDate() - 7))
47 | const newRepos = filter(repos, (repo) => repo.createdAt > recently)
48 |
49 | return (
50 |
51 |
52 |
New repositories
53 |
Showing { newRepos.length.toLocaleString() } repositories created in the last 7 days .
54 |
55 |
56 |
57 | )
58 | }
59 | }
60 |
61 | export default NewRepositories
62 |
--------------------------------------------------------------------------------
/src/client/pages/popular-developers/PopularDevelopers.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import DocumentTitle from 'react-document-title'
3 | import { orderBy } from 'lodash'
4 | import store from '~/store/store'
5 | import Loading from '~/components/loading/Loading'
6 | import DeveloperList from '~/components/developer-list/DeveloperList'
7 |
8 | class PopularDevelopers extends React.Component {
9 |
10 | state = {
11 | users: [],
12 | loading: true
13 | }
14 |
15 | componentDidMount() {
16 | store.getUsers().then((response) => {
17 | const orderedUsers = orderBy(response.items, ['followers', 'name'], ['desc', 'asc'])
18 | this.setState({
19 | users: orderedUsers,
20 | loading: !response.ready
21 | })
22 | })
23 | }
24 |
25 | render() {
26 | const { users, loading } = this.state
27 |
28 | if (loading) {
29 | return
30 | }
31 |
32 | return (
33 |
34 |
35 |
Popular developers
36 |
Showing { users.length.toLocaleString() } developers sorted by followers .
37 |
38 |
39 |
40 | )
41 | }
42 | }
43 |
44 | export default PopularDevelopers
45 |
--------------------------------------------------------------------------------
/src/client/pages/popular-languages/PopularLanguages.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { map } from 'lodash'
3 | import store from '~/store/store'
4 | import Loading from '~/components/loading/Loading'
5 |
6 | const style = {
7 | position: {
8 | width: 40,
9 | display: 'inline-block',
10 | fontSize: 18,
11 | },
12 | name: {
13 | fontSize: 22,
14 | marginRight: 10,
15 | },
16 | progress: {
17 | height: 10,
18 | }
19 | }
20 |
21 | class AboutPopularLanguages extends React.Component {
22 | state = {
23 | repos: [],
24 | loading: true
25 | }
26 | componentDidMount() {
27 | store.getRepos().then((response) => {
28 | this.setState({
29 | repos: response.items,
30 | loading: !response.ready
31 | })
32 | })
33 | }
34 | render() {
35 | const { repos, loading } = this.state
36 | if (loading) {
37 | return
38 | }
39 |
40 | // Count languages for each repos.
41 | const totals = repos.reduce((total, repo) => {
42 | repo.languages.forEach((lang) => {
43 | if (!total[lang.name]) {
44 | total[lang.name] = 0
45 | }
46 | total[lang.name]++
47 | })
48 | return total
49 | }, {})
50 |
51 | // Create language stats.
52 | const languages = map(totals, (total, name) => ({
53 | name,
54 | total,
55 | percentage: ((total / repos.length) * 100).toFixed(2)
56 | }))
57 |
58 | languages.sort((a, b) => b.total - a.total)
59 |
60 | const topLanguages = languages.slice(0, 10)
61 |
62 | return (
63 |
64 |
Popular Languages
65 | {topLanguages.map(({name, total, percentage}, index) => (
66 |
67 |
#{index + 1}
68 |
{name}
69 |
{percentage}%
70 |
73 |
74 | ))}
75 |
76 | )
77 | }
78 | }
79 |
80 | export default AboutPopularLanguages
81 |
--------------------------------------------------------------------------------
/src/client/pages/popular-repositories/PopularRepositories.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import DocumentTitle from 'react-document-title'
3 | import { orderBy, each } from 'lodash'
4 | import store from '~/store/store'
5 | import Loading from '~/components/loading/Loading'
6 | import RepositoryList from '~/components/repository-list/RepositoryList'
7 |
8 | /**
9 | * The PopularRepositories class object list all repositories by popularity.
10 | */
11 | class PopularRepositories extends React.Component {
12 |
13 | // The initial state.
14 | state = {
15 | repos: [],
16 | loading: true,
17 | error: false
18 | }
19 |
20 | /**
21 | * When component did mount request respository data.
22 | */
23 | componentDidMount() {
24 | store.getRepos().then((response) => {
25 | const orderedRepos = orderBy(response.items, ['stargazers', 'forks', 'watchers', 'name'], ['desc', 'desc', 'desc', 'asc'])
26 | each(orderedRepos, (repo, index) => repo.position = index + 1)
27 | this.setState({
28 | repos: orderedRepos,
29 | loading: !response.ready,
30 | error: response.error,
31 | })
32 | })
33 | }
34 |
35 | /**
36 | * Render this component.
37 | */
38 | render() {
39 | const { repos, loading } = this.state
40 |
41 | if (loading) {
42 | return
43 | }
44 |
45 | return (
46 |
47 |
48 |
Popular repositories
49 |
Showing { repos.length.toLocaleString() } repositories sorted by stars .
50 |
51 |
52 |
53 | )
54 | }
55 | }
56 |
57 | export default PopularRepositories
58 |
--------------------------------------------------------------------------------
/src/client/pages/recently-joined-developers/RecentlyJoinedDevelopers.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import DocumentTitle from 'react-document-title'
3 | import { orderBy, filter } from 'lodash'
4 | import store from '~/store/store'
5 | import Loading from '~/components/loading/Loading'
6 | import DeveloperList from '~/components/developer-list/DeveloperList'
7 |
8 | class RecentlyJoinedDevelopers extends React.Component {
9 |
10 | state = {
11 | users: [],
12 | loading: true
13 | }
14 |
15 | componentDidMount() {
16 | store.getUsers().then((response) => {
17 | const orderedUsers = orderBy(response.items, ['createdAt', 'name'], ['desc', 'asc'])
18 | this.setState({
19 | users: orderedUsers,
20 | loading: !response.ready
21 | })
22 | })
23 | }
24 | render() {
25 | const { users, loading } = this.state
26 |
27 | if (loading) {
28 | return
29 | }
30 |
31 | const now = new Date()
32 | const recently = new Date(now.setDate(now.getDate() - 30))
33 | console.log(recently)
34 | const newUsers = filter(users, (user) => user.createdAt > recently)
35 |
36 | return (
37 |
38 |
39 |
Recently joined developers
40 |
Showing { newUsers.length.toLocaleString() } developers that has joined in the last 30 days .
41 |
42 |
43 |
44 | )
45 | }
46 | }
47 |
48 | export default RecentlyJoinedDevelopers
49 |
--------------------------------------------------------------------------------
/src/client/pages/repositories-by-language/RepositoriesByLanguage.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import DocumentTitle from 'react-document-title'
3 | import { orderBy, each, filter, includes } from 'lodash'
4 | import store from '~/store/store'
5 | import Loading from '~/components/loading/Loading'
6 | import RepositoryList from '~/components/repository-list/RepositoryList'
7 |
8 | /**
9 | * The RepositoriesByLanguage class object.
10 | */
11 | class RepositoriesByLanguage extends React.Component {
12 |
13 | // Initial state.
14 | state = {
15 | repos: [],
16 | loading: true,
17 | error: false
18 | }
19 |
20 | /**
21 | * Fetch repos when this component mount.
22 | */
23 | componentDidMount() {
24 | store.getRepos().then((response) => {
25 | const orderedRepos = orderBy(response.items, ['stargazers', 'forks', 'watchers', 'name'], ['desc', 'desc', 'desc', 'asc'])
26 | each(orderedRepos, (repo, index) => repo.position = index + 1)
27 | this.setState({
28 | repos: orderedRepos,
29 | loading: !response.ready,
30 | error: response.error,
31 | })
32 | })
33 | }
34 |
35 | /**
36 | * Render this component.
37 | */
38 | render() {
39 | const { repos, loading } = this.state
40 | const { language } = this.props.match.params
41 |
42 | const filteredRepos = filter(repos, (repo) => includes(repo.languageNames, language))
43 |
44 | if (loading) {
45 | return
46 | }
47 |
48 | return (
49 |
50 |
51 |
Popular { language } repositories
52 |
Showing { filteredRepos.length.toLocaleString() } repositories.
53 |
54 |
55 |
56 | )
57 | }
58 | }
59 |
60 | export default RepositoriesByLanguage
61 |
--------------------------------------------------------------------------------
/src/client/pages/repositories/Repositories.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Route, Redirect, Switch } from 'react-router-dom'
3 | import New from '~/pages/new-repositories/NewRepositories'
4 | import Popular from '~/pages/popular-repositories/PopularRepositories'
5 | import ByLanguage from '~/pages/repositories-by-language/RepositoriesByLanguage'
6 | import SubNavLink from '~/components/sub-nav-link/SubNavLink'
7 |
8 | const Repositories = (props) => (
9 |
10 |
11 | Popular
12 | New
13 |
14 |
} />
15 |
16 |
17 |
18 |
19 |
20 |
21 | )
22 |
23 | export default Repositories
24 |
--------------------------------------------------------------------------------
/src/client/pages/statistics/Statistics.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { map } from 'lodash'
3 | import store from '~/store/store'
4 | import Loading from '~/components/loading/Loading'
5 |
6 | class AboutStatistics extends React.Component {
7 | state = {
8 | repos: [],
9 | users: [],
10 | loading: true
11 | }
12 |
13 | componentDidMount() {
14 | Promise.all([store.getRepos(), store.getUsers()])
15 | .then(([repoResponse, userResponse]) => {
16 | this.setState({
17 | repos: repoResponse.items,
18 | users: userResponse.items,
19 | loading: !repoResponse.ready || !userResponse.ready
20 | })
21 | })
22 | }
23 |
24 | render() {
25 | const { repos, users, loading } = this.state
26 | if (loading) {
27 | return
28 | }
29 |
30 | const usersWithMoreThanTenRepo = users
31 | .filter((user) => user.sources > 10)
32 | .length
33 |
34 | const reposWithMoreThanOneStargazer = repos
35 | .filter((repo) => repo.stargazers > 1)
36 | .length
37 |
38 | // Count languages for each repos.
39 | const totals = repos.reduce((total, repo) => {
40 | repo.languages.forEach((lang) => {
41 | if (!total[lang.name]) {
42 | total[lang.name] = 0
43 | }
44 | total[lang.name]++
45 | })
46 | return total
47 | }, {})
48 |
49 | // Create language stats.
50 | const languages = map(totals, (total, name) => ({
51 | name,
52 | total,
53 | percentage: ((total / repos.length) * 100).toFixed(2)
54 | }))
55 |
56 | languages.sort((a, b) => b.total - a.total)
57 |
58 | return (
59 |
60 |
Statistics
61 |
62 |
63 |
64 | perm_identity
65 | {users.length.toLocaleString()} developers are contributing to open source.
66 |
67 | (organizations are not counted)
68 | Among that number of developers, {usersWithMoreThanTenRepo.toLocaleString()} have more 10 repos .
69 |
70 |
71 |
72 | code
73 | {repos.length.toLocaleString()} repos created on GitHub. In average, each user contribute with {(repos.length / users.length).toFixed(1).toLocaleString()} repos.
74 |
75 | (excluding forks)
76 | Interesting, the fact that there are {reposWithMoreThanOneStargazer.toLocaleString()} repos with more than one star .
77 |
78 |
79 |
80 | assessment
81 | {languages.length.toLocaleString()} programming languages in use across {repos.length.toLocaleString()} repos.
82 |
83 | The less used languages among dominican developers in open source via GitHub are: {languages.slice(-10).map((lang) => lang.name).join(', ')}.
84 |
85 |
86 |
87 | )
88 | }
89 | }
90 |
91 | export default AboutStatistics
92 |
--------------------------------------------------------------------------------
/src/client/pages/trending-repositories/TrendingRepositories.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import DocumentTitle from 'react-document-title'
3 |
4 | const TrendingRepositories = () => (
5 |
6 |
7 | info_outline Coming soon!
8 |
9 |
10 | )
11 |
12 | export default TrendingRepositories
13 |
--------------------------------------------------------------------------------
/src/client/store/colors.json:
--------------------------------------------------------------------------------
1 | {
2 | "1c enterprise": {
3 | "color": "#814ccc",
4 | "url": "https://github.com/trending?l=1c-enterprise"
5 | },
6 | "abap": {
7 | "color": "#e8274b",
8 | "url": "https://github.com/trending?l=abap"
9 | },
10 | "actionscript": {
11 | "color": "#882b0f",
12 | "url": "https://github.com/trending?l=actionscript"
13 | },
14 | "ada": {
15 | "color": "#02f88c",
16 | "url": "https://github.com/trending?l=ada"
17 | },
18 | "agda": {
19 | "color": "#315665",
20 | "url": "https://github.com/trending?l=agda"
21 | },
22 | "ags script": {
23 | "color": "#b9d9ff",
24 | "url": "https://github.com/trending?l=ags-script"
25 | },
26 | "alloy": {
27 | "color": "#64c800",
28 | "url": "https://github.com/trending?l=alloy"
29 | },
30 | "alpine abuild": {
31 | "color": null,
32 | "url": "https://github.com/trending?l=alpine-abuild"
33 | },
34 | "ampl": {
35 | "color": "#e6efbb",
36 | "url": "https://github.com/trending?l=ampl"
37 | },
38 | "antlr": {
39 | "color": "#9dc3ff",
40 | "url": "https://github.com/trending?l=antlr"
41 | },
42 | "apex": {
43 | "color": null,
44 | "url": "https://github.com/trending?l=apex"
45 | },
46 | "api blueprint": {
47 | "color": "#2acca8",
48 | "url": "https://github.com/trending?l=api-blueprint"
49 | },
50 | "apl": {
51 | "color": "#5a8164",
52 | "url": "https://github.com/trending?l=apl"
53 | },
54 | "apollo guidance computer": {
55 | "color": null,
56 | "url": "https://github.com/trending?l=apollo-guidance-computer"
57 | },
58 | "applescript": {
59 | "color": "#101f1f",
60 | "url": "https://github.com/trending?l=applescript"
61 | },
62 | "arc": {
63 | "color": "#aa2afe",
64 | "url": "https://github.com/trending?l=arc"
65 | },
66 | "arduino": {
67 | "color": "#bd79d1",
68 | "url": "https://github.com/trending?l=arduino"
69 | },
70 | "asp": {
71 | "color": "#6a40fd",
72 | "url": "https://github.com/trending?l=asp"
73 | },
74 | "aspectj": {
75 | "color": "#a957b0",
76 | "url": "https://github.com/trending?l=aspectj"
77 | },
78 | "assembly": {
79 | "color": "#6e4c13",
80 | "url": "https://github.com/trending?l=assembly"
81 | },
82 | "ats": {
83 | "color": "#1ac620",
84 | "url": "https://github.com/trending?l=ats"
85 | },
86 | "augeas": {
87 | "color": null,
88 | "url": "https://github.com/trending?l=augeas"
89 | },
90 | "autohotkey": {
91 | "color": "#6594b9",
92 | "url": "https://github.com/trending?l=autohotkey"
93 | },
94 | "autoit": {
95 | "color": "#1c3552",
96 | "url": "https://github.com/trending?l=autoit"
97 | },
98 | "awk": {
99 | "color": null,
100 | "url": "https://github.com/trending?l=awk"
101 | },
102 | "ballerina": {
103 | "color": "#ff5000",
104 | "url": "https://github.com/trending?l=ballerina"
105 | },
106 | "batchfile": {
107 | "color": "#c1f12e",
108 | "url": "https://github.com/trending?l=batchfile"
109 | },
110 | "befunge": {
111 | "color": null,
112 | "url": "https://github.com/trending?l=befunge"
113 | },
114 | "bison": {
115 | "color": null,
116 | "url": "https://github.com/trending?l=bison"
117 | },
118 | "bitbake": {
119 | "color": null,
120 | "url": "https://github.com/trending?l=bitbake"
121 | },
122 | "blitzbasic": {
123 | "color": null,
124 | "url": "https://github.com/trending?l=blitzbasic"
125 | },
126 | "blitzmax": {
127 | "color": "#cd6400",
128 | "url": "https://github.com/trending?l=blitzmax"
129 | },
130 | "bluespec": {
131 | "color": null,
132 | "url": "https://github.com/trending?l=bluespec"
133 | },
134 | "boo": {
135 | "color": "#d4bec1",
136 | "url": "https://github.com/trending?l=boo"
137 | },
138 | "brainfuck": {
139 | "color": "#2f2530",
140 | "url": "https://github.com/trending?l=brainfuck"
141 | },
142 | "brightscript": {
143 | "color": null,
144 | "url": "https://github.com/trending?l=brightscript"
145 | },
146 | "bro": {
147 | "color": null,
148 | "url": "https://github.com/trending?l=bro"
149 | },
150 | "c": {
151 | "color": "#555555",
152 | "url": "https://github.com/trending?l=c"
153 | },
154 | "c#": {
155 | "color": "#178600",
156 | "url": "https://github.com/trending?l=csharp"
157 | },
158 | "c++": {
159 | "color": "#f34b7d",
160 | "url": "https://github.com/trending?l=c++"
161 | },
162 | "c2hs haskell": {
163 | "color": null,
164 | "url": "https://github.com/trending?l=c2hs-haskell"
165 | },
166 | "cap'n proto": {
167 | "color": null,
168 | "url": "https://github.com/trending?l=cap'n-proto"
169 | },
170 | "cartocss": {
171 | "color": null,
172 | "url": "https://github.com/trending?l=cartocss"
173 | },
174 | "ceylon": {
175 | "color": "#dfa535",
176 | "url": "https://github.com/trending?l=ceylon"
177 | },
178 | "chapel": {
179 | "color": "#8dc63f",
180 | "url": "https://github.com/trending?l=chapel"
181 | },
182 | "charity": {
183 | "color": null,
184 | "url": "https://github.com/trending?l=charity"
185 | },
186 | "chuck": {
187 | "color": null,
188 | "url": "https://github.com/trending?l=chuck"
189 | },
190 | "cirru": {
191 | "color": "#ccccff",
192 | "url": "https://github.com/trending?l=cirru"
193 | },
194 | "clarion": {
195 | "color": "#db901e",
196 | "url": "https://github.com/trending?l=clarion"
197 | },
198 | "clean": {
199 | "color": "#3f85af",
200 | "url": "https://github.com/trending?l=clean"
201 | },
202 | "click": {
203 | "color": "#e4e6f3",
204 | "url": "https://github.com/trending?l=click"
205 | },
206 | "clips": {
207 | "color": null,
208 | "url": "https://github.com/trending?l=clips"
209 | },
210 | "clojure": {
211 | "color": "#db5855",
212 | "url": "https://github.com/trending?l=clojure"
213 | },
214 | "cmake": {
215 | "color": null,
216 | "url": "https://github.com/trending?l=cmake"
217 | },
218 | "cobol": {
219 | "color": null,
220 | "url": "https://github.com/trending?l=cobol"
221 | },
222 | "coffeescript": {
223 | "color": "#244776",
224 | "url": "https://github.com/trending?l=coffeescript"
225 | },
226 | "coldfusion": {
227 | "color": "#ed2cd6",
228 | "url": "https://github.com/trending?l=coldfusion"
229 | },
230 | "coldfusion cfc": {
231 | "color": null,
232 | "url": "https://github.com/trending?l=coldfusion-cfc"
233 | },
234 | "common lisp": {
235 | "color": "#3fb68b",
236 | "url": "https://github.com/trending?l=common-lisp"
237 | },
238 | "component pascal": {
239 | "color": "#b0ce4e",
240 | "url": "https://github.com/trending?l=component-pascal"
241 | },
242 | "cool": {
243 | "color": null,
244 | "url": "https://github.com/trending?l=cool"
245 | },
246 | "coq": {
247 | "color": null,
248 | "url": "https://github.com/trending?l=coq"
249 | },
250 | "crystal": {
251 | "color": "#776791",
252 | "url": "https://github.com/trending?l=crystal"
253 | },
254 | "csound": {
255 | "color": null,
256 | "url": "https://github.com/trending?l=csound"
257 | },
258 | "csound document": {
259 | "color": null,
260 | "url": "https://github.com/trending?l=csound-document"
261 | },
262 | "csound score": {
263 | "color": null,
264 | "url": "https://github.com/trending?l=csound-score"
265 | },
266 | "css": {
267 | "color": "#563d7c",
268 | "url": "https://github.com/trending?l=css"
269 | },
270 | "cuda": {
271 | "color": "#3a4e3a",
272 | "url": "https://github.com/trending?l=cuda"
273 | },
274 | "cweb": {
275 | "color": null,
276 | "url": "https://github.com/trending?l=cweb"
277 | },
278 | "cycript": {
279 | "color": null,
280 | "url": "https://github.com/trending?l=cycript"
281 | },
282 | "cython": {
283 | "color": null,
284 | "url": "https://github.com/trending?l=cython"
285 | },
286 | "d": {
287 | "color": "#ba595e",
288 | "url": "https://github.com/trending?l=d"
289 | },
290 | "dart": {
291 | "color": "#00b4ab",
292 | "url": "https://github.com/trending?l=dart"
293 | },
294 | "dataweave": {
295 | "color": "#003a52",
296 | "url": "https://github.com/trending?l=dataweave"
297 | },
298 | "digital command language": {
299 | "color": null,
300 | "url": "https://github.com/trending?l=digital-command-language"
301 | },
302 | "dm": {
303 | "color": "#447265",
304 | "url": "https://github.com/trending?l=dm"
305 | },
306 | "dogescript": {
307 | "color": "#cca760",
308 | "url": "https://github.com/trending?l=dogescript"
309 | },
310 | "dtrace": {
311 | "color": null,
312 | "url": "https://github.com/trending?l=dtrace"
313 | },
314 | "dylan": {
315 | "color": "#6c616e",
316 | "url": "https://github.com/trending?l=dylan"
317 | },
318 | "e": {
319 | "color": "#ccce35",
320 | "url": "https://github.com/trending?l=e"
321 | },
322 | "ec": {
323 | "color": "#913960",
324 | "url": "https://github.com/trending?l=ec"
325 | },
326 | "ecl": {
327 | "color": "#8a1267",
328 | "url": "https://github.com/trending?l=ecl"
329 | },
330 | "eclipse": {
331 | "color": null,
332 | "url": "https://github.com/trending?l=eclipse"
333 | },
334 | "eiffel": {
335 | "color": "#946d57",
336 | "url": "https://github.com/trending?l=eiffel"
337 | },
338 | "elixir": {
339 | "color": "#6e4a7e",
340 | "url": "https://github.com/trending?l=elixir"
341 | },
342 | "elm": {
343 | "color": "#60b5cc",
344 | "url": "https://github.com/trending?l=elm"
345 | },
346 | "emacs lisp": {
347 | "color": "#c065db",
348 | "url": "https://github.com/trending?l=emacs-lisp"
349 | },
350 | "emberscript": {
351 | "color": "#fff4f3",
352 | "url": "https://github.com/trending?l=emberscript"
353 | },
354 | "eq": {
355 | "color": "#a78649",
356 | "url": "https://github.com/trending?l=eq"
357 | },
358 | "erlang": {
359 | "color": "#b83998",
360 | "url": "https://github.com/trending?l=erlang"
361 | },
362 | "f#": {
363 | "color": "#b845fc",
364 | "url": "https://github.com/trending?l=fsharp"
365 | },
366 | "factor": {
367 | "color": "#636746",
368 | "url": "https://github.com/trending?l=factor"
369 | },
370 | "fancy": {
371 | "color": "#7b9db4",
372 | "url": "https://github.com/trending?l=fancy"
373 | },
374 | "fantom": {
375 | "color": "#14253c",
376 | "url": "https://github.com/trending?l=fantom"
377 | },
378 | "filebench wml": {
379 | "color": null,
380 | "url": "https://github.com/trending?l=filebench-wml"
381 | },
382 | "filterscript": {
383 | "color": null,
384 | "url": "https://github.com/trending?l=filterscript"
385 | },
386 | "fish": {
387 | "color": null,
388 | "url": "https://github.com/trending?l=fish"
389 | },
390 | "flux": {
391 | "color": "#88ccff",
392 | "url": "https://github.com/trending?l=flux"
393 | },
394 | "forth": {
395 | "color": "#341708",
396 | "url": "https://github.com/trending?l=forth"
397 | },
398 | "fortran": {
399 | "color": "#4d41b1",
400 | "url": "https://github.com/trending?l=fortran"
401 | },
402 | "freemarker": {
403 | "color": "#0050b2",
404 | "url": "https://github.com/trending?l=freemarker"
405 | },
406 | "frege": {
407 | "color": "#00cafe",
408 | "url": "https://github.com/trending?l=frege"
409 | },
410 | "game maker language": {
411 | "color": "#8fb200",
412 | "url": "https://github.com/trending?l=game-maker-language"
413 | },
414 | "gams": {
415 | "color": null,
416 | "url": "https://github.com/trending?l=gams"
417 | },
418 | "gap": {
419 | "color": null,
420 | "url": "https://github.com/trending?l=gap"
421 | },
422 | "gcc machine description": {
423 | "color": null,
424 | "url": "https://github.com/trending?l=gcc-machine-description"
425 | },
426 | "gdb": {
427 | "color": null,
428 | "url": "https://github.com/trending?l=gdb"
429 | },
430 | "gdscript": {
431 | "color": null,
432 | "url": "https://github.com/trending?l=gdscript"
433 | },
434 | "genie": {
435 | "color": "#fb855d",
436 | "url": "https://github.com/trending?l=genie"
437 | },
438 | "genshi": {
439 | "color": null,
440 | "url": "https://github.com/trending?l=genshi"
441 | },
442 | "gentoo ebuild": {
443 | "color": null,
444 | "url": "https://github.com/trending?l=gentoo-ebuild"
445 | },
446 | "gentoo eclass": {
447 | "color": null,
448 | "url": "https://github.com/trending?l=gentoo-eclass"
449 | },
450 | "gherkin": {
451 | "color": "#5b2063",
452 | "url": "https://github.com/trending?l=gherkin"
453 | },
454 | "glsl": {
455 | "color": null,
456 | "url": "https://github.com/trending?l=glsl"
457 | },
458 | "glyph": {
459 | "color": "#e4cc98",
460 | "url": "https://github.com/trending?l=glyph"
461 | },
462 | "gnuplot": {
463 | "color": "#f0a9f0",
464 | "url": "https://github.com/trending?l=gnuplot"
465 | },
466 | "go": {
467 | "color": "#375eab",
468 | "url": "https://github.com/trending?l=go"
469 | },
470 | "golo": {
471 | "color": "#88562a",
472 | "url": "https://github.com/trending?l=golo"
473 | },
474 | "gosu": {
475 | "color": "#82937f",
476 | "url": "https://github.com/trending?l=gosu"
477 | },
478 | "grace": {
479 | "color": null,
480 | "url": "https://github.com/trending?l=grace"
481 | },
482 | "grammatical framework": {
483 | "color": "#79aa7a",
484 | "url": "https://github.com/trending?l=grammatical-framework"
485 | },
486 | "groovy": {
487 | "color": "#e69f56",
488 | "url": "https://github.com/trending?l=groovy"
489 | },
490 | "groovy server pages": {
491 | "color": null,
492 | "url": "https://github.com/trending?l=groovy-server-pages"
493 | },
494 | "hack": {
495 | "color": "#878787",
496 | "url": "https://github.com/trending?l=hack"
497 | },
498 | "harbour": {
499 | "color": "#0e60e3",
500 | "url": "https://github.com/trending?l=harbour"
501 | },
502 | "haskell": {
503 | "color": "#5e5086",
504 | "url": "https://github.com/trending?l=haskell"
505 | },
506 | "haxe": {
507 | "color": "#df7900",
508 | "url": "https://github.com/trending?l=haxe"
509 | },
510 | "hcl": {
511 | "color": null,
512 | "url": "https://github.com/trending?l=hcl"
513 | },
514 | "hlsl": {
515 | "color": null,
516 | "url": "https://github.com/trending?l=hlsl"
517 | },
518 | "html": {
519 | "color": "#e34c26",
520 | "url": "https://github.com/trending?l=html"
521 | },
522 | "hy": {
523 | "color": "#7790b2",
524 | "url": "https://github.com/trending?l=hy"
525 | },
526 | "hyphy": {
527 | "color": null,
528 | "url": "https://github.com/trending?l=hyphy"
529 | },
530 | "idl": {
531 | "color": "#a3522f",
532 | "url": "https://github.com/trending?l=idl"
533 | },
534 | "idris": {
535 | "color": null,
536 | "url": "https://github.com/trending?l=idris"
537 | },
538 | "igor pro": {
539 | "color": null,
540 | "url": "https://github.com/trending?l=igor-pro"
541 | },
542 | "inform 7": {
543 | "color": null,
544 | "url": "https://github.com/trending?l=inform-7"
545 | },
546 | "inno setup": {
547 | "color": null,
548 | "url": "https://github.com/trending?l=inno-setup"
549 | },
550 | "io": {
551 | "color": "#a9188d",
552 | "url": "https://github.com/trending?l=io"
553 | },
554 | "ioke": {
555 | "color": "#078193",
556 | "url": "https://github.com/trending?l=ioke"
557 | },
558 | "isabelle": {
559 | "color": "#fefe00",
560 | "url": "https://github.com/trending?l=isabelle"
561 | },
562 | "isabelle root": {
563 | "color": null,
564 | "url": "https://github.com/trending?l=isabelle-root"
565 | },
566 | "j": {
567 | "color": "#9eedff",
568 | "url": "https://github.com/trending?l=j"
569 | },
570 | "jasmin": {
571 | "color": null,
572 | "url": "https://github.com/trending?l=jasmin"
573 | },
574 | "java": {
575 | "color": "#b07219",
576 | "url": "https://github.com/trending?l=java"
577 | },
578 | "java server pages": {
579 | "color": null,
580 | "url": "https://github.com/trending?l=java-server-pages"
581 | },
582 | "javascript": {
583 | "color": "#f1e05a",
584 | "url": "https://github.com/trending?l=javascript"
585 | },
586 | "jflex": {
587 | "color": null,
588 | "url": "https://github.com/trending?l=jflex"
589 | },
590 | "jison": {
591 | "color": null,
592 | "url": "https://github.com/trending?l=jison"
593 | },
594 | "jison lex": {
595 | "color": null,
596 | "url": "https://github.com/trending?l=jison-lex"
597 | },
598 | "jolie": {
599 | "color": "#843179",
600 | "url": "https://github.com/trending?l=jolie"
601 | },
602 | "jsoniq": {
603 | "color": "#40d47e",
604 | "url": "https://github.com/trending?l=jsoniq"
605 | },
606 | "jsx": {
607 | "color": null,
608 | "url": "https://github.com/trending?l=jsx"
609 | },
610 | "julia": {
611 | "color": "#a270ba",
612 | "url": "https://github.com/trending?l=julia"
613 | },
614 | "jupyter notebook": {
615 | "color": "#da5b0b",
616 | "url": "https://github.com/trending?l=jupyter-notebook"
617 | },
618 | "kotlin": {
619 | "color": "#f18e33",
620 | "url": "https://github.com/trending?l=kotlin"
621 | },
622 | "krl": {
623 | "color": "#28431f",
624 | "url": "https://github.com/trending?l=krl"
625 | },
626 | "labview": {
627 | "color": null,
628 | "url": "https://github.com/trending?l=labview"
629 | },
630 | "lasso": {
631 | "color": "#999999",
632 | "url": "https://github.com/trending?l=lasso"
633 | },
634 | "lean": {
635 | "color": null,
636 | "url": "https://github.com/trending?l=lean"
637 | },
638 | "lex": {
639 | "color": "#dbca00",
640 | "url": "https://github.com/trending?l=lex"
641 | },
642 | "lfe": {
643 | "color": null,
644 | "url": "https://github.com/trending?l=lfe"
645 | },
646 | "lilypond": {
647 | "color": null,
648 | "url": "https://github.com/trending?l=lilypond"
649 | },
650 | "limbo": {
651 | "color": null,
652 | "url": "https://github.com/trending?l=limbo"
653 | },
654 | "literate agda": {
655 | "color": null,
656 | "url": "https://github.com/trending?l=literate-agda"
657 | },
658 | "literate coffeescript": {
659 | "color": null,
660 | "url": "https://github.com/trending?l=literate-coffeescript"
661 | },
662 | "literate haskell": {
663 | "color": null,
664 | "url": "https://github.com/trending?l=literate-haskell"
665 | },
666 | "livescript": {
667 | "color": "#499886",
668 | "url": "https://github.com/trending?l=livescript"
669 | },
670 | "llvm": {
671 | "color": "#185619",
672 | "url": "https://github.com/trending?l=llvm"
673 | },
674 | "logos": {
675 | "color": null,
676 | "url": "https://github.com/trending?l=logos"
677 | },
678 | "logtalk": {
679 | "color": null,
680 | "url": "https://github.com/trending?l=logtalk"
681 | },
682 | "lolcode": {
683 | "color": "#cc9900",
684 | "url": "https://github.com/trending?l=lolcode"
685 | },
686 | "lookml": {
687 | "color": "#652b81",
688 | "url": "https://github.com/trending?l=lookml"
689 | },
690 | "loomscript": {
691 | "color": null,
692 | "url": "https://github.com/trending?l=loomscript"
693 | },
694 | "lsl": {
695 | "color": "#3d9970",
696 | "url": "https://github.com/trending?l=lsl"
697 | },
698 | "lua": {
699 | "color": "#000080",
700 | "url": "https://github.com/trending?l=lua"
701 | },
702 | "m": {
703 | "color": null,
704 | "url": "https://github.com/trending?l=m"
705 | },
706 | "m4": {
707 | "color": null,
708 | "url": "https://github.com/trending?l=m4"
709 | },
710 | "m4sugar": {
711 | "color": null,
712 | "url": "https://github.com/trending?l=m4sugar"
713 | },
714 | "makefile": {
715 | "color": "#427819",
716 | "url": "https://github.com/trending?l=makefile"
717 | },
718 | "mako": {
719 | "color": null,
720 | "url": "https://github.com/trending?l=mako"
721 | },
722 | "mask": {
723 | "color": "#f97732",
724 | "url": "https://github.com/trending?l=mask"
725 | },
726 | "mathematica": {
727 | "color": null,
728 | "url": "https://github.com/trending?l=mathematica"
729 | },
730 | "matlab": {
731 | "color": "#e16737",
732 | "url": "https://github.com/trending?l=matlab"
733 | },
734 | "max": {
735 | "color": "#c4a79c",
736 | "url": "https://github.com/trending?l=max"
737 | },
738 | "maxscript": {
739 | "color": "#00a6a6",
740 | "url": "https://github.com/trending?l=maxscript"
741 | },
742 | "mercury": {
743 | "color": "#ff2b2b",
744 | "url": "https://github.com/trending?l=mercury"
745 | },
746 | "meson": {
747 | "color": "#007800",
748 | "url": "https://github.com/trending?l=meson"
749 | },
750 | "metal": {
751 | "color": "#8f14e9",
752 | "url": "https://github.com/trending?l=metal"
753 | },
754 | "minid": {
755 | "color": null,
756 | "url": "https://github.com/trending?l=minid"
757 | },
758 | "mirah": {
759 | "color": "#c7a938",
760 | "url": "https://github.com/trending?l=mirah"
761 | },
762 | "modelica": {
763 | "color": null,
764 | "url": "https://github.com/trending?l=modelica"
765 | },
766 | "modula-2": {
767 | "color": null,
768 | "url": "https://github.com/trending?l=modula-2"
769 | },
770 | "module management system": {
771 | "color": null,
772 | "url": "https://github.com/trending?l=module-management-system"
773 | },
774 | "monkey": {
775 | "color": null,
776 | "url": "https://github.com/trending?l=monkey"
777 | },
778 | "moocode": {
779 | "color": null,
780 | "url": "https://github.com/trending?l=moocode"
781 | },
782 | "moonscript": {
783 | "color": null,
784 | "url": "https://github.com/trending?l=moonscript"
785 | },
786 | "mql4": {
787 | "color": "#62a8d6",
788 | "url": "https://github.com/trending?l=mql4"
789 | },
790 | "mql5": {
791 | "color": "#4a76b8",
792 | "url": "https://github.com/trending?l=mql5"
793 | },
794 | "mtml": {
795 | "color": "#b7e1f4",
796 | "url": "https://github.com/trending?l=mtml"
797 | },
798 | "muf": {
799 | "color": null,
800 | "url": "https://github.com/trending?l=muf"
801 | },
802 | "mupad": {
803 | "color": null,
804 | "url": "https://github.com/trending?l=mupad"
805 | },
806 | "myghty": {
807 | "color": null,
808 | "url": "https://github.com/trending?l=myghty"
809 | },
810 | "ncl": {
811 | "color": "#28431f",
812 | "url": "https://github.com/trending?l=ncl"
813 | },
814 | "nearley": {
815 | "color": "#990000",
816 | "url": "https://github.com/trending?l=nearley"
817 | },
818 | "nemerle": {
819 | "color": "#3d3c6e",
820 | "url": "https://github.com/trending?l=nemerle"
821 | },
822 | "nesc": {
823 | "color": "#94b0c7",
824 | "url": "https://github.com/trending?l=nesc"
825 | },
826 | "netlinx": {
827 | "color": "#0aa0ff",
828 | "url": "https://github.com/trending?l=netlinx"
829 | },
830 | "netlinx+erb": {
831 | "color": "#747faa",
832 | "url": "https://github.com/trending?l=netlinx+erb"
833 | },
834 | "netlogo": {
835 | "color": "#ff6375",
836 | "url": "https://github.com/trending?l=netlogo"
837 | },
838 | "newlisp": {
839 | "color": "#87aed7",
840 | "url": "https://github.com/trending?l=newlisp"
841 | },
842 | "nim": {
843 | "color": "#37775b",
844 | "url": "https://github.com/trending?l=nim"
845 | },
846 | "nit": {
847 | "color": "#009917",
848 | "url": "https://github.com/trending?l=nit"
849 | },
850 | "nix": {
851 | "color": "#7e7eff",
852 | "url": "https://github.com/trending?l=nix"
853 | },
854 | "nsis": {
855 | "color": null,
856 | "url": "https://github.com/trending?l=nsis"
857 | },
858 | "nu": {
859 | "color": "#c9df40",
860 | "url": "https://github.com/trending?l=nu"
861 | },
862 | "numpy": {
863 | "color": null,
864 | "url": "https://github.com/trending?l=numpy"
865 | },
866 | "objective-c": {
867 | "color": "#438eff",
868 | "url": "https://github.com/trending?l=objective-c"
869 | },
870 | "objective-c++": {
871 | "color": "#6866fb",
872 | "url": "https://github.com/trending?l=objective-c++"
873 | },
874 | "objective-j": {
875 | "color": "#ff0c5a",
876 | "url": "https://github.com/trending?l=objective-j"
877 | },
878 | "ocaml": {
879 | "color": "#3be133",
880 | "url": "https://github.com/trending?l=ocaml"
881 | },
882 | "omgrofl": {
883 | "color": "#cabbff",
884 | "url": "https://github.com/trending?l=omgrofl"
885 | },
886 | "ooc": {
887 | "color": "#b0b77e",
888 | "url": "https://github.com/trending?l=ooc"
889 | },
890 | "opa": {
891 | "color": null,
892 | "url": "https://github.com/trending?l=opa"
893 | },
894 | "opal": {
895 | "color": "#f7ede0",
896 | "url": "https://github.com/trending?l=opal"
897 | },
898 | "opencl": {
899 | "color": null,
900 | "url": "https://github.com/trending?l=opencl"
901 | },
902 | "openedge abl": {
903 | "color": null,
904 | "url": "https://github.com/trending?l=openedge-abl"
905 | },
906 | "openrc runscript": {
907 | "color": null,
908 | "url": "https://github.com/trending?l=openrc-runscript"
909 | },
910 | "openscad": {
911 | "color": null,
912 | "url": "https://github.com/trending?l=openscad"
913 | },
914 | "ox": {
915 | "color": null,
916 | "url": "https://github.com/trending?l=ox"
917 | },
918 | "oxygene": {
919 | "color": "#cdd0e3",
920 | "url": "https://github.com/trending?l=oxygene"
921 | },
922 | "oz": {
923 | "color": "#fab738",
924 | "url": "https://github.com/trending?l=oz"
925 | },
926 | "p4": {
927 | "color": "#7055b5",
928 | "url": "https://github.com/trending?l=p4"
929 | },
930 | "pan": {
931 | "color": "#cc0000",
932 | "url": "https://github.com/trending?l=pan"
933 | },
934 | "papyrus": {
935 | "color": "#6600cc",
936 | "url": "https://github.com/trending?l=papyrus"
937 | },
938 | "parrot": {
939 | "color": "#f3ca0a",
940 | "url": "https://github.com/trending?l=parrot"
941 | },
942 | "parrot assembly": {
943 | "color": null,
944 | "url": "https://github.com/trending?l=parrot-assembly"
945 | },
946 | "parrot internal representation": {
947 | "color": null,
948 | "url": "https://github.com/trending?l=parrot-internal-representation"
949 | },
950 | "pascal": {
951 | "color": "#e3f171",
952 | "url": "https://github.com/trending?l=pascal"
953 | },
954 | "pawn": {
955 | "color": "#dbb284",
956 | "url": "https://github.com/trending?l=pawn"
957 | },
958 | "pep8": {
959 | "color": "#c76f5b",
960 | "url": "https://github.com/trending?l=pep8"
961 | },
962 | "perl": {
963 | "color": "#0298c3",
964 | "url": "https://github.com/trending?l=perl"
965 | },
966 | "perl 6": {
967 | "color": "#0000fb",
968 | "url": "https://github.com/trending?l=perl-6"
969 | },
970 | "php": {
971 | "color": "#4f5d95",
972 | "url": "https://github.com/trending?l=php"
973 | },
974 | "picolisp": {
975 | "color": null,
976 | "url": "https://github.com/trending?l=picolisp"
977 | },
978 | "piglatin": {
979 | "color": "#fcd7de",
980 | "url": "https://github.com/trending?l=piglatin"
981 | },
982 | "pike": {
983 | "color": "#005390",
984 | "url": "https://github.com/trending?l=pike"
985 | },
986 | "plpgsql": {
987 | "color": null,
988 | "url": "https://github.com/trending?l=plpgsql"
989 | },
990 | "plsql": {
991 | "color": "#dad8d8",
992 | "url": "https://github.com/trending?l=plsql"
993 | },
994 | "pogoscript": {
995 | "color": "#d80074",
996 | "url": "https://github.com/trending?l=pogoscript"
997 | },
998 | "pony": {
999 | "color": null,
1000 | "url": "https://github.com/trending?l=pony"
1001 | },
1002 | "postscript": {
1003 | "color": "#da291c",
1004 | "url": "https://github.com/trending?l=postscript"
1005 | },
1006 | "pov-ray sdl": {
1007 | "color": null,
1008 | "url": "https://github.com/trending?l=pov-ray-sdl"
1009 | },
1010 | "powerbuilder": {
1011 | "color": "#8f0f8d",
1012 | "url": "https://github.com/trending?l=powerbuilder"
1013 | },
1014 | "powershell": {
1015 | "color": "#012456",
1016 | "url": "https://github.com/trending?l=powershell"
1017 | },
1018 | "processing": {
1019 | "color": "#0096d8",
1020 | "url": "https://github.com/trending?l=processing"
1021 | },
1022 | "prolog": {
1023 | "color": "#74283c",
1024 | "url": "https://github.com/trending?l=prolog"
1025 | },
1026 | "propeller spin": {
1027 | "color": "#7fa2a7",
1028 | "url": "https://github.com/trending?l=propeller-spin"
1029 | },
1030 | "puppet": {
1031 | "color": "#302b6d",
1032 | "url": "https://github.com/trending?l=puppet"
1033 | },
1034 | "purebasic": {
1035 | "color": "#5a6986",
1036 | "url": "https://github.com/trending?l=purebasic"
1037 | },
1038 | "purescript": {
1039 | "color": "#1d222d",
1040 | "url": "https://github.com/trending?l=purescript"
1041 | },
1042 | "python": {
1043 | "color": "#3572a5",
1044 | "url": "https://github.com/trending?l=python"
1045 | },
1046 | "python console": {
1047 | "color": null,
1048 | "url": "https://github.com/trending?l=python-console"
1049 | },
1050 | "qmake": {
1051 | "color": null,
1052 | "url": "https://github.com/trending?l=qmake"
1053 | },
1054 | "qml": {
1055 | "color": "#44a51c",
1056 | "url": "https://github.com/trending?l=qml"
1057 | },
1058 | "r": {
1059 | "color": "#198ce7",
1060 | "url": "https://github.com/trending?l=r"
1061 | },
1062 | "racket": {
1063 | "color": "#22228f",
1064 | "url": "https://github.com/trending?l=racket"
1065 | },
1066 | "ragel": {
1067 | "color": "#9d5200",
1068 | "url": "https://github.com/trending?l=ragel"
1069 | },
1070 | "raml": {
1071 | "color": "#77d9fb",
1072 | "url": "https://github.com/trending?l=raml"
1073 | },
1074 | "rascal": {
1075 | "color": "#fffaa0",
1076 | "url": "https://github.com/trending?l=rascal"
1077 | },
1078 | "realbasic": {
1079 | "color": null,
1080 | "url": "https://github.com/trending?l=realbasic"
1081 | },
1082 | "reason": {
1083 | "color": null,
1084 | "url": "https://github.com/trending?l=reason"
1085 | },
1086 | "rebol": {
1087 | "color": "#358a5b",
1088 | "url": "https://github.com/trending?l=rebol"
1089 | },
1090 | "red": {
1091 | "color": "#f50000",
1092 | "url": "https://github.com/trending?l=red"
1093 | },
1094 | "redcode": {
1095 | "color": null,
1096 | "url": "https://github.com/trending?l=redcode"
1097 | },
1098 | "ren'py": {
1099 | "color": "#ff7f7f",
1100 | "url": "https://github.com/trending?l=ren'py"
1101 | },
1102 | "renderscript": {
1103 | "color": null,
1104 | "url": "https://github.com/trending?l=renderscript"
1105 | },
1106 | "rexx": {
1107 | "color": null,
1108 | "url": "https://github.com/trending?l=rexx"
1109 | },
1110 | "ring": {
1111 | "color": "#0e60e3",
1112 | "url": "https://github.com/trending?l=ring"
1113 | },
1114 | "robotframework": {
1115 | "color": null,
1116 | "url": "https://github.com/trending?l=robotframework"
1117 | },
1118 | "roff": {
1119 | "color": "#ecdebe",
1120 | "url": "https://github.com/trending?l=roff"
1121 | },
1122 | "rouge": {
1123 | "color": "#cc0088",
1124 | "url": "https://github.com/trending?l=rouge"
1125 | },
1126 | "ruby": {
1127 | "color": "#701516",
1128 | "url": "https://github.com/trending?l=ruby"
1129 | },
1130 | "runoff": {
1131 | "color": "#665a4e",
1132 | "url": "https://github.com/trending?l=runoff"
1133 | },
1134 | "rust": {
1135 | "color": "#dea584",
1136 | "url": "https://github.com/trending?l=rust"
1137 | },
1138 | "sage": {
1139 | "color": null,
1140 | "url": "https://github.com/trending?l=sage"
1141 | },
1142 | "saltstack": {
1143 | "color": "#646464",
1144 | "url": "https://github.com/trending?l=saltstack"
1145 | },
1146 | "sas": {
1147 | "color": "#b34936",
1148 | "url": "https://github.com/trending?l=sas"
1149 | },
1150 | "scala": {
1151 | "color": "#c22d40",
1152 | "url": "https://github.com/trending?l=scala"
1153 | },
1154 | "scheme": {
1155 | "color": "#1e4aec",
1156 | "url": "https://github.com/trending?l=scheme"
1157 | },
1158 | "scilab": {
1159 | "color": null,
1160 | "url": "https://github.com/trending?l=scilab"
1161 | },
1162 | "self": {
1163 | "color": "#0579aa",
1164 | "url": "https://github.com/trending?l=self"
1165 | },
1166 | "shaderlab": {
1167 | "color": null,
1168 | "url": "https://github.com/trending?l=shaderlab"
1169 | },
1170 | "shell": {
1171 | "color": "#89e051",
1172 | "url": "https://github.com/trending?l=shell"
1173 | },
1174 | "shellsession": {
1175 | "color": null,
1176 | "url": "https://github.com/trending?l=shellsession"
1177 | },
1178 | "shen": {
1179 | "color": "#120f14",
1180 | "url": "https://github.com/trending?l=shen"
1181 | },
1182 | "slash": {
1183 | "color": "#007eff",
1184 | "url": "https://github.com/trending?l=slash"
1185 | },
1186 | "smali": {
1187 | "color": null,
1188 | "url": "https://github.com/trending?l=smali"
1189 | },
1190 | "smalltalk": {
1191 | "color": "#596706",
1192 | "url": "https://github.com/trending?l=smalltalk"
1193 | },
1194 | "smarty": {
1195 | "color": null,
1196 | "url": "https://github.com/trending?l=smarty"
1197 | },
1198 | "smt": {
1199 | "color": null,
1200 | "url": "https://github.com/trending?l=smt"
1201 | },
1202 | "sourcepawn": {
1203 | "color": "#5c7611",
1204 | "url": "https://github.com/trending?l=sourcepawn"
1205 | },
1206 | "sqf": {
1207 | "color": "#3f3f3f",
1208 | "url": "https://github.com/trending?l=sqf"
1209 | },
1210 | "sqlpl": {
1211 | "color": null,
1212 | "url": "https://github.com/trending?l=sqlpl"
1213 | },
1214 | "squirrel": {
1215 | "color": "#800000",
1216 | "url": "https://github.com/trending?l=squirrel"
1217 | },
1218 | "srecode template": {
1219 | "color": "#348a34",
1220 | "url": "https://github.com/trending?l=srecode-template"
1221 | },
1222 | "stan": {
1223 | "color": "#b2011d",
1224 | "url": "https://github.com/trending?l=stan"
1225 | },
1226 | "standard ml": {
1227 | "color": "#dc566d",
1228 | "url": "https://github.com/trending?l=standard-ml"
1229 | },
1230 | "stata": {
1231 | "color": null,
1232 | "url": "https://github.com/trending?l=stata"
1233 | },
1234 | "supercollider": {
1235 | "color": "#46390b",
1236 | "url": "https://github.com/trending?l=supercollider"
1237 | },
1238 | "swift": {
1239 | "color": "#ffac45",
1240 | "url": "https://github.com/trending?l=swift"
1241 | },
1242 | "systemverilog": {
1243 | "color": "#dae1c2",
1244 | "url": "https://github.com/trending?l=systemverilog"
1245 | },
1246 | "tcl": {
1247 | "color": "#e4cc98",
1248 | "url": "https://github.com/trending?l=tcl"
1249 | },
1250 | "tcsh": {
1251 | "color": null,
1252 | "url": "https://github.com/trending?l=tcsh"
1253 | },
1254 | "terra": {
1255 | "color": "#00004c",
1256 | "url": "https://github.com/trending?l=terra"
1257 | },
1258 | "tex": {
1259 | "color": "#3d6117",
1260 | "url": "https://github.com/trending?l=tex"
1261 | },
1262 | "thrift": {
1263 | "color": null,
1264 | "url": "https://github.com/trending?l=thrift"
1265 | },
1266 | "ti program": {
1267 | "color": "#a0aa87",
1268 | "url": "https://github.com/trending?l=ti-program"
1269 | },
1270 | "tla": {
1271 | "color": null,
1272 | "url": "https://github.com/trending?l=tla"
1273 | },
1274 | "turing": {
1275 | "color": "#cf142b",
1276 | "url": "https://github.com/trending?l=turing"
1277 | },
1278 | "txl": {
1279 | "color": null,
1280 | "url": "https://github.com/trending?l=txl"
1281 | },
1282 | "typescript": {
1283 | "color": "#2b7489",
1284 | "url": "https://github.com/trending?l=typescript"
1285 | },
1286 | "unified parallel c": {
1287 | "color": null,
1288 | "url": "https://github.com/trending?l=unified-parallel-c"
1289 | },
1290 | "unix assembly": {
1291 | "color": null,
1292 | "url": "https://github.com/trending?l=unix-assembly"
1293 | },
1294 | "uno": {
1295 | "color": null,
1296 | "url": "https://github.com/trending?l=uno"
1297 | },
1298 | "unrealscript": {
1299 | "color": "#a54c4d",
1300 | "url": "https://github.com/trending?l=unrealscript"
1301 | },
1302 | "urweb": {
1303 | "color": null,
1304 | "url": "https://github.com/trending?l=urweb"
1305 | },
1306 | "vala": {
1307 | "color": "#fbe5cd",
1308 | "url": "https://github.com/trending?l=vala"
1309 | },
1310 | "vcl": {
1311 | "color": null,
1312 | "url": "https://github.com/trending?l=vcl"
1313 | },
1314 | "verilog": {
1315 | "color": "#b2b7f8",
1316 | "url": "https://github.com/trending?l=verilog"
1317 | },
1318 | "vhdl": {
1319 | "color": "#adb2cb",
1320 | "url": "https://github.com/trending?l=vhdl"
1321 | },
1322 | "vim script": {
1323 | "color": "#199f4b",
1324 | "url": "https://github.com/trending?l=vim-script"
1325 | },
1326 | "visual basic": {
1327 | "color": "#945db7",
1328 | "url": "https://github.com/trending?l=visual-basic"
1329 | },
1330 | "volt": {
1331 | "color": "#1f1f1f",
1332 | "url": "https://github.com/trending?l=volt"
1333 | },
1334 | "vue": {
1335 | "color": "#2c3e50",
1336 | "url": "https://github.com/trending?l=vue"
1337 | },
1338 | "webassembly": {
1339 | "color": "#04133b",
1340 | "url": "https://github.com/trending?l=webassembly"
1341 | },
1342 | "webidl": {
1343 | "color": null,
1344 | "url": "https://github.com/trending?l=webidl"
1345 | },
1346 | "wisp": {
1347 | "color": "#7582d1",
1348 | "url": "https://github.com/trending?l=wisp"
1349 | },
1350 | "x10": {
1351 | "color": "#4b6bef",
1352 | "url": "https://github.com/trending?l=x10"
1353 | },
1354 | "xbase": {
1355 | "color": "#403a40",
1356 | "url": "https://github.com/trending?l=xbase"
1357 | },
1358 | "xc": {
1359 | "color": "#99da07",
1360 | "url": "https://github.com/trending?l=xc"
1361 | },
1362 | "xojo": {
1363 | "color": null,
1364 | "url": "https://github.com/trending?l=xojo"
1365 | },
1366 | "xproc": {
1367 | "color": null,
1368 | "url": "https://github.com/trending?l=xproc"
1369 | },
1370 | "xquery": {
1371 | "color": "#5232e7",
1372 | "url": "https://github.com/trending?l=xquery"
1373 | },
1374 | "xs": {
1375 | "color": null,
1376 | "url": "https://github.com/trending?l=xs"
1377 | },
1378 | "xslt": {
1379 | "color": "#eb8ceb",
1380 | "url": "https://github.com/trending?l=xslt"
1381 | },
1382 | "xtend": {
1383 | "color": null,
1384 | "url": "https://github.com/trending?l=xtend"
1385 | },
1386 | "yacc": {
1387 | "color": "#4b6c4b",
1388 | "url": "https://github.com/trending?l=yacc"
1389 | },
1390 | "zephir": {
1391 | "color": "#118f9e",
1392 | "url": "https://github.com/trending?l=zephir"
1393 | },
1394 | "zimpl": {
1395 | "color": null,
1396 | "url": "https://github.com/trending?l=zimpl"
1397 | }
1398 | }
1399 |
--------------------------------------------------------------------------------
/src/client/store/store.js:
--------------------------------------------------------------------------------
1 | import 'isomorphic-fetch'
2 | import { merge, find, compact, orderBy } from 'lodash'
3 | import utils from '~/utils'
4 | import { languageColor } from '~/utils/colors'
5 |
6 | const baseUrl = 'https://developersdo.github.io/opensource-data/'
7 |
8 | const cache = {
9 | repos: null,
10 | users: null,
11 | }
12 |
13 | const fetcher = {
14 | repos: null,
15 | users: null,
16 | }
17 |
18 | const store = {
19 | getRepos({ force } = { force: false }) {
20 | if (cache.repos && !force) {
21 | return Promise.resolve(cache.repos)
22 | }
23 | if (fetcher.repos) {
24 | return fetcher.repos
25 | }
26 | fetcher.repos = fetch(`${baseUrl}/repos.json`)
27 | .then((response) => response.json())
28 | .then((response) => Promise.all(response.map(transformRepo)))
29 | .then((response) => {
30 | cache.repos = { error: false, ready: true, items: response }
31 | return cache.repos
32 | })
33 | .catch((error) => {
34 | console.error('Cannot fetch repos data.', error)
35 | return { error, ready: false, items: [] }
36 | })
37 | return fetcher.repos
38 | },
39 | getUsers({ force } = { force: false }) {
40 | if (cache.users && !force) {
41 | return Promise.resolve(cache.users)
42 | }
43 | if (fetcher.users) {
44 | return fetcher.users
45 | }
46 | fetcher.users = fetch(`${baseUrl}/users.json`)
47 | .then((response) => response.json())
48 | .then((response) => response.map(transformUser))
49 | .then((response) => {
50 | cache.users = { error: false, ready: true, items: response }
51 | return cache.users
52 | })
53 | .catch((error) => {
54 | console.error('Cannot fetch users data.', error)
55 | return { error, ready: false, items: [] }
56 | })
57 | return fetcher.users
58 | }
59 | }
60 |
61 | function transformRepo(repo) {
62 | return new Promise((resolve, reject) => {
63 | return store.getUsers()
64 | .then((users) => {
65 | let owner = find(users.items, { login: repo.name.split('/')[0] })
66 | if (!owner) {
67 | owner = {}
68 | console.warn(`Could not find user by login: ${repo.name}, probably the user changed his login. More details at: https://github.com/developersdo/opensource/issues/89`)
69 | }
70 | return resolve(merge(repo, {
71 | normalizedName: utils.unicodeNormalize(repo.name),
72 | normalizedDescription: utils.unicodeNormalize(repo.description),
73 | languages: parseLanguages(repo.languages),
74 | languageNames: repo.languages,
75 | user: owner,
76 | createdAt: new Date(repo.createdAt),
77 | }))
78 | })
79 | .catch(reject)
80 | })
81 | }
82 |
83 | function transformUser(user) {
84 | return merge(user, {
85 | normalizedName: utils.unicodeNormalize(user.name),
86 | githubUrl: `https://github.com/${user.login}`,
87 | createdAt: new Date(user.createdAt),
88 | })
89 | }
90 |
91 | function parseLanguages(input) {
92 | const names = compact(input.split(/\ +/g))
93 | const langs = names.map((name) => {
94 | return {
95 | name: name,
96 | color: languageColor(name).backgroundColor,
97 | }
98 | })
99 | return orderBy(langs, ['name'], ['asc'])
100 | }
101 |
102 | export default store
103 |
--------------------------------------------------------------------------------
/src/client/utils/colors.js:
--------------------------------------------------------------------------------
1 | const colors = require('~/store/colors.json')
2 |
3 | const hexToRgb = hex => {
4 | // turn hex val to RGB
5 | const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
6 | return result
7 | ? {
8 | r: parseInt(result[1], 16),
9 | g: parseInt(result[2], 16),
10 | b: parseInt(result[3], 16)
11 | }
12 | : null
13 | }
14 |
15 | // calc to work out if it will match on black or white better
16 | const setContrast = (rgb) =>
17 | (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000 > 125 ? 'black' : 'white'
18 |
19 | export const languageColor = (language) => {
20 | if (colors[language]) {
21 | const languageColor = colors[language].color || '#000000'
22 | return {
23 | backgroundColor: languageColor,
24 | textColor: setContrast(hexToRgb(languageColor))
25 | }
26 | } else {
27 | return {
28 | background: 'white',
29 | color: 'black'
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/client/utils/index.js:
--------------------------------------------------------------------------------
1 | import unorm from 'unorm'
2 |
3 | const utils = {
4 | /**
5 | * Escape RegExp special characters.
6 | * @param {String} str The string to escape.
7 | * @return {String}
8 | */
9 | escapeRegExp(str) {
10 | return str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
11 | },
12 |
13 | /**
14 | * Normalize an unicode string.
15 | * @param {String} str The string to normalize.
16 | * @return {String}
17 | */
18 | unicodeNormalize(str) {
19 | return unorm.nfkd(str).replace(/[\u0300-\u036F]/g, '')
20 | }
21 | }
22 |
23 | export default utils
24 |
--------------------------------------------------------------------------------