diff --git a/README.md b/README.md index 3cfe416..00de919 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ CLI to initialize and configure a [Blowfish](https://blowfish.page) project. Ins - Configure an existing Hugo project to use Blowfish - Run a local server with Blowfish - Generate the static site with Hugo +- Configure site's main information - title, description, etc +- Configure site's author - name, bio, links, etc ## Installation Install globally using: @@ -51,4 +53,6 @@ Commands: install Installs Blowfish on an existing Hugo project (assumes current directory). run Run a local server with Blowfish in the current directory. Requires Hugo to be installed and Blowfish configured in current directory. generate Generates site assets in public folder in the current directory. Requires Hugo to be installed and Blowfish configured in current directory. + configMeta Configure site's main information - title, description, etc + configAuthor Configure site's author - name, bio, links, etc ``` diff --git a/cli.js b/cli.js index 088e6b3..a440741 100755 --- a/cli.js +++ b/cli.js @@ -42,5 +42,17 @@ program.command('generate') flow.generateSite(true); }); +program.command('configMeta') + .description('Configure site\'s main information - title, description, etc') + .action((str, options) => { + flow.configureMeta(true); + }); + +program.command('configAuthor') + .description('Configure site\'s author - name, bio, links, etc') + .action((str, options) => { + flow.configureAuthor(true); + }); + program.parse(); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 4eeb233..2559c57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,20 @@ { "name": "blowfish-tools", - "version": "0.8.0", + "version": "0.8.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "blowfish-tools", - "version": "0.8.0", + "version": "0.8.3", "license": "MIT", "dependencies": { "chalk": "^5.3.0", "command-exists": "^1.2.9", "commander": "^11.1.0", "enquirer": "^2.4.1", - "ora": "^8.0.1" + "ora": "^8.0.1", + "toml-patch": "^0.2.3" }, "bin": { "blowfish-tools": "cli.js" @@ -311,6 +312,11 @@ "engines": { "node": ">=8" } + }, + "node_modules/toml-patch": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/toml-patch/-/toml-patch-0.2.3.tgz", + "integrity": "sha512-SQI/j7f2S/iQZmoWBWNUMTfVmPbhP3+YCqxB/q8iOjdnXBk29HDARHzjCazmwftZaylYuMSrTTrvJiESVyzJzw==" } } } diff --git a/package.json b/package.json index a6235d6..c88cde3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "blowfish-tools", - "version": "0.8.2", + "version": "0.8.3", "description": "CLI to initialize and configure a Blowfish project.", "main": "cli.js", "bin": { @@ -33,6 +33,7 @@ "command-exists": "^1.2.9", "commander": "^11.1.0", "enquirer": "^2.4.1", - "ora": "^8.0.1" + "ora": "^8.0.1", + "toml-patch": "^0.2.3" } } diff --git a/src/flow.js b/src/flow.js index 712c9ad..9e6f471 100644 --- a/src/flow.js +++ b/src/flow.js @@ -2,6 +2,8 @@ import ora from 'ora'; import pkg from 'enquirer'; const { prompt } = pkg; +import toml from 'toml-patch'; + import eyecandy from "./eyecandy.js"; import utils from './utils.js'; @@ -17,7 +19,7 @@ export default class flow { } } - static async showMain() { + static async showMain(message) { var blowfishIsInstalled = await flow.detectBlowfish(); @@ -26,12 +28,16 @@ export default class flow { var choices = []; for (var i in options) { - if (!options[i].hasOwnProperty('blowfishIsInstalled') ) + if (!options[i].hasOwnProperty('blowfishIsInstalled')) choices.push(options[i].text); else if (options[i].blowfishIsInstalled && blowfishIsInstalled) choices.push(options[i].text); else if (!options[i].blowfishIsInstalled && !blowfishIsInstalled) - choices.push(options[i].text); + choices.push(options[i].text); + } + + if (message) { + console.log(message); } const response = await prompt({ @@ -51,27 +57,6 @@ export default class flow { } } - static async showPost(message) { - console.log(message) - const response = await prompt({ - type: 'AutoComplete', - name: 'option', - message: 'Do you need help with anything else?', - limit: 10, - initial: 0, - choices: [ - 'Take me to the main menu', - 'Exit' - ] - }); - - if (response.option === 'Exit') { - eyecandy.showBye(); - } else if (response.option === 'Take me to the main menu') { - flow.showMain(); - } - } - static async configureNew(directory, exitAfterRun) { const spinner = ora('Checking for dependencies').start(); await flow.checkHugo(spinner); @@ -130,14 +115,14 @@ export default class flow { if (exitAfterRun) process.exit(0); else - flow.showPost('Blowfish configured in ' + response.directory + '. cd into it and run "hugo server" to start your website.', { dir: response.directory }); + flow.showMain('Blowfish configured in ' + response.directory + '. cd into it and run "hugo server" to start your website.', { dir: response.directory }); } static async configureExisting(exitAfterRun) { var blowfishIsInstalled = await flow.detectBlowfish(); - if(blowfishIsInstalled) { + if (blowfishIsInstalled) { console.log('Blowfish is already installed in this folder.'); process.exit(0); } @@ -162,7 +147,7 @@ export default class flow { if (exitAfterRun) process.exit(0); else - flow.showPost('Blowfish installed. Run "hugo server" to start your website.', { dir: response.directory }); + flow.showMain('Blowfish installed. Run "hugo server" to start your website.', { dir: response.directory }); } static async runServer() { @@ -212,6 +197,160 @@ export default class flow { }); } + static async configureMeta(exitAfterRun) { + var blowfishIsInstalled = await flow.detectBlowfish(); + if (!blowfishIsInstalled) { + console.log('Blowfish is not yet installed.'); + process.exit(0); + } + + const fileToConfigure = './config/_default/languages.en.toml'; + + if (!utils.fileExists(fileToConfigure)) { + console.log('File ' + fileToConfigure + ' does not exist.'); + process.exit(0); + } + + var data = toml.parse(utils.openFile(fileToConfigure).toString()); + + const response = await prompt([ + { + type: 'input', + name: 'title', + default: data.title ? data.title : 'a title', + message: 'What is the title of your site?' + }, + { + type: 'input', + name: 'description', + default: data.description ? data.description : 'a description', + message: 'What is the description of your site?' + }, + { + type: 'input', + name: 'logo', + default: data.params && data.params.logo ? data.params.logo : 'logo.png', + message: 'Do you have a logo for your website? - please place the file in the assets folder and type the filename here.' + } + ]); + + data.title = response.title; + if (!data.params) + data.params = {}; + + data.params.description = response.description; + data.params.logo = response.logo; + + utils.saveFileSync(fileToConfigure, toml.stringify(data)); + + if (exitAfterRun) + process.exit(0); + else + flow.showMain('Configurations applied. Run server to check changes.'); + } + + static async configureAuthor(exitAfterRun) { + + var blowfishIsInstalled = await flow.detectBlowfish(); + if (!blowfishIsInstalled) { + console.log('Blowfish is not yet installed.'); + process.exit(0); + } + + const fileToConfigure = './config/_default/languages.en.toml'; + + if (!utils.fileExists(fileToConfigure)) { + console.log('File ' + fileToConfigure + ' does not exist.'); + process.exit(0); + } + + var data = toml.parse(utils.openFile(fileToConfigure).toString()); + + const response = await prompt([ + { + type: 'input', + name: 'name', + default: data.author && data.author.name ? data.author.name : 'a name', + message: 'What is your name?' + }, + { + type: 'input', + name: 'image', + default: data.author && data.author.image ? data.author.image : 'profile.png', + message: 'Do you have a profile for your website? - please place the file in the assets folder and type the filename here.' + }, + { + type: 'input', + name: 'headline', + default: data.author && data.author.headline ? data.author.headline : 'a headline', + message: 'What is your headline - displayed below name in main page?' + }, + { + type: 'input', + name: 'bio', + default: data.author && data.author.bio ? data.author.bio : 'a bio', + message: 'What is your bio - displayed in author pages?' + }, + { + type: 'multiselect', + name: 'value', + message: 'Which links to you want to configure for your profile?\nSelect using spacebar and press enter when done.', + choices: [ + { name: 'email' }, + { name: 'link' }, + { name: 'bluesky' }, + { name: 'discord' }, + { name: 'github' }, + { name: 'instagram' }, + { name: 'keybase' }, + { name: 'linkedin' }, + { name: 'mastodon' }, + { name: 'medium' }, + { name: 'reddit' }, + { name: 'telegram' }, + { name: 'tiktok' }, + { name: 'twitter' }, + { name: 'x-twitter' }, + { name: 'whatsapp' }, + { name: 'youtube' } + ] + } + ]); + + + var linksQuestions = []; + for (var i in response.value) { + linksQuestions.push({ + type: 'input', + name: response.value[i], + message: 'What URL do you want to configure for ' + response.value[i] + '?' + }); + } + + const responseLinks = await prompt(linksQuestions); + + if (!data.author) + data.author = {}; + data.author.name = response.name; + data.author.image = response.image; + data.author.headline = response.headline; + data.author.bio = response.bio; + data.author.links = []; + + for (const [key, value] of Object.entries(responseLinks)) { + var obj = {} + obj[key] = value; + data.author.links.push(obj); + } + + utils.saveFileSync(fileToConfigure, toml.stringify(data)); + + if (exitAfterRun) + process.exit(0); + else + flow.showMain('Configurations applied. Run server to check changes.'); + } + } @@ -226,6 +365,16 @@ var options = [ blowfishIsInstalled: false, action: flow.configureExisting }, + { + text: 'Configure site\'s main information - title, description, etc', + blowfishIsInstalled: true, + action: flow.configureMeta + }, + { + text: 'Configure site\'s author - name, bio, links, etc', + blowfishIsInstalled: true, + action: flow.configureAuthor + }, { text: 'Run a local server with Blowfish', blowfishIsInstalled: true, diff --git a/src/utils.js b/src/utils.js index 072fc05..681069f 100644 --- a/src/utils.js +++ b/src/utils.js @@ -26,7 +26,6 @@ export default class utils { }); } - static detectCommand(cmd) { return new Promise((resolve, reject) => { commandExists(cmd, function (err, commandExists) { @@ -39,6 +38,14 @@ export default class utils { }); } + static fileExists(path) { + try { + return fs.existsSync(path); + } catch (err) { + return false; + } + } + static directoryExists(path) { try { return fs.existsSync(path); @@ -54,4 +61,21 @@ export default class utils { return false; } } + + static openFile(path) { + try { + return fs.readFileSync(path); + } catch (err) { + return false; + } + } + + static saveFileSync(path, data) { + try { + fs.writeFileSync(path, data); + // file written successfully + } catch (err) { + console.error(err); + } + } } \ No newline at end of file