├── .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 SourceDiscover 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 | ![Dominican Open Source - Discover the open source ecosystem related to the Dominican Republic!](.github/banner.svg) 2 | 3 | [![GitHub license](https://img.shields.io/github/license/developersdo/opensource.svg)](https://github.com/developersdo/opensource/blob/develop/LICENSE) 4 | [![CircleCI](https://circleci.com/gh/developersdo/opensource.svg?style=svg)](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 |
51 | With ♥︎ from all contributors. 52 |
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 | 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 | {
{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 |
5 |
6 |
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 | 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 | linkGitHub 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 | 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 |
    25 |
    26 | 27 |
    28 |
    29 | 30 |
    31 |
    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 |
    71 |
    72 |
    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 | --------------------------------------------------------------------------------