npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details


  • User packages



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.


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 🙏

© 2021 – Pkg Stats / Ryan Hefner




Linter/Syntax Checker for EJS Templates





Linter/Syntax Checker for EJS Templates.

This was born out of mde/ejs #119 and the frustration of the unhelpful errors thrown if you make a simple syntax error inside a scriptlet tag.


EJS-Lint parses scriptlet tags (<%, %>, <%_, _%>, and -%>) and expression tags (<%= and <%-).

Note: This linter does not attempt to check for unclosed EJS tags, so if you get an error Unexpected token with a line number that doesn't contain any scriptlets, you most likely forgot to close a tag earlier.

It will error out if it encounters an old-style includes (<% include filename %>) by default, but will tolerate them if the --preprocessor-include/preprocessorInclude option is set. It does not lint included files regardless of the method of inclusion.

Using await inside your ejs template will also throw an error by default - use option --await/await to allow usage of await in the template.

It can work with custom delimiters, just pass it in the options (if using the API) or pass the --delimiter (-d) flag on the CLI.


To install globally, for command-line use:

npm install -g ejs-lint

How it Works

EJS-Lint replaces everything outside a scriptlet tag with whitespace (to retain line & column numbers) and then runs the resulting (hopefully) valid JS through node-syntax-error to check for errors.

We use rewire to load EJS. This allows us to access Template.parseTemplateText(), an internal function that parses the string and splits it into an array.

Why can't EJS do this? At EJS, we try to keep the library lightweight. EJS-Lint uses acorn which is too large a dependency for EJS.


 ejslint <file> [-d=?]

  If no file is specified, reads from stdin

  --help                  Show help                                            [boolean]
  --version               Show version number                                  [boolean]
  -d, --delimiter         Specify a custom delimiter ( i.e. <? instead of <% ) [string]
  --preprocessor-include  Allow old (pre-EJS v3) preprocessor-style includes   [boolean]
  --await                 Allow usage of await inside template                 [boolean]



const ejsLint = require('ejs-lint');

Then do ejsLint(text, options); where text is the EJS template and options are the EJS options (can additionally set preprocessorInclude to allow for old-style includes or set await to allow usage of await inside the template). This returns a node-syntax-error object that you can parse.