mirror of
https://github.com/dilllxd/gitfolio.git
synced 2024-08-14 22:28:09 +00:00
Cli feature (#29)
* Move all cli options to single bin file, export fns from each file instead * Make username/title required in cli itself * fix username not being parsed, set desc separately * read outDir from env var, defaults to dist * set outDir env var in cli to cwd * Move default configs to default dir * handle blog.json not existing * fix assets path * make build function async * update clean command * added defaults to CLI
This commit is contained in:
parent
2ec61a9132
commit
e62e4c05b3
10 changed files with 169 additions and 99 deletions
|
@ -50,6 +50,7 @@
|
||||||
},800);
|
},800);
|
||||||
},1500);
|
},1500);
|
||||||
$.getJSON("blog.json", function(blog){
|
$.getJSON("blog.json", function(blog){
|
||||||
|
blog = blog || [];
|
||||||
if(blog.length == 0){
|
if(blog.length == 0){
|
||||||
return document.getElementById("blog_section").style.display = "none";
|
return document.getElementById("blog_section").style.display = "none";
|
||||||
}
|
}
|
||||||
|
@ -68,6 +69,8 @@
|
||||||
</a>
|
</a>
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
}).fail(function(){
|
||||||
|
return document.getElementById("blog_section").style.display = "none";
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
44
bin/gitfolio.js
Normal file
44
bin/gitfolio.js
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#! /usr/bin/env node
|
||||||
|
/* Argument parser */
|
||||||
|
const program = require('commander');
|
||||||
|
|
||||||
|
process.env.OUT_DIR = process.env.OUT_DIR || process.cwd();
|
||||||
|
|
||||||
|
const {buildCommand} = require('../build');
|
||||||
|
const {updateCommand} = require('../update');
|
||||||
|
const {blogCommand} = require('../blog');
|
||||||
|
const {version} = require('../package.json');
|
||||||
|
|
||||||
|
program
|
||||||
|
.command('build <username>')
|
||||||
|
.description('Build site with your GitHub username. This will be used to customize your site')
|
||||||
|
.option('-t, --theme [theme]', 'specify a theme to use', 'light')
|
||||||
|
.option('-b, --background [background]', 'set the background image')
|
||||||
|
.option('-f, --fork', 'includes forks with repos')
|
||||||
|
.option('-s, --sort [sort]', 'set default sort for repository', 'created')
|
||||||
|
.option('-o, --order [order]', 'set default order on sort', 'asc')
|
||||||
|
.action(buildCommand)
|
||||||
|
|
||||||
|
program
|
||||||
|
.command('update')
|
||||||
|
.action(updateCommand);
|
||||||
|
|
||||||
|
program
|
||||||
|
.command('blog <title>')
|
||||||
|
.description('Create blog with specified title')
|
||||||
|
.option('-s, --subtitle [subtitle]', 'give blog a subtitle', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.')
|
||||||
|
.option('-p, --pagetitle [pagetitle]', 'give blog page a title')
|
||||||
|
.option('-f, --folder [folder]', 'give folder a title (use "-" instead of spaces)')
|
||||||
|
.action(blogCommand);
|
||||||
|
|
||||||
|
program.on('command:*', () => {
|
||||||
|
console.log('Unknown Command: ' + program.args.join(' '))
|
||||||
|
program.help()
|
||||||
|
});
|
||||||
|
|
||||||
|
program
|
||||||
|
.version(version, '-v --version')
|
||||||
|
.usage('<command> [options]')
|
||||||
|
.parse(process.argv);
|
||||||
|
|
||||||
|
if (program.args.length === 0) program.help();
|
51
blog.js
51
blog.js
|
@ -1,31 +1,23 @@
|
||||||
const program = require('commander');
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const jsdom = require('jsdom').JSDOM,
|
const jsdom = require('jsdom').JSDOM,
|
||||||
options = {
|
options = {
|
||||||
resources: "usable"
|
resources: "usable"
|
||||||
};
|
};
|
||||||
|
const {getBlog, outDir} = require('./utils');
|
||||||
program
|
|
||||||
.version('0.1.2')
|
|
||||||
.option('-t, --title [title]', 'give blog a title')
|
|
||||||
.option('-s, --subtitle [subtitle]', 'give blog a subtitle', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.')
|
|
||||||
.option('-p, --pagetitle [pagetitle]', 'give blog page a title')
|
|
||||||
.option('-f, --folder [folder]', 'give folder a title (use "-" instead of spaces)')
|
|
||||||
.parse(process.argv);
|
|
||||||
|
|
||||||
function createBlog(title, subtitle, pagetitle, folder) {
|
function createBlog(title, subtitle, pagetitle, folder) {
|
||||||
// Checks to make sure this directory actually exists
|
// Checks to make sure this directory actually exists
|
||||||
// and creates it if it doesn't
|
// and creates it if it doesn't
|
||||||
if (!fs.existsSync(`./dist/blog/`)){
|
if (!fs.existsSync(`${outDir}/blog/`)){
|
||||||
fs.mkdirSync(`./dist/blog/`, { recursive: true }, err => {});
|
fs.mkdirSync(`${outDir}/blog/`, { recursive: true }, err => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fs.existsSync(`./dist/blog/${folder}`)){
|
if (!fs.existsSync(`${outDir}/blog/${folder}`)){
|
||||||
fs.mkdirSync(`./dist/blog/${folder}`, { recursive: true });
|
fs.mkdirSync(`${outDir}/blog/${folder}`, { recursive: true });
|
||||||
}
|
}
|
||||||
fs.copyFile('./assets/blog/blogTemplate.html', `./dist/blog/${folder}/index.html`, (err) => {
|
fs.copyFile(`${__dirname}/assets/blog/blogTemplate.html`, `${outDir}/blog/${folder}/index.html`, (err) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
jsdom.fromFile(`./dist/blog/${folder}/index.html`, options).then(function (dom) {
|
jsdom.fromFile(`${outDir}/blog/${folder}/index.html`, options).then(function (dom) {
|
||||||
let window = dom.window, document = window.document;
|
let window = dom.window, document = window.document;
|
||||||
var style = document.createElement("link");
|
var style = document.createElement("link");
|
||||||
style.setAttribute("rel","stylesheet")
|
style.setAttribute("rel","stylesheet")
|
||||||
|
@ -36,7 +28,7 @@ function createBlog(title, subtitle, pagetitle, folder) {
|
||||||
document.getElementById("blog_title").textContent = title;
|
document.getElementById("blog_title").textContent = title;
|
||||||
document.getElementById("blog_sub_title").textContent = subtitle;
|
document.getElementById("blog_sub_title").textContent = subtitle;
|
||||||
|
|
||||||
fs.writeFile(`./dist/blog/${folder}/index.html`, '<!DOCTYPE html>'+window.document.documentElement.outerHTML, function (error){
|
fs.writeFile(`${outDir}/blog/${folder}/index.html`, '<!DOCTYPE html>'+window.document.documentElement.outerHTML, async function (error){
|
||||||
if (error) throw error;
|
if (error) throw error;
|
||||||
var blog_data = {
|
var blog_data = {
|
||||||
"url_title": pagetitle,
|
"url_title": pagetitle,
|
||||||
|
@ -44,14 +36,11 @@ function createBlog(title, subtitle, pagetitle, folder) {
|
||||||
"sub_title": subtitle,
|
"sub_title": subtitle,
|
||||||
"top_image": "https://images.unsplash.com/photo-1553748024-d1b27fb3f960?w=1450",
|
"top_image": "https://images.unsplash.com/photo-1553748024-d1b27fb3f960?w=1450",
|
||||||
"visible": true }
|
"visible": true }
|
||||||
fs.readFile("./dist/blog.json", function (err , data) {
|
const old_blogs = await getBlog();
|
||||||
|
old_blogs.push(blog_data);
|
||||||
|
fs.writeFile(`${outDir}/blog.json`, JSON.stringify(old_blogs, null, ' '), function(err){
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
var old_blogs = JSON.parse(data);
|
console.log('Blog Created Successfully in "blog" folder.');
|
||||||
old_blogs.push(blog_data);
|
|
||||||
fs.writeFile('./dist/blog.json', JSON.stringify(old_blogs, null, ' '), function(err){
|
|
||||||
if (err) throw err;
|
|
||||||
console.log('Blog Created Successfully in "blog" folder.');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}).catch(function(error){
|
}).catch(function(error){
|
||||||
|
@ -60,18 +49,20 @@ function createBlog(title, subtitle, pagetitle, folder) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (program.title) {
|
function blogCommand(title, program) {
|
||||||
/* Check if build has been executed before blog this will prevent it from giving "link : index.css" error */
|
/* Check if build has been executed before blog this will prevent it from giving "link : index.css" error */
|
||||||
if (!fs.existsSync(`./dist/index.html`) || !fs.existsSync(`./dist/index.css`)){
|
if (!fs.existsSync(`${outDir}/index.html`) || !fs.existsSync(`${outDir}/index.css`)){
|
||||||
return console.log("You need to run build command before using blog one");
|
return console.log("You need to run build command before using blog one");
|
||||||
}
|
}
|
||||||
if (!program.pagetitle) {
|
if (!program.pagetitle) {
|
||||||
program.pagetitle = program.title;
|
program.pagetitle = title;
|
||||||
}
|
}
|
||||||
if (!program.folder) {
|
if (!program.folder) {
|
||||||
program.folder = program.title;
|
program.folder = title;
|
||||||
}
|
}
|
||||||
createBlog(program.title, program.subtitle, program.pagetitle, program.folder);
|
createBlog(title, program.subtitle, program.pagetitle, program.folder);
|
||||||
} else {
|
|
||||||
console.log("Provide a title to create a new blog");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
blogCommand,
|
||||||
|
};
|
||||||
|
|
53
build.js
53
build.js
|
@ -1,5 +1,3 @@
|
||||||
/* Argument parser */
|
|
||||||
const program = require('commander');
|
|
||||||
/* Filepath utilities */
|
/* Filepath utilities */
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
/* Promise library */
|
/* Promise library */
|
||||||
|
@ -9,22 +7,10 @@ const hbs = require('handlebars');
|
||||||
from callback-passed async functions */
|
from callback-passed async functions */
|
||||||
const fs = bluebird.promisifyAll(require('fs'));
|
const fs = bluebird.promisifyAll(require('fs'));
|
||||||
const { updateHTML } = require('./populate');
|
const { updateHTML } = require('./populate');
|
||||||
|
const { getConfig, outDir } = require('./utils');
|
||||||
|
|
||||||
|
const assetDir = path.resolve(`${__dirname}/assets/`);
|
||||||
/* Specify the options the program uses */
|
const config = path.join(outDir, 'config.json');
|
||||||
program
|
|
||||||
.version('0.1.2')
|
|
||||||
.option('-n, --name [username]', 'your GitHub username. This will be used to customize your site')
|
|
||||||
.option('-t, --theme [theme]', 'specify a theme to use')
|
|
||||||
.option('-b, --background [background]', 'set the background image')
|
|
||||||
.option('-f, --fork', 'includes forks with repos')
|
|
||||||
.option('-s, --sort [sort]', 'set default sort for repository')
|
|
||||||
.option('-o, --order [order]', 'set default order on sort')
|
|
||||||
.parse(process.argv);
|
|
||||||
|
|
||||||
const config = './dist/config.json';
|
|
||||||
const assetDir = path.resolve('./assets/');
|
|
||||||
const outDir = path.resolve('./dist/');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the stylesheet used by the site from a template stylesheet.
|
* Creates the stylesheet used by the site from a template stylesheet.
|
||||||
|
@ -32,9 +18,12 @@ const outDir = path.resolve('./dist/');
|
||||||
* Theme styles are added to the new stylesheet depending on command line
|
* Theme styles are added to the new stylesheet depending on command line
|
||||||
* arguments.
|
* arguments.
|
||||||
*/
|
*/
|
||||||
async function populateCSS() {
|
async function populateCSS({
|
||||||
|
theme = 'light',
|
||||||
|
background = 'https://images.unsplash.com/photo-1553748024-d1b27fb3f960?w=1450',
|
||||||
|
} = {}) {
|
||||||
/* Get the theme the user requests. Defaults to 'light' */
|
/* Get the theme the user requests. Defaults to 'light' */
|
||||||
let theme = `${program.theme || 'light'}.css`; /* Site theme, defaults to 'light' */
|
theme = `${theme}.css`;
|
||||||
let template = path.resolve(assetDir, 'index.css');
|
let template = path.resolve(assetDir, 'index.css');
|
||||||
let stylesheet = path.join(outDir, 'index.css');
|
let stylesheet = path.join(outDir, 'index.css');
|
||||||
|
|
||||||
|
@ -58,41 +47,41 @@ async function populateCSS() {
|
||||||
themeSource = themeSource.toString('utf-8');
|
themeSource = themeSource.toString('utf-8');
|
||||||
let themeTemplate = hbs.compile(themeSource);
|
let themeTemplate = hbs.compile(themeSource);
|
||||||
let styles = themeTemplate({
|
let styles = themeTemplate({
|
||||||
'background': `${program.background || 'https://images.unsplash.com/photo-1553748024-d1b27fb3f960?w=1450'}`
|
'background': `${background}`
|
||||||
})
|
})
|
||||||
/* Add the user-specified styles to the new stylesheet */
|
/* Add the user-specified styles to the new stylesheet */
|
||||||
await fs.appendFileAsync(stylesheet, styles);
|
await fs.appendFileAsync(stylesheet, styles);
|
||||||
|
|
||||||
/* Update the config file with the user's theme choice */
|
/* Update the config file with the user's theme choice */
|
||||||
let data = await fs.readFileAsync(config);
|
const data = await getConfig();
|
||||||
data = JSON.parse(data);
|
|
||||||
data[0].theme = theme;
|
data[0].theme = theme;
|
||||||
await fs.writeFileAsync(config, JSON.stringify(data, null, ' '));
|
await fs.writeFileAsync(config, JSON.stringify(data, null, ' '));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function populateConfig(sort, order, includeFork) {
|
async function populateConfig(sort, order, includeFork) {
|
||||||
let data = await fs.readFileAsync(config);
|
const data = await getConfig();
|
||||||
data = JSON.parse(data);
|
|
||||||
data[0].sort = sort;
|
data[0].sort = sort;
|
||||||
data[0].order = order;
|
data[0].order = order;
|
||||||
data[0].includeFork = includeFork;
|
data[0].includeFork = includeFork;
|
||||||
await fs.writeFileAsync(config, JSON.stringify(data, null, ' '));
|
await fs.writeFileAsync(config, JSON.stringify(data, null, ' '));
|
||||||
}
|
}
|
||||||
|
|
||||||
populateCSS();
|
async function buildCommand(username, program) {
|
||||||
|
await populateCSS(program);
|
||||||
|
|
||||||
if (typeof program.name === 'string' && program.name.trim() !== '') {
|
|
||||||
let sort = program.sort ? program.sort : 'created';
|
let sort = program.sort ? program.sort : 'created';
|
||||||
let order = "asc";
|
let order = "asc";
|
||||||
let includeFork = false;
|
let includeFork = false;
|
||||||
if(program.order){
|
if(program.order){
|
||||||
order = ('%s', program.order);
|
order = ('%s', program.order);
|
||||||
}
|
}
|
||||||
if(program.fork){
|
if(program.fork){
|
||||||
includeFork = true;
|
includeFork = true;
|
||||||
}
|
}
|
||||||
populateConfig(sort, order, includeFork);
|
await populateConfig(sort, order, includeFork);
|
||||||
updateHTML(('%s', program.name), sort, order, includeFork);
|
updateHTML(('%s', username), sort, order, includeFork);
|
||||||
} else {
|
|
||||||
console.error("Error: Please provide a GitHub username.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
buildCommand,
|
||||||
|
};
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"description": "portfolio website for showcasing your work",
|
"description": "portfolio website for showcasing your work",
|
||||||
"main": "build.js",
|
"main": "build.js",
|
||||||
|
"bin": "bin/gitfolio.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rm -f dist/index.*",
|
"cli": "OUT_DIR='./dist' node bin/gitfolio.js",
|
||||||
|
"clean": "rm -rf ./dist/*",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"author": "imfunny",
|
"author": "imfunny",
|
||||||
|
|
20
populate.js
20
populate.js
|
@ -5,6 +5,7 @@ const jsdom = require('jsdom').JSDOM,
|
||||||
options = {
|
options = {
|
||||||
resources: "usable"
|
resources: "usable"
|
||||||
};
|
};
|
||||||
|
const { getConfig, outDir } = require('./utils');
|
||||||
|
|
||||||
function convertToEmoji(text) {
|
function convertToEmoji(text) {
|
||||||
if (text == null) return;
|
if (text == null) return;
|
||||||
|
@ -29,7 +30,7 @@ function convertToEmoji(text) {
|
||||||
|
|
||||||
module.exports.updateHTML = (username, sort, order, includeFork) => {
|
module.exports.updateHTML = (username, sort, order, includeFork) => {
|
||||||
//add data to assets/index.html
|
//add data to assets/index.html
|
||||||
jsdom.fromFile("./assets/index.html", options).then(function (dom) {
|
jsdom.fromFile(`${__dirname}/assets/index.html`, options).then(function (dom) {
|
||||||
let window = dom.window, document = window.document;
|
let window = dom.window, document = window.document;
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
|
@ -115,18 +116,15 @@ module.exports.updateHTML = (username, sort, order, includeFork) => {
|
||||||
<span style="display:${user.location == null || !user.location ? 'none' : 'block'};"><i class="fas fa-map-marker-alt"></i> ${user.location}</span>
|
<span style="display:${user.location == null || !user.location ? 'none' : 'block'};"><i class="fas fa-map-marker-alt"></i> ${user.location}</span>
|
||||||
<span style="display:${user.hireable == false || !user.hireable ? 'none' : 'block'};"><i class="fas fa-user-tie"></i> Available for hire</span>`;
|
<span style="display:${user.hireable == false || !user.hireable ? 'none' : 'block'};"><i class="fas fa-user-tie"></i> Available for hire</span>`;
|
||||||
//add data to config.json
|
//add data to config.json
|
||||||
fs.readFile("./dist/config.json", function (err, data) {
|
const data = await getConfig();
|
||||||
|
data[0].username = user.login;
|
||||||
|
data[0].name = user.name;
|
||||||
|
data[0].userimg = user.avatar_url;
|
||||||
|
fs.writeFile(`${outDir}/config.json`, JSON.stringify(data, null, ' '), function (err) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
data = JSON.parse(data);
|
console.log("Config file updated.");
|
||||||
data[0].username = user.login;
|
|
||||||
data[0].name = user.name;
|
|
||||||
data[0].userimg = user.avatar_url;
|
|
||||||
fs.writeFile('./dist/config.json', JSON.stringify(data, null, ' '), function (err) {
|
|
||||||
if (err) throw err;
|
|
||||||
console.log("Config file updated.");
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
fs.writeFile('dist/index.html', '<!DOCTYPE html>' + window.document.documentElement.outerHTML, function (error) {
|
fs.writeFile(`${outDir}/index.html`, '<!DOCTYPE html>' + window.document.documentElement.outerHTML, function (error) {
|
||||||
if (error) throw error;
|
if (error) throw error;
|
||||||
console.log("Build Complete");
|
console.log("Build Complete");
|
||||||
});
|
});
|
||||||
|
|
12
update.js
12
update.js
|
@ -1,9 +1,9 @@
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const {getConfig, outDir} = require('./utils');
|
||||||
const {updateHTML} = require('./populate');
|
const {updateHTML} = require('./populate');
|
||||||
|
|
||||||
fs.readFile("./dist/config.json", function (err , data) {
|
async function updateCommand() {
|
||||||
if (err) throw err;
|
const data = await getConfig();
|
||||||
data = JSON.parse(data);
|
|
||||||
var username = data[0].username;
|
var username = data[0].username;
|
||||||
var sort = data[0].sort;
|
var sort = data[0].sort;
|
||||||
var order = data[0].order;
|
var order = data[0].order;
|
||||||
|
@ -13,4 +13,8 @@ fs.readFile("./dist/config.json", function (err , data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
updateHTML(username, sort, order, includeFork);
|
updateHTML(username, sort, order, includeFork);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
updateCommand,
|
||||||
|
};
|
||||||
|
|
39
utils.js
Normal file
39
utils.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
const path = require('path');
|
||||||
|
const bluebird = require('bluebird');
|
||||||
|
const fs = bluebird.promisifyAll(require('fs'));
|
||||||
|
|
||||||
|
const outDir = path.resolve(process.env.OUT_DIR || './dist/');
|
||||||
|
const configPath = path.join(outDir, 'config.json');
|
||||||
|
const blogPath = path.join(outDir, 'blog.json');
|
||||||
|
|
||||||
|
const defaultConfigPath = path.resolve(`${__dirname}/default/config.json`);
|
||||||
|
const defaultBlogPath = path.resolve(`${__dirname}/default/blog.json`);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to read file from out dir,
|
||||||
|
* if not present returns default file contents
|
||||||
|
*/
|
||||||
|
async function getFileWithDefaults(file, defaultFile) {
|
||||||
|
try {
|
||||||
|
await fs.accessAsync(file, fs.constants.F_OK);
|
||||||
|
} catch (err) {
|
||||||
|
const defaultData = await fs.readFileAsync(defaultFile);
|
||||||
|
return JSON.parse(defaultData);
|
||||||
|
}
|
||||||
|
const data = await fs.readFileAsync(file);
|
||||||
|
return JSON.parse(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getConfig() {
|
||||||
|
return getFileWithDefaults(configPath, defaultConfigPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getBlog() {
|
||||||
|
return getFileWithDefaults(blogPath, defaultBlogPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
outDir,
|
||||||
|
getConfig,
|
||||||
|
getBlog,
|
||||||
|
};
|
Loading…
Reference in a new issue