npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@wcj/ejs-cli

v1.6.0

Published

An enhanced version of the EJS cli.

Downloads

398

Readme

ejs-cli

Buy me a coffee CI NPM version

Enhanced version of EJS cli. A command-line tool based on the ejs wrapper, but with many useful features added.

Features

  • Support config files to configure ejs options.
  • Multiple .ejs files matching to generate html.
  • Multiple ways of data injection into templates.
  • Global data injection template
  • Monitoring .ejs to output .html files in real time.
  • Support automatic copying of static resources

Install

$ npm install @wcj/ejs-cli
# Or
$ npm install --global @wcj/ejs-cli

Quick start

$ ejsc "template/**/*"
$ ejsc "template/*.ejs" "template/about/*.ejs" --watch

Command Help

Below is a help of commands you might find useful. You can use the ejsc and ejs-cli commands:

Usage: ejs-cli <source...> [options]

Options:

  -v, --version             Show version number
  -h, --help                Show help
  -w, --watch               Listen to ejs changes and output HTML (default: "false")
  -o, --out                 Specify the output directory (default: "dist")
  -m, --delimiter           Use CHARACTER with angle brackets for open/close (defaults to %)
  -p, --open-delimiter      Use CHARACTER instead of left angle bracket to open.
  -c, --close-delimiter     Use CHARACTER instead of right angle bracket to close.
  -f, --data-file FILE      Must be JSON-formatted. Use parsed input from FILE as data for rendering
  --rm-whitespace           Remove all safe-to-remove whitespace, including leading and trailing
  --copy-pattern            Use shell patterns to match the files that need to be copied.

Examples:

  $ ejsc "template/*.ejs" "template/about/*.ejs"
  $ ejsc "template/*.ejs" "template/about/*.ejs" --watch
  # The above command: matches all `.ejs` files in the template folder
  $ ejsc "template/**/*" --watch
  $ ejs-cli "template/*.ejs" --watch --out build

Copyright 2024

Match files

Folders and .ejs files starting with an underscore (_) will be ignored.

$ ejs-cli "template/**/*"
$ ejsc "template/**/*"
$ ejsc "template/*.ejs" "template/about/*.ejs"
$ ejsc "template/home.ejs" "template/about.ejs"

The above command: matches all .ejs files in the template folder, excluding files starting with _ and .ejs files in folders starting with _.

Inject data

Inject data by default

PUBLIC_PATH

PUBLIC_PATH Relative path string concatenation. E.g: ../, ../../.

<link rel="stylesheet" href="<%= PUBLIC_PATH %>static/css/main.css">

<img src="<%= PUBLIC_PATH %>static/img/logo.png" />

<a href="<%= PUBLIC_PATH %>about/index.html"><a>

GLOBEL

You need to specify the data file --data-file ./data.json on the command line, or configure the globelData field in the configuration

<h2><%= GLOBEL.helloworld %></h2>

If the specified ./temp.json injection data content is an array, the value will be assigned to the template variable of TEMP. The variable naming rule is uppercase for file names:

  • ./a/data-name.json => DATA_NAME
  • ./temp/data.json => DATA
  • ./temp/temp.json => TEMP
//=> ./a/data-name.json
[
  { name: "ejs", version: "v1.2" },
  { name: "auto-config-loader", version: "^1.7.4" },
];

The value will be assigned to the template variable of DATA_NAME

<% DATA_NAME.forEach((item) => { %>
  <div><%= item.name %>@<%= item.version %></div>
<% }); %>

The rules are the same in configuration.

NOW_DATE

Current page compilation time

<div><%=NOW_DATE%></div>

GLOBEL.PACKAGE

Read the project's package.json file and inject its data into the template engine so that it can be accessed via GLOBAL.PACKAGE. An example is shown below:

<footer>
  <p>&copy; 2017 Company, Inc.</p>
  v<%=GLOBEL.PACKAGE.version%>
</footer>

Specific Template

Inject data into a specific template, which needs to be configured in .ejscrc.mjs:

{
  "globelData": {
    "helloworld": "Hello Wrold!"
  },
  "data": {
    "template/about/index.ejs": "./data.json",
    "template/home.ejs": {
      "name": "Hello World",
      "age": 36
    }
  }
}

Used in template/home.ejs template

<h2><%= name %></h2>
<h3><%= GLOBEL.helloworld %></h3>

HTML Minifier

In the .ejscrc.mjs configuration, add the beforeSaveHTML method to process and compress HTML using html-minifier.

import { minify } from "html-minifier";

const options = {
  includeAutoGeneratedTags: true,
  removeAttributeQuotes: true,
  removeComments: true,
  removeRedundantAttributes: true,
  removeScriptTypeAttributes: true,
  removeStyleLinkTypeAttributes: true,
  sortClassName: true,
  useShortDoctype: true,
  collapseWhitespace: true,
};

/**
 * @type {import('@wcj/ejs-cli/lib/watch.mjs').Options}
 */
export default {
  watchOption: {},
  globelData: {},
  data: {},
  beforeSaveHTML: (html, output, filename) => {
    const minHTML = minify(html, options);
    return minHTML + "<!-- Hello -->";
  },
};

JS Minifier

In the .ejscrc.mjs configuration, add the afterCopyFile method to process and compress HTML using UglifyJS.

import UglifyJS from "uglify-js-export";
import fs from "fs-extra";

export default {
  watchOption: {},
  globelData: {},
  data: {},
  afterCopyFile: (filePath, outputPath) => {
    if (filePath.endsWith(".js")) {
      const result = UglifyJS.minify(fs.readFileSync(outputPath, "utf-8"));
      fs.writeFileSync(outputPath, result.code);
      console.log(`🐝 Compress js file success! ${outputPath}`);
    }
  },
};

CSS Minifier

In the .ejscrc.mjs configuration, add the afterCopyFile method to process and compress HTML using clean-css.

import CleanCSS from "clean-css";
import fs from "fs-extra";

export default {
  watchOption: {},
  globelData: {},
  data: {},
  afterCopyFile: (filePath, outputPath) => {
    if (filePath.endsWith(".css")) {
      const result = new CleanCSS().minify(
        fs.readFileSync(outputPath, "utf-8"),
      );
      fs.writeFileSync(outputPath, result.styles);
      console.log(`🐝 Compress css file success! ${outputPath}`);
    }
  },
};

Config

The default configuration is the parameter of EJS, you can add data to inject data into the EJS template, and add watchOption parameter to configure Chokidar settings.

Store .ejscrc.json in the root directory of the project:

{
  "watchOption": {},
  "data": {
    "template/home.ejs": {
      "name": "Hello World",
      "age": 36
    }
  }
}

Support JSON, JSONC, JSON5, YAML, TOML, INI, CJS, Typescript, and ESM config load.

.ejscrc.mjs config example:

import { minify } from "html-minifier";
import UglifyJS from "uglify-js-export";
import fs from "fs-extra";

/**
 * @type {import('@wcj/ejs-cli/lib/watch.mjs').Options}
 */
export default {
  /** Chokidar's watch parameter settings */
  watchOption: {},
  /** Injecting data into EJS templates */
  data: {
    "template/home.ejs": {
      name: "Hello World",
      age: 36,
    },
  },
  /**
   * Use shell patterns to match the files that need to be copied.
   * @default "/**\/*.{css,js,png,jpg,gif,svg,webp,eot,ttf,woff,woff2}"
   */
  copyPattern: "",
  /**
   * Pre-Save HTML Callback Method
   * @param html
   * @param output
   * @param filename
   * @returns
   */
  beforeSaveHTML: (html, output, filename) => {
    return minify(html, options);
  },
  /**
   * Callback method after copying files.
   * @param filepath
   * @param output
   * @returns
   */
  afterCopyFile: (filePath, outputPath) => {
    if (filePath.endsWith(".js")) {
      const result = UglifyJS.minify(fs.readFileSync(outputPath, "utf-8"));
      fs.writeFileSync(outputPath, result.code);
      console.log(`🐝 Compress js file success! ${outputPath}`);
    }
  },
};

You can configure in package.json:

{
  "name": "@wcj/examples",
  "version": "0.0.1",
  "ejsc": {
    "data": {
      "template/home.ejs": {
        "name": "Hello World",
        "age": 36
      }
    }
  }
}

For more configuration methods, please see default searchPlaces.

Development

$ npm i
$ npm run build

Contributors

As always, thanks to our amazing contributors!

Made with contributors.

License

MIT © Kenny Wong