fix conflicts

This commit is contained in:
atomiks
2017-12-30 07:19:12 +11:00
parent 6219892639
commit ec09fbddec
9 changed files with 424 additions and 307 deletions

View File

@ -10,25 +10,21 @@
"tape": "^4.8.0"
},
"name": "30-seconds-of-code",
"description": "A collection of useful Javascript snippets.",
"description": "A collection of useful JavaScript snippets.",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"builder": "node ./scripts/build-script.js",
"linter": "node ./scripts/lint-script.js",
"tagger": "node ./scripts/tag-script.js",
"webber": "node ./scripts/web-script.js",
"tdd": "node ./scripts/tdd-script.js"
"builder": "node ./scripts/build.js",
"linter": "node ./scripts/lint.js",
"tagger": "node ./scripts/tag.js",
"webber": "node ./scripts/web.js",
"tdd": "node ./scripts/tdd.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Chalarangelo/30-seconds-of-code.git"
},
"keywords": [
"javascript",
"snippets",
"list"
],
"keywords": ["javascript", "snippets", "list"],
"author": "Chalarangelo (chalarangelo@gmail.com)",
"license": "MIT",
"bugs": {

View File

@ -1,99 +0,0 @@
/*
This is the builder script that generates the README file.
Run using `npm run builder`.
*/
// Load modules
const fs = require('fs-extra'), path = require('path'), chalk = require('chalk');
// Set variables for paths
const snippetsPath = './snippets', staticPartsPath = './static-parts';
// Set variables for script
let snippets = {}, startPart = '', endPart = '', output = '', tagDbData = {};
// Load helper functions (these are from existing snippets in 30 seconds of code!)
const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {});
const capitalize = (str, lowerRest = false) => str.slice(0, 1).toUpperCase() + (lowerRest ? str.slice(1).toLowerCase() : str.slice(1));
// Start the timer of the script
console.time('Builder');
// Synchronously read all snippets and sort them as necessary (case-insensitive)
try {
let snippetFilenames = fs.readdirSync(snippetsPath);
snippetFilenames.sort((a, b) => {
a = a.toLowerCase();
b = b.toLowerCase();
if (a < b) return -1;
if (a > b) return 1;
return 0;
});
// Store the data read from each snippet in the appropriate object
for(let snippet of snippetFilenames) snippets[snippet] = fs.readFileSync(path.join(snippetsPath,snippet),'utf8');
}
catch (err){ // Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During snippet loading: ${err}`);
process.exit(1);
}
// Load static parts for the README file
try {
startPart = fs.readFileSync(path.join(staticPartsPath,'README-start.md'),'utf8');
endPart = fs.readFileSync(path.join(staticPartsPath,'README-end.md'),'utf8');
}
catch (err){ // Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During static part loading: ${err}`);
process.exit(1);
}
// Load tag data from the database
try {
tagDbData = objectFromPairs(fs.readFileSync('tag_database','utf8').split('\n').slice(0,-1).map(v => v.split(':').slice(0,2)));
}
catch (err){ // Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During tag database loading: ${err}`);
process.exit(1);
}
// Create the output for the README file
try {
// Add the start static part
output += `${startPart+'\n'}`;
// Loop over tags and snippets to create the table of contents
let uncategorizedOutput = '';
for(let tag of [...new Set(Object.entries(tagDbData).map(t => t[1]))].filter(v => v).sort((a,b) => a.localeCompare(b))){
if(capitalize(tag, true)=='Uncategorized') {
uncategorizedOutput +=`### _${capitalize(tag, true)}_\n\n<details>\n<summary>View contents</summary>\n\n`;
for(let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag))
uncategorizedOutput += `* [\`${taggedSnippet[0]}\`](#${taggedSnippet[0].toLowerCase()})\n`
uncategorizedOutput += '\n</details>\n\n';
} else {
output +=`### ${capitalize(tag, true)}\n\n<details>\n<summary>View contents</summary>\n\n`;
for(let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag))
output += `* [\`${taggedSnippet[0]}\`](#${taggedSnippet[0].toLowerCase()})\n`
output += '\n</details>\n\n';
}
}
output += uncategorizedOutput;
uncategorizedOutput = '';
// Loop over tags and snippets to create the list of snippets
for(let tag of [...new Set(Object.entries(tagDbData).map(t => t[1]))].filter(v => v).sort((a,b) => a.localeCompare(b))){
if(capitalize(tag, true)=='Uncategorized') {
uncategorizedOutput +=`## _${capitalize(tag, true)}_\n`;
for(let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag))
uncategorizedOutput += `\n${snippets[taggedSnippet[0]+'.md']+'\n<br>[⬆ back to top](#table-of-contents)\n\n'}`;
} else {
output +=`## ${capitalize(tag, true)}\n`;
for(let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag)){
let data = snippets[taggedSnippet[0]+'.md'];
data = data.slice(0,data.lastIndexOf('```js')) + '<details>\n<summary>Examples</summary>\n\n' + data.slice(data.lastIndexOf('```js'),data.lastIndexOf('```')) + data.slice(data.lastIndexOf('```')) + '\n</details>\n';
output += `\n${data+'\n<br>[⬆ Back to top](#table-of-contents)\n\n'}`;
}
}
}
output += uncategorizedOutput;
// Add the ending static part
output += `\n${endPart+'\n'}`;
// Write to the README file
fs.writeFileSync('README.md', output);
}
catch (err){ // Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During README generation: ${err}`);
process.exit(1);
}
// Log a success message
console.log(`${chalk.green('SUCCESS!')} README file generated!`);
// Log the time taken
console.timeEnd('Builder');

127
scripts/build.js Normal file
View File

@ -0,0 +1,127 @@
/*
This is the builder script that generates the README file.
Run using `npm run builder`.
*/
// Load modules
const fs = require('fs-extra'),
path = require('path'),
chalk = require('chalk');
// Set variables for paths
const snippetsPath = './snippets',
staticPartsPath = './static-parts';
// Set variables for script
let snippets = {},
startPart = '',
endPart = '',
output = '',
tagDbData = {};
// Load helper functions (these are from existing snippets in 30 seconds of code!)
const objectFromPairs = arr => arr.reduce((a, v) => ((a[v[0]] = v[1]), a), {});
const capitalize = (str, lowerRest = false) =>
str.slice(0, 1).toUpperCase() + (lowerRest ? str.slice(1).toLowerCase() : str.slice(1));
// Start the timer of the script
console.time('Builder');
// Synchronously read all snippets and sort them as necessary (case-insensitive)
try {
let snippetFilenames = fs.readdirSync(snippetsPath);
snippetFilenames.sort((a, b) => {
a = a.toLowerCase();
b = b.toLowerCase();
if (a < b) return -1;
if (a > b) return 1;
return 0;
});
// Store the data read from each snippet in the appropriate object
for (let snippet of snippetFilenames)
snippets[snippet] = fs.readFileSync(path.join(snippetsPath, snippet), 'utf8');
} catch (err) {
// Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During snippet loading: ${err}`);
process.exit(1);
}
// Load static parts for the README file
try {
startPart = fs.readFileSync(path.join(staticPartsPath, 'README-start.md'), 'utf8');
endPart = fs.readFileSync(path.join(staticPartsPath, 'README-end.md'), 'utf8');
} catch (err) {
// Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During static part loading: ${err}`);
process.exit(1);
}
// Load tag data from the database
try {
tagDbData = objectFromPairs(
fs
.readFileSync('tag_database', 'utf8')
.split('\n')
.slice(0, -1)
.map(v => v.split(':').slice(0, 2))
);
} catch (err) {
// Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During tag database loading: ${err}`);
process.exit(1);
}
// Create the output for the README file
try {
// Add the start static part
output += `${startPart + '\n'}`;
// Loop over tags and snippets to create the table of contents
let uncategorizedOutput = '';
for (let tag of [...new Set(Object.entries(tagDbData).map(t => t[1]))]
.filter(v => v)
.sort((a, b) => a.localeCompare(b))) {
if (capitalize(tag, true) == 'Uncategorized') {
uncategorizedOutput += `### _${capitalize(
tag,
true
)}_\n\n<details>\n<summary>View contents</summary>\n\n`;
for (let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag))
uncategorizedOutput += `* [\`${taggedSnippet[0]}\`](#${taggedSnippet[0].toLowerCase()})\n`;
uncategorizedOutput += '\n</details>\n\n';
} else {
output += `### ${capitalize(tag, true)}\n\n<details>\n<summary>View contents</summary>\n\n`;
for (let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag))
output += `* [\`${taggedSnippet[0]}\`](#${taggedSnippet[0].toLowerCase()})\n`;
output += '\n</details>\n\n';
}
}
output += uncategorizedOutput;
uncategorizedOutput = '';
// Loop over tags and snippets to create the list of snippets
for (let tag of [...new Set(Object.entries(tagDbData).map(t => t[1]))]
.filter(v => v)
.sort((a, b) => a.localeCompare(b))) {
if (capitalize(tag, true) == 'Uncategorized') {
uncategorizedOutput += `## _${capitalize(tag, true)}_\n`;
for (let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag))
uncategorizedOutput += `\n${snippets[taggedSnippet[0] + '.md'] +
'\n<br>[⬆ back to top](#table-of-contents)\n\n'}`;
} else {
output += `## ${capitalize(tag, true)}\n`;
for (let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag)) {
let data = snippets[taggedSnippet[0] + '.md'];
data =
data.slice(0, data.lastIndexOf('```js')) +
'<details>\n<summary>Examples</summary>\n\n' +
data.slice(data.lastIndexOf('```js'), data.lastIndexOf('```')) +
data.slice(data.lastIndexOf('```')) +
'\n</details>\n';
output += `\n${data + '\n<br>[⬆ Back to top](#table-of-contents)\n\n'}`;
}
}
}
output += uncategorizedOutput;
// Add the ending static part
output += `\n${endPart + '\n'}`;
// Write to the README file
fs.writeFileSync('README.md', output);
} catch (err) {
// Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During README generation: ${err}`);
process.exit(1);
}
// Log a success message
console.log(`${chalk.green('SUCCESS!')} README file generated!`);
// Log the time taken
console.timeEnd('Builder');

View File

@ -18,7 +18,8 @@ const codeRE = /```\s*js([\s\S]*?)```/g;
console.time('Linter');
try {
const snippets = fs.readdirSync(SNIPPETS_PATH)
const snippets = fs
.readdirSync(SNIPPETS_PATH)
.sort((a, b) => a.toLowerCase() - b.toLowerCase())
// turn it into an object so we can add data to it to be used in a different scope
.map(name => ({ name }));
@ -46,7 +47,8 @@ try {
});
}
const cmd = `semistandard "${TEMP_PATH}" --fix & ` +
const cmd =
`semistandard "${TEMP_PATH}" --fix & ` +
`prettier "${TEMP_PATH}/*.js" --single-quote --print-width=100 --write`;
cp.exec(cmd, {}, (err, stdout, stderr) => {

View File

@ -3,14 +3,20 @@
Run using `npm run tagger`.
*/
// Load modules
const fs = require('fs-extra'), path = require('path'), chalk = require('chalk');
const fs = require('fs-extra'),
path = require('path'),
chalk = require('chalk');
// Set variables for paths
const snippetsPath = './snippets';
// Set variables for script
let snippets = {}, output = '', tagDbData = {}, missingTags = 0, tagDbStats = {};
let snippets = {},
output = '',
tagDbData = {},
missingTags = 0,
tagDbStats = {};
// Load helper functions (these are from existing snippets in 30 seconds of code!)
const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {});
const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
const objectFromPairs = arr => arr.reduce((a, v) => ((a[v[0]] = v[1]), a), {});
const countOccurrences = (arr, value) => arr.reduce((a, v) => (v === value ? a + 1 : a + 0), 0);
// Start the timer of the script
console.time('Tagger');
// Synchronously read all snippets and sort them as necessary (case-insensitive)
@ -24,43 +30,60 @@ try {
return 0;
});
// Store the data read from each snippet in the appropriate object
for(let snippet of snippetFilenames) snippets[snippet] = fs.readFileSync(path.join(snippetsPath,snippet),'utf8');
}
catch (err){ // Handle errors (hopefully not!)
for (let snippet of snippetFilenames)
snippets[snippet] = fs.readFileSync(path.join(snippetsPath, snippet), 'utf8');
} catch (err) {
// Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During snippet loading: ${err}`);
process.exit(1);
}
// Load tag data from the database
try {
tagDbData = objectFromPairs(fs.readFileSync('tag_database','utf8').split('\n').slice(0,-1).map(v => v.split(':').slice(0,2)));
tagDbStats = Object.entries(tagDbData).sort((a,b) => a[1].localeCompare(b[1])).reduce((acc, val) => {acc.hasOwnProperty(val[1]) ? acc[val[1]]++ : acc[val[1]] = 1; return acc;}, {});
}
catch (err){ // Handle errors (hopefully not!)
tagDbData = objectFromPairs(
fs
.readFileSync('tag_database', 'utf8')
.split('\n')
.slice(0, -1)
.map(v => v.split(':').slice(0, 2))
);
tagDbStats = Object.entries(tagDbData)
.sort((a, b) => a[1].localeCompare(b[1]))
.reduce((acc, val) => {
acc.hasOwnProperty(val[1]) ? acc[val[1]]++ : (acc[val[1]] = 1);
return acc;
}, {});
} catch (err) {
// Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During tag database loading: ${err}`);
process.exit(1);
}
// Update the listing of snippets in tag_database and log the statistics, along with missing scripts
try {
for(let snippet of Object.entries(snippets))
if(tagDbData.hasOwnProperty(snippet[0].slice(0,-3)) && tagDbData[snippet[0].slice(0,-3)].trim())
output += `${snippet[0].slice(0,-3)}:${tagDbData[snippet[0].slice(0,-3)].trim()}\n`;
for (let snippet of Object.entries(snippets))
if (
tagDbData.hasOwnProperty(snippet[0].slice(0, -3)) &&
tagDbData[snippet[0].slice(0, -3)].trim()
)
output += `${snippet[0].slice(0, -3)}:${tagDbData[snippet[0].slice(0, -3)].trim()}\n`;
else {
output += `${snippet[0].slice(0,-3)}:uncategorized\n`;
output += `${snippet[0].slice(0, -3)}:uncategorized\n`;
missingTags++;
console.log(`${chalk.yellow('Tagged uncategorized:')} ${snippet[0].slice(0,-3)}`);
console.log(`${chalk.yellow('Tagged uncategorized:')} ${snippet[0].slice(0, -3)}`);
}
// Write to tag_database
fs.writeFileSync('tag_database', output);
}
catch (err){ // Handle errors (hopefully not!)
} catch (err) {
// Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During tag_database generation: ${err}`);
process.exit(1);
}
// Log statistics for the tag_database file
console.log(`\n${chalk.bgWhite(chalk.black('=== TAG STATS ==='))}`)
for(let tagData of Object.entries(tagDbStats).filter(v => v[0] !== 'undefined'))
console.log(`\n${chalk.bgWhite(chalk.black('=== TAG STATS ==='))}`);
for (let tagData of Object.entries(tagDbStats).filter(v => v[0] !== 'undefined'))
console.log(`${chalk.green(tagData[0])}: ${tagData[1]} snippets`);
console.log(`${chalk.blue('New untagged snippets (will be tagged as \'uncategorized\'):')} ${missingTags}\n`);
console.log(
`${chalk.blue("New untagged snippets (will be tagged as 'uncategorized'):")} ${missingTags}\n`
);
// Log a success message
console.log(`${chalk.green('SUCCESS!')} tag_database file updated!`);
// Log the time taken

View File

@ -1,41 +0,0 @@
const fs = require('fs-extra');
const SNIPPETS_PATH = './snippets';
const TEST_PATH = './test';
const snippetFiles = fs.readdirSync(SNIPPETS_PATH, 'utf8')
.map(fileName => fileName.slice(0, -3));
fs.removeSync(TEST_PATH);
snippetFiles
.map(fileName => { fs.ensureDirSync(`${TEST_PATH}/${fileName}`); return fileName})
.map(fileName => {
const fileData = fs.readFileSync(`${SNIPPETS_PATH}/${fileName}.md`, 'utf8');
const fileCode = fileData.slice( fileData.indexOf('```js'), fileData.lastIndexOf('```') + 3 );
const blockMarkers = fileCode.split('\n').map((line, lineIndex) => line.slice(0, 3) === '```' ? lineIndex : '//CLEAR//').filter(x => !(x === '//CLEAR//'))
const fileFunction = fileCode.split('\n').map(line => line.trim()).filter((_, i) => blockMarkers[0] < i && i < blockMarkers[1]);
const fileExample = fileCode.split('\n').map(line => line.trim()).filter((_, i) => blockMarkers[2] < i && i < blockMarkers[3]);
const exportFile = `module.exports = ${fileFunction.join('\n').slice(17)}`;
const exportTest = [
`const test = require('tape');`,
`const ${fileName} = require('./${fileName}.js');`,
`test('Testing ${fileName}', (t) => {`,
`//For more information on all the methods supported by tape\n//Please go to https://github.com/substack/tape`,
`//t.deepEqual(${fileName}(args..), 'Expected');`,
`//t.equal(${fileName}(args..), 'Expected');`,
`//t.false(${fileName}(args..), 'Expected');`,
`//t.true(${fileName}(args..), 'Expected');`,
`//t.throws(${fileName}(args..), 'Expected');`,
`t.end();`,
`});`
].join('\n')
fs.writeFileSync(`${TEST_PATH}/${fileName}/${fileName}.js`, exportFile);
fs.writeFileSync(`${TEST_PATH}/${fileName}/${fileName}.test.js`, exportTest);
return fileName;
})

50
scripts/tdd.js Normal file
View File

@ -0,0 +1,50 @@
const fs = require('fs-extra');
const SNIPPETS_PATH = './snippets';
const TEST_PATH = './test';
const snippetFiles = fs.readdirSync(SNIPPETS_PATH, 'utf8').map(fileName => fileName.slice(0, -3));
fs.removeSync(TEST_PATH);
snippetFiles
.map(fileName => {
fs.ensureDirSync(`${TEST_PATH}/${fileName}`);
return fileName;
})
.map(fileName => {
const fileData = fs.readFileSync(`${SNIPPETS_PATH}/${fileName}.md`, 'utf8');
const fileCode = fileData.slice(fileData.indexOf('```js'), fileData.lastIndexOf('```') + 3);
const blockMarkers = fileCode
.split('\n')
.map((line, lineIndex) => (line.slice(0, 3) === '```' ? lineIndex : '//CLEAR//'))
.filter(x => !(x === '//CLEAR//'));
const fileFunction = fileCode
.split('\n')
.map(line => line.trim())
.filter((_, i) => blockMarkers[0] < i && i < blockMarkers[1]);
const fileExample = fileCode
.split('\n')
.map(line => line.trim())
.filter((_, i) => blockMarkers[2] < i && i < blockMarkers[3]);
const exportFile = `module.exports = ${fileFunction.join('\n').slice(17)}`;
const exportTest = [
`const test = require('tape');`,
`const ${fileName} = require('./${fileName}.js');`,
`test('Testing ${fileName}', (t) => {`,
`//For more information on all the methods supported by tape\n//Please go to https://github.com/substack/tape`,
`//t.deepEqual(${fileName}(args..), 'Expected');`,
`//t.equal(${fileName}(args..), 'Expected');`,
`//t.false(${fileName}(args..), 'Expected');`,
`//t.true(${fileName}(args..), 'Expected');`,
`//t.throws(${fileName}(args..), 'Expected');`,
`t.end();`,
`});`
].join('\n');
fs.writeFileSync(`${TEST_PATH}/${fileName}/${fileName}.js`, exportFile);
fs.writeFileSync(`${TEST_PATH}/${fileName}/${fileName}.test.js`, exportTest);
return fileName;
});

View File

@ -1,133 +0,0 @@
/*
This is the web builder script that generates the README file.
Run using `npm run webber`.
*/
// Load modules
const fs = require('fs-extra'), path = require('path'), chalk = require('chalk'),
md = require('markdown-it')(), minify = require('html-minifier').minify;
// Compile the mini.css framework and custom CSS styles, using `node-sass`.
const sass = require('node-sass');
sass.render({
file: path.join('docs','mini','flavor.scss'),
outFile: path.join('docs','mini.css'),
outputStyle: 'compressed'
}, function(err, result) {
if(!err){
fs.writeFile(path.join('docs','mini.css'), result.css, function(err2){
if(!err2) console.log(`${chalk.green('SUCCESS!')} mini.css file generated!`);
else console.log(`${chalk.red('ERROR!')} During mini.css file generation: ${err}`);
});
}
else {
console.log(`${chalk.red('ERROR!')} During mini.css file generation: ${err}`);
}
});
// Set variables for paths
const snippetsPath = './snippets', staticPartsPath = './static-parts', docsPath = './docs';
// Set variables for script
let snippets = {}, startPart = '', endPart = '', output = '', tagDbData = {};
// Load helper functions (these are from existing snippets in 30 seconds of code!)
const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {});
const capitalize = (str, lowerRest = false) => str.slice(0, 1).toUpperCase() + (lowerRest ? str.slice(1).toLowerCase() : str.slice(1));
// Start the timer of the script
console.time('Builder');
// Synchronously read all snippets and sort them as necessary (case-insensitive)
try {
let snippetFilenames = fs.readdirSync(snippetsPath);
snippetFilenames.sort((a, b) => {
a = a.toLowerCase();
b = b.toLowerCase();
if (a < b) return -1;
if (a > b) return 1;
return 0;
});
// Store the data read from each snippet in the appropriate object
for(let snippet of snippetFilenames) snippets[snippet] = fs.readFileSync(path.join(snippetsPath,snippet),'utf8');
}
catch (err){ // Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During snippet loading: ${err}`);
process.exit(1);
}
// Load static parts for the index.html file
try {
startPart = fs.readFileSync(path.join(staticPartsPath,'index-start.html'),'utf8');
endPart = fs.readFileSync(path.join(staticPartsPath,'index-end.html'),'utf8');
}
catch (err){ // Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During static part loading: ${err}`);
process.exit(1);
}
// Load tag data from the database
try {
tagDbData = objectFromPairs(fs.readFileSync('tag_database','utf8').split('\n').slice(0,-1).map(v => v.split(':').slice(0,2)));
}
catch (err){ // Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During tag database loading: ${err}`);
process.exit(1);
}
// Create the output for the index.html file
try {
// Add the start static part
output += `${startPart+'\n'}`;
let uncategorizedOutput = '';
// Loop over tags and snippets to create the table of contents
for(let tag of [...new Set(Object.entries(tagDbData).map(t => t[1]))].filter(v => v).sort((a,b) => a.localeCompare(b))){
if(capitalize(tag, true)=='Uncategorized') {
uncategorizedOutput +=`<h3>`+md.render(`${capitalize(tag, true)}\n`).replace(/<p>/g,'').replace(/<\/p>/g,'')+`</h3>`;
for(let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag))
uncategorizedOutput += md.render(`[${taggedSnippet[0]}](#${taggedSnippet[0].toLowerCase()})\n`).replace(/<p>/g,'').replace(/<\/p>/g,'').replace(/<a/g,'<a class="sublink-1"');
uncategorizedOutput += '\n';
} else {
output +=`<h3>`+md.render(`${capitalize(tag, true)}\n`).replace(/<p>/g,'').replace(/<\/p>/g,'')+`</h3>`;
for(let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag))
output += md.render(`[${taggedSnippet[0]}](#${taggedSnippet[0].toLowerCase()})\n`).replace(/<p>/g,'').replace(/<\/p>/g,'').replace(/<a/g,'<a class="sublink-1"');
output += '\n';
}
}
output += uncategorizedOutput;
output += `</nav><main class="col-sm-12 col-md-8 col-lg-9" style="height: 100%;overflow-y: auto; background: #eceef2; padding: 0;">`;
output += `<a id="top">&nbsp;</a>`;
uncategorizedOutput = '';
// Loop over tags and snippets to create the list of snippets
for(let tag of [...new Set(Object.entries(tagDbData).map(t => t[1]))].filter(v => v).sort((a,b) => a.localeCompare(b))){
if(capitalize(tag, true)=='Uncategorized') {
uncategorizedOutput +=md.render(`## ${capitalize(tag, true)}\n`).replace(/<h2>/g,'<h2 style="text-align:center;">');
for(let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag))
uncategorizedOutput += '<div class="card fluid"><div class="section double-padded">' + md.render(`\n${snippets[taggedSnippet[0]+'.md']}`).replace(/<h3/g,`<h3 id="${taggedSnippet[0].toLowerCase()}"`).replace(/<\/h3>/g,'</h3></div><div class="section double-padded">') + '</div></div><br/>';
} else {
output +=md.render(`## ${capitalize(tag, true)}\n`).replace(/<h2>/g,'<h2 style="text-align:center;">');
for(let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag))
output += '<div class="card fluid"><div class="section double-padded">' + md.render(`\n${snippets[taggedSnippet[0]+'.md']}`).replace(/<h3/g,`<h3 id="${taggedSnippet[0].toLowerCase()}"`).replace(/<\/h3>/g,'</h3></div><div class="section double-padded">') + '</div></div><br/>';
}
}
output += uncategorizedOutput;
// Add the ending static part
output += `\n${endPart+'\n'}`;
// Minify output
output = minify(output, {
collapseBooleanAttributes: true,
collapseWhitespace: true,
decodeEntities: false,
minifyCSS: true,
minifyJS: true,
keepClosingSlash: true,
processConditionalComments: true,
removeAttributeQuotes: false,
removeComments: true,
removeEmptyAttributes: false,
removeOptionalTags: false,
removeScriptTypeAttributes: false,
removeStyleLinkTypeAttributes: false,
trimCustomFragments: true,
});
// 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 index.html generation: ${err}`);
process.exit(1);
}
// Log a success message
console.log(`${chalk.green('SUCCESS!')} index.html file generated!`);
// Log the time taken
console.timeEnd('Builder');

192
scripts/web.js Normal file
View File

@ -0,0 +1,192 @@
/*
This is the web builder script that generates the README file.
Run using `npm run webber`.
*/
// Load modules
const fs = require('fs-extra'),
path = require('path'),
chalk = require('chalk'),
md = require('markdown-it')(),
minify = require('html-minifier').minify;
// Compile the mini.css framework and custom CSS styles, using `node-sass`.
const sass = require('node-sass');
sass.render(
{
file: path.join('docs', 'mini', 'flavor.scss'),
outFile: path.join('docs', 'mini.css'),
outputStyle: 'compressed'
},
function(err, result) {
if (!err) {
fs.writeFile(path.join('docs', 'mini.css'), result.css, function(err2) {
if (!err2) console.log(`${chalk.green('SUCCESS!')} mini.css file generated!`);
else console.log(`${chalk.red('ERROR!')} During mini.css file generation: ${err}`);
});
} else {
console.log(`${chalk.red('ERROR!')} During mini.css file generation: ${err}`);
}
}
);
// Set variables for paths
const snippetsPath = './snippets',
staticPartsPath = './static-parts',
docsPath = './docs';
// Set variables for script
let snippets = {},
startPart = '',
endPart = '',
output = '',
tagDbData = {};
// Load helper functions (these are from existing snippets in 30 seconds of code!)
const objectFromPairs = arr => arr.reduce((a, v) => ((a[v[0]] = v[1]), a), {});
const capitalize = (str, lowerRest = false) =>
str.slice(0, 1).toUpperCase() + (lowerRest ? str.slice(1).toLowerCase() : str.slice(1));
// Start the timer of the script
console.time('Builder');
// Synchronously read all snippets and sort them as necessary (case-insensitive)
try {
let snippetFilenames = fs.readdirSync(snippetsPath);
snippetFilenames.sort((a, b) => {
a = a.toLowerCase();
b = b.toLowerCase();
if (a < b) return -1;
if (a > b) return 1;
return 0;
});
// Store the data read from each snippet in the appropriate object
for (let snippet of snippetFilenames)
snippets[snippet] = fs.readFileSync(path.join(snippetsPath, snippet), 'utf8');
} catch (err) {
// Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During snippet loading: ${err}`);
process.exit(1);
}
// Load static parts for the index.html file
try {
startPart = fs.readFileSync(path.join(staticPartsPath, 'index-start.html'), 'utf8');
endPart = fs.readFileSync(path.join(staticPartsPath, 'index-end.html'), 'utf8');
} catch (err) {
// Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During static part loading: ${err}`);
process.exit(1);
}
// Load tag data from the database
try {
tagDbData = objectFromPairs(
fs
.readFileSync('tag_database', 'utf8')
.split('\n')
.slice(0, -1)
.map(v => v.split(':').slice(0, 2))
);
} catch (err) {
// Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During tag database loading: ${err}`);
process.exit(1);
}
// Create the output for the index.html file
try {
// Add the start static part
output += `${startPart + '\n'}`;
let uncategorizedOutput = '';
// Loop over tags and snippets to create the table of contents
for (let tag of [...new Set(Object.entries(tagDbData).map(t => t[1]))]
.filter(v => v)
.sort((a, b) => a.localeCompare(b))) {
if (capitalize(tag, true) == 'Uncategorized') {
uncategorizedOutput +=
`<h3>` +
md
.render(`${capitalize(tag, true)}\n`)
.replace(/<p>/g, '')
.replace(/<\/p>/g, '') +
`</h3>`;
for (let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag))
uncategorizedOutput += md
.render(`[${taggedSnippet[0]}](#${taggedSnippet[0].toLowerCase()})\n`)
.replace(/<p>/g, '')
.replace(/<\/p>/g, '')
.replace(/<a/g, '<a class="sublink-1"');
uncategorizedOutput += '\n';
} else {
output +=
`<h3>` +
md
.render(`${capitalize(tag, true)}\n`)
.replace(/<p>/g, '')
.replace(/<\/p>/g, '') +
`</h3>`;
for (let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag))
output += md
.render(`[${taggedSnippet[0]}](#${taggedSnippet[0].toLowerCase()})\n`)
.replace(/<p>/g, '')
.replace(/<\/p>/g, '')
.replace(/<a/g, '<a class="sublink-1"');
output += '\n';
}
}
output += uncategorizedOutput;
output += `</nav><main class="col-sm-12 col-md-8 col-lg-9" style="height: 100%;overflow-y: auto; background: #eceef2; padding: 0;">`;
output += `<a id="top">&nbsp;</a>`;
uncategorizedOutput = '';
// Loop over tags and snippets to create the list of snippets
for (let tag of [...new Set(Object.entries(tagDbData).map(t => t[1]))]
.filter(v => v)
.sort((a, b) => a.localeCompare(b))) {
if (capitalize(tag, true) == 'Uncategorized') {
uncategorizedOutput += md
.render(`## ${capitalize(tag, true)}\n`)
.replace(/<h2>/g, '<h2 style="text-align:center;">');
for (let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag))
uncategorizedOutput +=
'<div class="card fluid"><div class="section double-padded">' +
md
.render(`\n${snippets[taggedSnippet[0] + '.md']}`)
.replace(/<h3/g, `<h3 id="${taggedSnippet[0].toLowerCase()}"`)
.replace(/<\/h3>/g, '</h3></div><div class="section double-padded">') +
'</div></div><br/>';
} else {
output += md
.render(`## ${capitalize(tag, true)}\n`)
.replace(/<h2>/g, '<h2 style="text-align:center;">');
for (let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag))
output +=
'<div class="card fluid"><div class="section double-padded">' +
md
.render(`\n${snippets[taggedSnippet[0] + '.md']}`)
.replace(/<h3/g, `<h3 id="${taggedSnippet[0].toLowerCase()}"`)
.replace(/<\/h3>/g, '</h3></div><div class="section double-padded">') +
'</div></div><br/>';
}
}
output += uncategorizedOutput;
// Add the ending static part
output += `\n${endPart + '\n'}`;
// Minify output
output = minify(output, {
collapseBooleanAttributes: true,
collapseWhitespace: true,
decodeEntities: false,
minifyCSS: true,
minifyJS: true,
keepClosingSlash: true,
processConditionalComments: true,
removeAttributeQuotes: false,
removeComments: true,
removeEmptyAttributes: false,
removeOptionalTags: false,
removeScriptTypeAttributes: false,
removeStyleLinkTypeAttributes: false,
trimCustomFragments: true
});
// 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 index.html generation: ${err}`);
process.exit(1);
}
// Log a success message
console.log(`${chalk.green('SUCCESS!')} index.html file generated!`);
// Log the time taken
console.timeEnd('Builder');