ProductPromotion
Logo

0x3d.Site

is designed for aggregating information.

Enhancing Functionality – Adding Features and Flexibility

In this tutorial, we’ll transform our simple Markdown-to-HTML converter into a versatile and flexible CLI tool. By adding the ability to handle multiple tasks and options, we’re going to take this project from “nice and simple” to “powerful and practical.” We’ll also make sure it’s user-friendly, handles errors like a champ, and allows customization with configuration options.

Handling Command-Line Arguments

Okay, so our first CLI tool works, but right now it’s like a restaurant with only one item on the menu. Sure, it gets the job done, but it’s not very flexible. To make our tool more useful, we’re going to give users some options. Imagine if they could pass commands like --output, --help, or even run commands on multiple files at once! This will turn your one-trick pony into a versatile powerhouse.

But how do we go about handling these different inputs? Enter yargs and commander.js—two popular libraries that make it super easy to manage command-line arguments in Node.js. For this tutorial, let’s go with commander.js because it’s lightweight, powerful, and pretty straightforward.

Step 1: Install Commander.js

First, we need to install the commander package:

npm install commander

Commander.js will let us define different commands and options that users can pass when running our tool. Now, let’s dive into the code and integrate it into our project.

Step 2: Updating the Code to Handle Arguments

Open up your index.js file, and let’s add some basic commands.

#!/usr/bin/env node

const { program } = require('commander');
const fs = require('fs');
const path = require('path');

// Define our program commands
program
  .version('1.0.0')
  .description('Markdown to HTML converter CLI tool')
  .option('-o, --output <file>', 'Specify the output file')
  .option('-h, --help', 'Display help for the command')
  .parse(process.argv);

// Get the input file and output options
const inputFile = program.args[0];
const outputFile = program.output || 'output.html';

if (!inputFile) {
  console.error('Error: No input file provided');
  process.exit(1);
}

// Read the input file and process it
const markdownContent = fs.readFileSync(inputFile, 'utf-8');
const htmlContent = markdownToHtml(markdownContent);

// Write the HTML to the output file
fs.writeFileSync(outputFile, htmlContent);
console.log(`Converted ${inputFile} to ${outputFile}`);

// Function to convert Markdown to HTML
function markdownToHtml(markdown) {
  // Dummy function for now. We'll improve this later.
  return `<html><body>${markdown}</body></html>`;
}

Step 3: Breaking Down the Code

Let’s unpack what’s happening here.

  • program.version(): This command sets the version of your tool. It’s not required, but it’s a nice touch, and it’s good practice for CLI tools.
  • program.option(): We use this to define the options our tool accepts. In this case, we added an --output option that lets the user specify an output file. If no output file is provided, it defaults to output.html.
  • program.parse(): This processes the arguments passed when the tool is run.
  • program.args[0]: This grabs the first argument passed, which is the input file (the Markdown file that needs converting).
  • Error handling: We check if the input file was provided. If not, we throw an error message and exit the process.

At this stage, you can run your tool like this:

md2html input.md --output result.html

This will take input.md, convert it to HTML, and write the result to result.html. If you don’t specify --output, it’ll save the HTML to output.html by default.

Error Handling and Validation

Next up, let’s give our tool some “manners.” By that, I mean we need to handle errors and validate user inputs to make sure everything goes smoothly. A good CLI tool should not crash or leave users guessing what went wrong.

Step 1: Validating Input Files

What if the user passes a file that doesn’t exist? Or worse, what if they pass an invalid file type? We don’t want our tool to just give up silently. Instead, let’s check for common mistakes and provide clear feedback.

Add this block of code to your index.js to handle some basic validations:

// Check if the input file exists
if (!fs.existsSync(inputFile)) {
  console.error(`Error: File "${inputFile}" does not exist.`);
  process.exit(1);
}

// Check if the input file is a Markdown file
if (path.extname(inputFile) !== '.md') {
  console.error(`Error: "${inputFile}" is not a Markdown file.`);
  process.exit(1);
}

Now, if the user tries to run the tool with an invalid or non-existent file, they’ll get an error message instead of a mysterious crash.

Step 2: Adding Help Messages

Another way to make your tool user-friendly is by providing helpful messages when things go wrong—or better yet, when users ask for help. With commander.js, adding a help message is super simple.

Just update your program definition like this:

program
  .version('1.0.0')
  .description('Markdown to HTML converter CLI tool')
  .option('-o, --output <file>', 'Specify the output file')
  .on('--help', function () {
    console.log('');
    console.log('Example:');
    console.log('  $ md2html input.md --output result.html');
  })
  .parse(process.argv);

Now, when users run:

md2html --help

They’ll see a help message with examples on how to use the tool. Giving users clear instructions is key to making sure they don’t get frustrated.

Reading and Writing Files with Node.js

Now we’re going to get into the meat of this tool: reading the Markdown file and converting it to HTML. For that, we’ll use Node.js’s file system (fs) module, which lets us work with files right from the terminal.

Step 1: Reading the Markdown File

Let’s start by reading the user’s input file. The following line of code takes care of that:

const markdownContent = fs.readFileSync(inputFile, 'utf-8');
  • fs.readFileSync(): This reads the content of the file synchronously (blocking). We pass in the file path (inputFile) and specify the encoding (utf-8) so that we get the file content as a string.

Step 2: Writing the Output File

Once we’ve read the Markdown file, the next step is to convert it to HTML and save the result. Here’s how we do that:

fs.writeFileSync(outputFile, htmlContent);
console.log(`Converted ${inputFile} to ${outputFile}`);
  • fs.writeFileSync(): This writes the content of htmlContent to the file specified by outputFile.

Adding Configuration Options

Wouldn’t it be nice if users could save their settings and not have to pass the same arguments every time they run your tool? That’s where configuration files come in. We can give users the ability to specify default options (like the default output folder) in a config file.

Step 1: Creating a Config File

Let’s create a simple configuration file format using JSON. The config file will store things like the default output directory or file extension.

Create a new file called md2html.config.json in your project folder, and add this sample content:

{
  "outputDir": "./dist",
  "fileExtension": ".html"
}

Step 2: Reading the Config File

Now let’s update our tool to read from this config file. Add this code to your index.js:

let config = {
  outputDir: './',
  fileExtension: '.html'
};

if (fs.existsSync('md2html.config.json')) {
  const configFile = fs.readFileSync('md2html.config.json');
  config = JSON.parse(configFile);
}

const outputFile = path.join(config.outputDir, path.basename(inputFile, '.md') + config.fileExtension);

This code does a few things:

  • If md2html.config.json exists, it reads the file and updates the config object with its values.
  • We use the outputDir and fileExtension from the config to generate the output file path.

Step 3: Using Configuration Options

Now when users run the tool, they don’t have to specify an output file if they don’t want to. They can rely on the defaults in their config file instead.

For example, if a user has this in their config file:

{
  "outputDir": "./output",
  "fileExtension": ".html"
}

They can simply run:

md2html input.md

And the tool will save the output to ./output/input.html without needing any extra arguments.

Takeaway

Look at you—you’ve come a long way from that basic script we started with in the last tutorial. Now you’ve got a CLI tool that can handle arguments, validate inputs, and read/write files. Plus, it’s got some manners thanks to error handling and helpful messages. Your tool can even be customized by users via configuration files, making it super flexible and professional.

At this point, you’re basically a CLI master. And trust me, there’s no turning back from here—you’ll want to start automating everything now!

Next up, we’ll make your tool even fancier by adding testing and publishing it as a real, open-source project.

Creating and Maintaining Open-Source Node.js CLI Tools

Welcome! So, you want to build open-source CLI tools in Node.js, huh? Perfect choice! The world needs more niche tools to solve small but crucial problems—things like static site generators, format converters, or quick deployment scripts. In this course, we're going to walk through how to create, document, and maintain your own CLI tool. By the end, you’ll have a working project ready for the open-source community.

Questions & Answers

to widen your perspective.

Tools

available to use.

Providers

to have an visit.

Resouces

to browse on more.
0x3d
https://www.0x3d.site/
0x3d is designed for aggregating information.
NodeJS
https://nodejs.0x3d.site/
NodeJS Online Directory
Cross Platform
https://cross-platform.0x3d.site/
Cross Platform Online Directory
Open Source
https://open-source.0x3d.site/
Open Source Online Directory
Analytics
https://analytics.0x3d.site/
Analytics Online Directory
JavaScript
https://javascript.0x3d.site/
JavaScript Online Directory
GoLang
https://golang.0x3d.site/
GoLang Online Directory
Python
https://python.0x3d.site/
Python Online Directory
Swift
https://swift.0x3d.site/
Swift Online Directory
Rust
https://rust.0x3d.site/
Rust Online Directory
Scala
https://scala.0x3d.site/
Scala Online Directory
Ruby
https://ruby.0x3d.site/
Ruby Online Directory
Clojure
https://clojure.0x3d.site/
Clojure Online Directory
Elixir
https://elixir.0x3d.site/
Elixir Online Directory
Elm
https://elm.0x3d.site/
Elm Online Directory
Lua
https://lua.0x3d.site/
Lua Online Directory
C Programming
https://c-programming.0x3d.site/
C Programming Online Directory
C++ Programming
https://cpp-programming.0x3d.site/
C++ Programming Online Directory
R Programming
https://r-programming.0x3d.site/
R Programming Online Directory
Perl
https://perl.0x3d.site/
Perl Online Directory
Java
https://java.0x3d.site/
Java Online Directory
Kotlin
https://kotlin.0x3d.site/
Kotlin Online Directory
PHP
https://php.0x3d.site/
PHP Online Directory
React JS
https://react.0x3d.site/
React JS Online Directory
Angular
https://angular.0x3d.site/
Angular JS Online Directory