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);
|
||||
},1500);
|
||||
$.getJSON("blog.json", function(blog){
|
||||
blog = blog || [];
|
||||
if(blog.length == 0){
|
||||
return document.getElementById("blog_section").style.display = "none";
|
||||
}
|
||||
|
@ -68,6 +69,8 @@
|
|||
</a>
|
||||
`);
|
||||
}
|
||||
}).fail(function(){
|
||||
return document.getElementById("blog_section").style.display = "none";
|
||||
});
|
||||
</script>
|
||||
</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 jsdom = require('jsdom').JSDOM,
|
||||
options = {
|
||||
resources: "usable"
|
||||
};
|
||||
|
||||
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);
|
||||
const {getBlog, outDir} = require('./utils');
|
||||
|
||||
function createBlog(title, subtitle, pagetitle, folder) {
|
||||
// Checks to make sure this directory actually exists
|
||||
// and creates it if it doesn't
|
||||
if (!fs.existsSync(`./dist/blog/`)){
|
||||
fs.mkdirSync(`./dist/blog/`, { recursive: true }, err => {});
|
||||
if (!fs.existsSync(`${outDir}/blog/`)){
|
||||
fs.mkdirSync(`${outDir}/blog/`, { recursive: true }, err => {});
|
||||
}
|
||||
|
||||
if (!fs.existsSync(`./dist/blog/${folder}`)){
|
||||
fs.mkdirSync(`./dist/blog/${folder}`, { recursive: true });
|
||||
if (!fs.existsSync(`${outDir}/blog/${folder}`)){
|
||||
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;
|
||||
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;
|
||||
var style = document.createElement("link");
|
||||
style.setAttribute("rel","stylesheet")
|
||||
|
@ -36,7 +28,7 @@ function createBlog(title, subtitle, pagetitle, folder) {
|
|||
document.getElementById("blog_title").textContent = title;
|
||||
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;
|
||||
var blog_data = {
|
||||
"url_title": pagetitle,
|
||||
|
@ -44,14 +36,11 @@ function createBlog(title, subtitle, pagetitle, folder) {
|
|||
"sub_title": subtitle,
|
||||
"top_image": "https://images.unsplash.com/photo-1553748024-d1b27fb3f960?w=1450",
|
||||
"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;
|
||||
var old_blogs = JSON.parse(data);
|
||||
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.');
|
||||
});
|
||||
console.log('Blog Created Successfully in "blog" folder.');
|
||||
});
|
||||
});
|
||||
}).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 */
|
||||
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");
|
||||
}
|
||||
if (!program.pagetitle) {
|
||||
program.pagetitle = program.title;
|
||||
program.pagetitle = title;
|
||||
}
|
||||
if (!program.folder) {
|
||||
program.folder = program.title;
|
||||
program.folder = title;
|
||||
}
|
||||
createBlog(program.title, program.subtitle, program.pagetitle, program.folder);
|
||||
} else {
|
||||
console.log("Provide a title to create a new blog");
|
||||
createBlog(title, program.subtitle, program.pagetitle, program.folder);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
blogCommand,
|
||||
};
|
||||
|
|
57
build.js
57
build.js
|
@ -1,5 +1,3 @@
|
|||
/* Argument parser */
|
||||
const program = require('commander');
|
||||
/* Filepath utilities */
|
||||
const path = require('path');
|
||||
/* Promise library */
|
||||
|
@ -9,22 +7,10 @@ const hbs = require('handlebars');
|
|||
from callback-passed async functions */
|
||||
const fs = bluebird.promisifyAll(require('fs'));
|
||||
const { updateHTML } = require('./populate');
|
||||
const { getConfig, outDir } = require('./utils');
|
||||
|
||||
|
||||
/* Specify the options the program uses */
|
||||
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/');
|
||||
const assetDir = path.resolve(`${__dirname}/assets/`);
|
||||
const config = path.join(outDir, 'config.json');
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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' */
|
||||
let theme = `${program.theme || 'light'}.css`; /* Site theme, defaults to 'light' */
|
||||
theme = `${theme}.css`;
|
||||
let template = path.resolve(assetDir, 'index.css');
|
||||
let stylesheet = path.join(outDir, 'index.css');
|
||||
|
||||
|
@ -58,41 +47,41 @@ async function populateCSS() {
|
|||
themeSource = themeSource.toString('utf-8');
|
||||
let themeTemplate = hbs.compile(themeSource);
|
||||
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 */
|
||||
await fs.appendFileAsync(stylesheet, styles);
|
||||
|
||||
/* Update the config file with the user's theme choice */
|
||||
let data = await fs.readFileAsync(config);
|
||||
data = JSON.parse(data);
|
||||
const data = await getConfig();
|
||||
data[0].theme = theme;
|
||||
await fs.writeFileAsync(config, JSON.stringify(data, null, ' '));
|
||||
}
|
||||
|
||||
async function populateConfig(sort, order, includeFork) {
|
||||
let data = await fs.readFileAsync(config);
|
||||
data = JSON.parse(data);
|
||||
const data = await getConfig();
|
||||
data[0].sort = sort;
|
||||
data[0].order = order;
|
||||
data[0].includeFork = includeFork;
|
||||
await fs.writeFileAsync(config, JSON.stringify(data, null, ' '));
|
||||
}
|
||||
|
||||
populateCSS();
|
||||
|
||||
if (typeof program.name === 'string' && program.name.trim() !== '') {
|
||||
async function buildCommand(username, program) {
|
||||
await populateCSS(program);
|
||||
|
||||
let sort = program.sort ? program.sort : 'created';
|
||||
let order = "asc";
|
||||
let includeFork = false;
|
||||
if(program.order){
|
||||
order = ('%s', program.order);
|
||||
if(program.order){
|
||||
order = ('%s', program.order);
|
||||
}
|
||||
if(program.fork){
|
||||
includeFork = true;
|
||||
}
|
||||
populateConfig(sort, order, includeFork);
|
||||
updateHTML(('%s', program.name), sort, order, includeFork);
|
||||
} else {
|
||||
console.error("Error: Please provide a GitHub username.");
|
||||
}
|
||||
await populateConfig(sort, order, includeFork);
|
||||
updateHTML(('%s', username), sort, order, includeFork);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
buildCommand,
|
||||
};
|
||||
|
|
42
package.json
42
package.json
|
@ -1,20 +1,22 @@
|
|||
{
|
||||
"name": "gitfolio",
|
||||
"version": "0.1.2",
|
||||
"description": "portfolio website for showcasing your work",
|
||||
"main": "build.js",
|
||||
"scripts": {
|
||||
"clean": "rm -f dist/index.*",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "imfunny",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"bluebird": "^3.5.4",
|
||||
"commander": "^2.20.0",
|
||||
"github-emoji": "^1.1.0",
|
||||
"got": "^9.6.0",
|
||||
"handlebars": "^4.1.2",
|
||||
"jsdom": "^15.1.0"
|
||||
}
|
||||
}
|
||||
{
|
||||
"name": "gitfolio",
|
||||
"version": "0.1.2",
|
||||
"description": "portfolio website for showcasing your work",
|
||||
"main": "build.js",
|
||||
"bin": "bin/gitfolio.js",
|
||||
"scripts": {
|
||||
"cli": "OUT_DIR='./dist' node bin/gitfolio.js",
|
||||
"clean": "rm -rf ./dist/*",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "imfunny",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"bluebird": "^3.5.4",
|
||||
"commander": "^2.20.0",
|
||||
"github-emoji": "^1.1.0",
|
||||
"got": "^9.6.0",
|
||||
"handlebars": "^4.1.2",
|
||||
"jsdom": "^15.1.0"
|
||||
}
|
||||
}
|
||||
|
|
20
populate.js
20
populate.js
|
@ -5,6 +5,7 @@ const jsdom = require('jsdom').JSDOM,
|
|||
options = {
|
||||
resources: "usable"
|
||||
};
|
||||
const { getConfig, outDir } = require('./utils');
|
||||
|
||||
function convertToEmoji(text) {
|
||||
if (text == null) return;
|
||||
|
@ -29,7 +30,7 @@ function convertToEmoji(text) {
|
|||
|
||||
module.exports.updateHTML = (username, sort, order, includeFork) => {
|
||||
//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;
|
||||
(async () => {
|
||||
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.hireable == false || !user.hireable ? 'none' : 'block'};"><i class="fas fa-user-tie"></i> Available for hire</span>`;
|
||||
//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;
|
||||
data = JSON.parse(data);
|
||||
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.");
|
||||
});
|
||||
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;
|
||||
console.log("Build Complete");
|
||||
});
|
||||
|
|
12
update.js
12
update.js
|
@ -1,9 +1,9 @@
|
|||
const fs = require('fs');
|
||||
const {getConfig, outDir} = require('./utils');
|
||||
const {updateHTML} = require('./populate');
|
||||
|
||||
fs.readFile("./dist/config.json", function (err , data) {
|
||||
if (err) throw err;
|
||||
data = JSON.parse(data);
|
||||
async function updateCommand() {
|
||||
const data = await getConfig();
|
||||
var username = data[0].username;
|
||||
var sort = data[0].sort;
|
||||
var order = data[0].order;
|
||||
|
@ -13,4 +13,8 @@ fs.readFile("./dist/config.json", function (err , data) {
|
|||
return;
|
||||
}
|
||||
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