Updated web script to generate landing page

Prioritized webber over builder to make sure it never times out. Prioritized the index page over the rest of the pages as it takes long due to api calls.
This commit is contained in:
Angelos Chalaris
2018-04-07 17:40:44 +03:00
parent de79e12c5f
commit b8b99bc399
10 changed files with 364 additions and 2096 deletions

View File

@ -10,8 +10,8 @@ before_install:
script:
- npm run tagger
- npm run linter
- npm run builder
- npm run webber
- npm run builder
- npm run packager
- npm run tester
after_success:

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<link rel="stylesheet" href="./mini.css">
<title>30 seconds of code - Beginner Section</title>
<title>Snippets for Beginners - 30 seconds of code</title>
<meta charset="utf-8">
<meta name="description" content="Curated collection of useful Javascript snippets that you can understand in 30 seconds or less.">
<meta name="keywords" content="javascript, snippets, code, programming">

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -760,3 +760,7 @@ button.next {
font-weight: 700;
color: #fff;
}
body {
overflow-x: hidden;
}

View File

@ -62,6 +62,15 @@ const optimizeNodes = (data, regexp, replacer) => {
} while (count > 0);
return output;
};
// Randomizes the order of the values of an array, returning a new array.
const shuffle = ([...arr]) => {
let m = arr.length;
while (m) {
const i = Math.floor(Math.random() * m--);
[arr[m], arr[i]] = [arr[i], arr[m]];
}
return arr;
};
// Capitalizes the first letter of a string
const capitalize = (str, lowerRest = false) =>
str.slice(0, 1).toUpperCase() + (lowerRest ? str.slice(1).toLowerCase() : str.slice(1));
@ -69,4 +78,4 @@ const capitalize = (str, lowerRest = false) =>
const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env;
// Creates a hash for a value using the SHA-256 algorithm.
const hashData = val => crypto.createHash('sha256').update(val).digest('hex');
module.exports = {readSnippets, readTags, optimizeNodes, capitalize, objectFromPairs, isTravisCI, hashData};
module.exports = {readSnippets, readTags, optimizeNodes, capitalize, objectFromPairs, isTravisCI, hashData, shuffle};

View File

@ -4,6 +4,7 @@
*/
// Load modules
const fs = require('fs-extra'),
https = require('https'),
path = require('path'),
chalk = require('chalk'),
md = require('markdown-it')(),
@ -58,6 +59,7 @@ let snippets = {},
beginnerStartPart = '',
beginnerEndPart = '',
beginnerOutput = '',
indexStaticFile = '',
pagesOutput = [];
tagDbData = {};
// Start the timer of the script
@ -65,13 +67,15 @@ console.time('Webber');
// Synchronously read all snippets and sort them as necessary (case-insensitive)
snippets = util.readSnippets(snippetsPath);
// Load static parts for the index.html file
// Load static parts for all pages
try {
startPart = fs.readFileSync(path.join(staticPartsPath, 'page-start.html'), 'utf8');
endPart = fs.readFileSync(path.join(staticPartsPath, 'page-end.html'), 'utf8');
beginnerStartPart = fs.readFileSync(path.join(staticPartsPath, 'beginner-page-start.html'), 'utf8');
beginnerEndPart = fs.readFileSync(path.join(staticPartsPath, 'beginner-page-end.html'), 'utf8');
indexStaticFile = fs.readFileSync(path.join(staticPartsPath, 'index.html'), 'utf8');
} catch (err) {
// Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During static part loading: ${err}`);
@ -79,7 +83,67 @@ try {
}
// Load tag data from the database
tagDbData = util.readTags();
// Create the output for the index.html file
// Create the output for the index.html file (only locally or on Travis CRON or custom job)
if(!util.isTravisCI() || (util.isTravisCI() && (process.env['TRAVIS_EVENT_TYPE'] === 'cron' || process.env['TRAVIS_EVENT_TYPE'] === 'api'))) {
try {
// Shuffle the array of snippets, pick 3
let indexDailyPicks = '';
let shuffledSnippets = util.shuffle(Object.keys(snippets)).slice(0,3);
const dailyPicks = Object.keys(snippets)
.filter(key => shuffledSnippets.includes(key))
.reduce((obj, key) => {
obj[key] = snippets[key];
return obj;
}, {});
// Generate the html for the picked snippets
for (let snippet of Object.entries(dailyPicks))
indexDailyPicks +=
'<div class="card fluid pick">' +
md
.render(`\n${snippets[snippet[0]]}`)
.replace(/<h3/g, `<h3 id="${snippet[0].toLowerCase()}" class="section double-padded"`)
.replace(/<\/h3>/g, `${snippet[1].includes('advanced')?'<mark class="tag">advanced</mark>':''}</h3>`)
.replace(/<\/h3>/g, '</h3><div class="section double-padded">')
.replace(/<pre><code class="language-js">([^\0]*?)<\/code><\/pre>/gm, (match, p1) => `<pre class="language-js">${Prism.highlight(unescapeHTML(p1), Prism.languages.javascript)}</pre>`)
.replace(/<\/pre>\s+<pre/g, '</pre><label class="collapse">Show examples</label><pre') +
'<button class="primary clipboard-copy">&#128203;&nbsp;Copy to clipboard</button>' +
'</div></div>';
// Select the first snippet from today's picks
indexDailyPicks = indexDailyPicks.replace('card fluid pick', 'card fluid pick selected');
// Optimize punctuation nodes
indexDailyPicks = util.optimizeNodes(indexDailyPicks, /<span class="token punctuation">([^\0<]*?)<\/span>([\n\r\s]*)<span class="token punctuation">([^\0]*?)<\/span>/gm, (match, p1, p2, p3) => `<span class="token punctuation">${p1}${p2}${p3}</span>`);
// Optimize operator nodes
indexDailyPicks = util.optimizeNodes(indexDailyPicks, /<span class="token operator">([^\0<]*?)<\/span>([\n\r\s]*)<span class="token operator">([^\0]*?)<\/span>/gm, (match, p1, p2, p3) => `<span class="token operator">${p1}${p2}${p3}</span>`);
// Optimize keyword nodes
indexDailyPicks = util.optimizeNodes(indexDailyPicks, /<span class="token keyword">([^\0<]*?)<\/span>([\n\r\s]*)<span class="token keyword">([^\0]*?)<\/span>/gm, (match, p1, p2, p3) => `<span class="token keyword">${p1}${p2}${p3}</span>`);
// Put the daily picks into the page
indexStaticFile = indexStaticFile.replace('$daily-picks',indexDailyPicks);
// Use the Github API to get the needed data
const githubApi = 'api.github.com';
const headers = { 'User-Agent' : '30-seconds-of-code'};
// Send requests and wait for responses, write to the page
https.get({host: githubApi, path: '/repos/chalarangelo/30-seconds-of-code/commits?per_page=1', headers: headers}, resCommits =>{
https.get({host: githubApi, path: '/repos/chalarangelo/30-seconds-of-code/contributors?per_page=1', headers: headers}, resContributors => {
https.get({host: githubApi, path: '/repos/chalarangelo/30-seconds-of-code/stargazers?per_page=1', headers: headers}, resStars => {
let commits = resCommits.headers.link.split('&').slice(-1)[0].replace(/[^\d]/g,''),
contribs = resContributors.headers.link.split('&').slice(-1)[0].replace(/[^\d]/g,''),
stars = resStars.headers.link.split('&').slice(-1)[0].replace(/[^\d]/g,'');
indexStaticFile = indexStaticFile.replace(/\$snippet-count/g, Object.keys(snippets).length).replace(/\$commit-count/g,commits).replace(/\$contrib-count/g,contribs).replace(/\$star-count/g,stars);
// Generate 'index.html' file
fs.writeFileSync(path.join(docsPath, 'index.html'), indexStaticFile);
console.log(`${chalk.green('SUCCESS!')} index.html file generated!`);
});
});
});
} catch (err) {
console.log(`${chalk.red('ERROR!')} During index.html generation: ${err}`);
process.exit(1);
}
}
// Create the output for individual category pages
try {
// Add the start static part
output += `${startPart + '\n'}`;
@ -125,6 +189,7 @@ try {
'</div></div>';
// Add the ending static part
localOutput += `\n${endPart + '\n'}`;
// Optimize punctuation nodes
localOutput = util.optimizeNodes(localOutput, /<span class="token punctuation">([^\0<]*?)<\/span>([\n\r\s]*)<span class="token punctuation">([^\0]*?)<\/span>/gm, (match, p1, p2, p3) => `<span class="token punctuation">${p1}${p2}${p3}</span>`);
// Optimize operator nodes
localOutput = util.optimizeNodes(localOutput, /<span class="token operator">([^\0<]*?)<\/span>([\n\r\s]*)<span class="token operator">([^\0]*?)<\/span>/gm, (match, p1, p2, p3) => `<span class="token operator">${p1}${p2}${p3}</span>`);
@ -153,8 +218,6 @@ try {
fs.writeFileSync(path.join(docsPath, page.tag+'.html'), page.content);
console.log(`${chalk.green('SUCCESS!')} ${page.tag}.html file generated!`);
})
// Write to the index.html file
//fs.writeFileSync(path.join(docsPath, 'index.html'), output);
} catch (err) {
// Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During category page generation: ${err}`);
@ -162,7 +225,6 @@ try {
}
// Create the output for the beginner.html file
try {
// Add the static part
beginnerOutput += `${beginnerStartPart + '\n'}`;
@ -190,6 +252,7 @@ try {
'<button class="primary clipboard-copy">&#128203;&nbsp;Copy to clipboard</button>' +
'</div></div></div></div>';
// Optimize punctuation nodes
beginnerOutput = util.optimizeNodes(beginnerOutput, /<span class="token punctuation">([^\0<]*?)<\/span>([\n\r\s]*)<span class="token punctuation">([^\0]*?)<\/span>/gm, (match, p1, p2, p3) => `<span class="token punctuation">${p1}${p2}${p3}</span>`);
// Optimize operator nodes
beginnerOutput = util.optimizeNodes(beginnerOutput, /<span class="token operator">([^\0<]*?)<\/span>([\n\r\s]*)<span class="token operator">([^\0]*?)<\/span>/gm, (match, p1, p2, p3) => `<span class="token operator">${p1}${p2}${p3}</span>`);

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<link rel="stylesheet" href="./mini.css">
<title>30 seconds of code - Beginner Section</title>
<title>Snippets for Beginners - 30 seconds of code</title>
<meta charset="utf-8">
<meta name="description" content="Curated collection of useful Javascript snippets that you can understand in 30 seconds or less.">
<meta name="keywords" content="javascript, snippets, code, programming">

View File

@ -24,19 +24,19 @@
<div class="row">
<div class="col-sm-3 no-padding" style="text-align: center">
<svg version="1.1" width="24" height="24" viewBox="0 0 14 16" class="octicon octicon-code" aria-hidden="true"><path fill-rule="evenodd" d="M9.5 3L8 4.5 11.5 8 8 11.5 9.5 13 14 8 9.5 3zm-5 0L0 8l4.5 5L6 11.5 2.5 8 6 4.5 4.5 3z"/></svg>
<p><span id="snippet-count">295</span><br/>snippets</p>
<p><span id="snippet-count">$snippet-count</span><br/>snippets</p>
</div>
<div class="col-sm-3 no-padding" style="text-align: center">
<svg version="1.1" width="24" height="24" viewBox="0 0 16 16" class="octicon octicon-organization" aria-hidden="true"><path fill-rule="evenodd" d="M16 12.999c0 .439-.45 1-1 1H7.995c-.539 0-.994-.447-.995-.999H1c-.54 0-1-.561-1-1 0-2.634 3-4 3-4s.229-.409 0-1c-.841-.621-1.058-.59-1-3 .058-2.419 1.367-3 2.5-3s2.442.58 2.5 3c.058 2.41-.159 2.379-1 3-.229.59 0 1 0 1s1.549.711 2.42 2.088A6.78 6.78 0 0 1 10 8.999s.229-.409 0-1c-.841-.62-1.058-.59-1-3 .058-2.419 1.367-3 2.5-3s2.437.581 2.495 3c.059 2.41-.158 2.38-1 3-.229.59 0 1 0 1s3.005 1.366 3.005 4z"/></svg>
<p><span id="contrib-count">114</span><br/>contributors</p>
<p><span id="contrib-count">$contrib-count</span><br/>contributors</p>
</div>
<div class="col-sm-3 no-padding" style="text-align: center">
<svg version="1.1" width="24" height="24" viewBox="0 0 10 16" class="octicon octicon-git-branch" aria-hidden="true"><path fill-rule="evenodd" d="M10 5c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v.3c-.02.52-.23.98-.63 1.38-.4.4-.86.61-1.38.63-.83.02-1.48.16-2 .45V4.72a1.993 1.993 0 0 0-1-3.72C.88 1 0 1.89 0 3a2 2 0 0 0 1 1.72v6.56c-.59.35-1 .99-1 1.72 0 1.11.89 2 2 2 1.11 0 2-.89 2-2 0-.53-.2-1-.53-1.36.09-.06.48-.41.59-.47.25-.11.56-.17.94-.17 1.05-.05 1.95-.45 2.75-1.25S8.95 7.77 9 6.73h-.02C9.59 6.37 10 5.73 10 5zM2 1.8c.66 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2C1.35 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2zm0 12.41c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm6-8c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/></svg>
<p><span id="commit-count">3028</span><br/>commits</p>
<p><span id="commit-count">$commit-count</span><br/>commits</p>
</div>
<div class="col-sm-3 no-padding" style="text-align: center">
<svg version="1.1" width="24" height="24" viewBox="0 0 14 16" class="octicon octicon-star" aria-hidden="true"><path 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"/></svg>
<p><span id="star-count">19459</span><br/>stars</p>
<p><span id="star-count">$star-count</span><br/>stars</p>
</div>
</div>
</div>
@ -65,16 +65,7 @@
<div id="pick-slider">
<button class="next"><svg version="1.1" width="8" height="16" viewBox="0 0 8 16" class="octicon octicon-chevron-right" aria-hidden="true"><path fill-rule="evenodd" d="M7.5 8l-5 5L1 11.5 4.75 8 1 4.5 2.5 3l5 5z"/></svg></button>
<button class="previous"><svg version="1.1" width="8" height="16" viewBox="0 0 8 16" class="octicon octicon-chevron-left" aria-hidden="true"><path fill-rule="evenodd" d="M6 3l1.5 1.5L3.75 8l3.75 3.5L6 13 1 8l5-5z"/></svg></button>
<div class="card fluid pick selected">
<h3 id="bottomvisible" class="section double-padded">bottomVisible</h3><div class="section double-padded"><p>Returns <code>true</code> if the bottom of the page is visible, <code>false</code> otherwise.</p><p>Use <code>scrollY</code>, <code>scrollHeight</code> and <code>clientHeight</code> to determine if the bottom of the page is visible.</p><pre class="language-js"><span class="token keyword">const</span> <span class="token function-variable function">bottomVisible</span> <span class="token operator">=</span> <span class="token punctuation">()</span> <span class="token operator">=&gt;</span>
document<span class="token punctuation">.</span>documentElement<span class="token punctuation">.</span>clientHeight <span class="token operator">+</span> window<span class="token punctuation">.</span>scrollY <span class="token operator">&gt;=</span>
<span class="token punctuation">(</span>document<span class="token punctuation">.</span>documentElement<span class="token punctuation">.</span>scrollHeight <span class="token operator">||</span> document<span class="token punctuation">.</span>documentElement<span class="token punctuation">.</span>clientHeight<span class="token punctuation">);</span>
</pre><label class="collapse">Show examples</label><pre class="language-js"><span class="token function">bottomVisible</span><span class="token punctuation">();</span> <span class="token comment">// true</span>
</pre></div></div>
<div class="card fluid pick"><h3 id="ary" class="section double-padded">ary</h3><div class="section double-padded"><p>Creates a function that accepts up to <code>n</code> arguments, ignoring any additional arguments.</p><p>Call the provided function, <code>fn</code>, with up to <code>n</code> arguments, using <code>Array.slice(0,n)</code> and the spread operator (<code>...</code>).</p><pre class="language-js"><span class="token keyword">const</span> <span class="token function-variable function">ary</span> <span class="token operator">=</span> <span class="token punctuation">(</span>fn<span class="token punctuation">,</span> n<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">(</span><span class="token operator">...</span>args<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token function">fn</span><span class="token punctuation">(</span><span class="token operator">...</span>args<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> n<span class="token punctuation">));</span>
</pre><label class="collapse">Show examples</label><pre class="language-js"><span class="token keyword">const</span> firstTwoMax <span class="token operator">=</span> <span class="token function">ary</span><span class="token punctuation">(</span>Math<span class="token punctuation">.</span>max<span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">);
[[</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token string">'a'</span><span class="token punctuation">], [</span><span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">], [</span><span class="token number">10</span><span class="token punctuation">]].</span><span class="token function">map</span><span class="token punctuation">(</span>x <span class="token operator">=&gt;</span> <span class="token function">firstTwoMax</span><span class="token punctuation">(</span><span class="token operator">...</span>x<span class="token punctuation">));</span> <span class="token comment">// [6, 8, 10]</span>
</pre></div></div>
$daily-picks
<br/>
</div>
</div>
@ -191,7 +182,7 @@
<script>
window.onload = function(){
let counters = ['#snippet-count', '#contrib-count', '#commit-count', '#star-count'];
let values = [295,114,3028,19459];
let values = [$snippet-count,$contrib-count,$commit-count,$star-count];
let steps = [1,1,8,42];
runCounter(counters[0],0,values[0],steps[0]);
runCounter(counters[1],0,values[1],steps[1]);

File diff suppressed because one or more lines are too long