Skip to content

Commit

Permalink
✨ Display GitHub stars count on each workshop
Browse files Browse the repository at this point in the history
  • Loading branch information
marcpicaud committed Nov 25, 2018
1 parent 9512999 commit 40ad1ab
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 13 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Generate your GitHub Personnal Access Token here: https://github.com/settings/tokens
GITHUB_PERSONAL_ACCESS_TOKEN=put_your_github_token_here
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.DS_Store
.env
.idea
.build*
_site
Expand Down
18 changes: 12 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ We ask that you make pull requests because changes to this repository will get d

## Running the entire app locally

This is a static site with a build step, simply run `npm start`:
This is a static site with a build step. The build step uses a [GitHub Personnal Access Token](https://github.com/settings/tokens) that you need to generate and put in a .env file. **Actually you don't need to configure any authorization on this access token**, it just serves the purpose of unleashing the GitHub API Rate Limit.

```
cp .env.example .env
// then put your GitHub Personnal Access Token in the .env file
```
After that, simply run `npm start`:

```
npm install
Expand All @@ -25,10 +31,10 @@ Please refer to the [nodeschool site](http://nodeschool.io/#workshoppers) for de

- **Globally** (easiest)

Depending on the npm version, `npm packages` get installed in different routes. To have access to them globally. Do
Depending on the npm version, `npm packages` get installed in different routes. To have access to them globally. Do

`npm install -global package_name` or `npm install -g package_name`

If you get a `permission denied` **error**. Run the previous command with `sudo`.

`sudo npm install -g package_name`
Expand All @@ -52,10 +58,10 @@ If you would like to keep all the node_school workshop packages inside a custom
```
~ mkdir -p node_school
cd node_school
npm install javascripting
npm install javascripting
```

From within the `node_school` directory now run `node_modules/learnyounode/bin/javascripting` to start it.
From within the `node_school` directory now run `node_modules/learnyounode/bin/javascripting` to start it.

This is because you need to run the executable from within the directory itself since it's not available globally in your `$PATH`

Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@
"devDependencies": {
"after-all": "^2.0.1",
"autoprefixer-stylus": "^0.9.4",
"axios": "^0.18.0",
"browserify": "^12.0.1",
"cheerio": "^0.19.0",
"dotenv": "^6.1.0",
"gaze": "^0.5.1",
"glob": "^6.0.3",
"jsdom": "^7.1.0",
Expand Down
80 changes: 74 additions & 6 deletions scripts/build-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,25 @@ const Path = require('path')
const Fs = require('fs')
const jsdom = require('jsdom')
const mkdirp = require('mkdirp')
const { performance } = require('perf_hooks');
const cmdwatcher = require('./util/cmdwatcher')
const LANGS = Path.join(__dirname, '../languages/languages.json')
const FOOTER = Path.join(__dirname, '../footer.html')

const env = require('dotenv').config();
if (env.error) {
throw env.error;
}

if (!process.env.GITHUB_PERSONAL_ACCESS_TOKEN) {
throw new Error('GITHUB_PERSONAL_ACCESS_TOKEN environment variable is not found');
}

const axios = require('axios').create({
baseURL: 'https://api.github.com/',
headers: { 'Authorization': `token ${process.env.GITHUB_PERSONAL_ACCESS_TOKEN}` }
});

function createLangButton(dom, file, lang, langName) {
var li = dom.createElement('li')
li.className = 'nav-lang-' + lang
Expand Down Expand Up @@ -71,6 +86,50 @@ function getNodeByLanguage(nodes, lang) {
}
}

async function getStargazers(workshopElement) {
const url = require('url');
const githubUrl = workshopElement.getAttribute("href");
let response, parsedUrl;

if (!githubUrl) {
return 0;
}

try {
parsedUrl = url.parse(githubUrl);
} catch (e) {
throw e;
}

try {
response = await axios.get(`/repos${parsedUrl.path}?per_page=1`);
} catch (e) {
throw e;
}
writeStargazers(workshopElement, response.data.stargazers_count)
}

function writeStargazers(workshopElement, stargazersCount) {
const starIconSVG = `<svg style="vertical-align: middle" viewBox="0 0 16 16" version="1.1" width="16" height="16" role="img"><path fill="currentColor" fill-rule="evenodd" d="M14 6l-4.9-.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14 7 11.67 11.33 14l-.93-4.74L14 6z"></path></svg>`;
workshopElement.innerHTML = `
<span>${workshopElement.innerHTML}</span>
<span>(${starIconSVG}${kFormatter(stargazersCount)})<span>
`;
}

function kFormatter(number) {
return number > 999 ? (number / 1000).toFixed(1) + 'k' : number
}

async function isRateLimitReached(nbToPerform) {
const remaining = await axios.get('/rate_limit')
if (remaining.data.resources.core.remaining < nbToPerform) {
console.error(`💔 GitHub Rate Limit Reached. Reset at ${new Date(remaining.data.resources.core.reset * 1000).toLocaleTimeString()}`);
return true;
}
return false;
}

cmdwatcher('build-html'
, '!(node_modules).html'
, 'languages/**'
Expand Down Expand Up @@ -102,27 +161,36 @@ cmdwatcher('build-html'
}
})
languages['en'] = 'English'
files.forEach(function (file) {
files.forEach(async function (file) {
var raw
, dom
, original
, original
try {
raw = Fs.readFileSync(file, 'utf8')
} catch(e) {
return console.log('Error while reading %s:\n%s', file, e)
}
try {
dom = jsdom.jsdom(raw)
dom = jsdom.jsdom(raw)
if (file === 'index.html') {
const t0 = performance.now();
const workshops = dom.getElementsByClassName('js-workshop-link');
await isRateLimitReached(workshops.length);
const githubPromises = Array.from(workshops).map(getStargazers);
await Promise.all(githubPromises);
const t1 = performance.now();
console.log(`⭐️ GitHub Stargazers fetched in ${((t1 - t0) / 1000).toFixed(1)}s`)
}
} catch(e) {
return console.log('Error while domify %s:\n%s', file, e)
}
return console.log('Error while domify %s:\n%s', file, e)
}

var footer = dom.querySelector('footer')
if(footer) {
var footerHtml = Fs.readFileSync(FOOTER, 'utf8')
footer.innerHTML = footerHtml
}

var list = dom.querySelectorAll('[data-i18n]')
if (list) {
original = {}
Expand Down
6 changes: 6 additions & 0 deletions scripts/build.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
#!/bin/bash
if [[ -f ../.env ]]
then
echo 'Missing .env file'
echo 'Please consult README for setup instructions'
exit 1
fi
npm run build-chapters -- $@
npm run generate-css
npm run build-dependencies
Expand Down
3 changes: 2 additions & 1 deletion styles/style.styl
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,8 @@ span.no-break { display:inline-block; }
font-family: Source Code Pro, monospace;
font-weight: 500;
text-decoration: none;
display: block;
display: flex;
justify-content: space-between;
border: none;
}

Expand Down

0 comments on commit 40ad1ab

Please sign in to comment.