{"id":25194,"library":"ejs-lint","title":"ejs-lint","description":"Linter and syntax checker for EJS templates. Version 2.0.1 released September 2022. ESM-only since v2, requires Node 14+. Parses scriptlet and expression tags, replacing template output with whitespace to retain line/column numbers, then validates resulting JavaScript with acorn via node-syntax-error. Distinguishes itself from EJS core by providing meaningful syntax error messages with line context, supporting custom delimiters, CLI and API usage. Does not check for unclosed EJS tags but helps detect malformed scriptlets. Alternatives exist (e.g., eslint-plugin-ejs) but ejs-lint is the standalone, lightweight option.","status":"active","version":"2.0.1","language":"javascript","source_language":"en","source_url":"git://github.com/ryanzim/ejs-lint","tags":["javascript"],"install":[{"cmd":"npm install ejs-lint","lang":"bash","label":"npm"},{"cmd":"yarn add ejs-lint","lang":"bash","label":"yarn"},{"cmd":"pnpm add ejs-lint","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Parses template text using EJS's internal Template.parseTemplateText()","package":"ejs","optional":false},{"reason":"Generates syntax error objects with line/column info","package":"node-syntax-error","optional":false},{"reason":"JavaScript parser used for syntax validation","package":"acorn","optional":false},{"reason":"Loads EJS to access private parseTemplateText function","package":"rewire","optional":false}],"imports":[{"note":"ESM-only since v2; use dynamic import or upgrade to Node 14+.","wrong":"const ejsLint = require('ejs-lint')","symbol":"default","correct":"import ejsLint from 'ejs-lint'"},{"note":"CLI is invoked via the 'ejslint' command, not as a programmatic export.","wrong":"import { ejslint } from 'ejs-lint'","symbol":"cli","correct":"import { execSync } from 'child_process'; execSync('npx ejslint file.ejs', {stdio: 'inherit'})"},{"note":"ejs-lint does not export its own error type; returns node-syntax-error objects.","wrong":"import type { EjsLintError } from 'ejs-lint'","symbol":"types","correct":"import type { SyntaxError } from 'node-syntax-error'"}],"quickstart":{"code":"import ejsLint from 'ejs-lint';\n\nconst template = `<% if (user) { %>\n  <h1><%= user.name %></h1>\n<% } else { %>\n  <h1>No user</h1>\n<% } %>`;\n\nconst err = ejsLint(template, { delimiter: '%' });\nif (err) {\n  console.error(`Syntax error at line ${err.line}, column ${err.column}: ${err.message}`);\n} else {\n  console.log('Template is valid');\n}","lang":"typescript","description":"Shows how to use the ejsLint API to check an EJS template for syntax errors."},"warnings":[{"fix":"Update code to use import statements or use dynamic import().","message":"v2.0.0 switched to ESM-only; CommonJS require() will fail","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Upgrade Node.js to version 14 or higher.","message":"v2.0.0 dropped Node 12 support; requires Node 14+","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Replace .lint(text, options) with ejsLint(text, options).","message":"v1.0.0 removed deprecated .lint() alias; use ejsLint() instead","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"Use ejsLint() API or ejslint CLI only.","message":"v0.3.0 removed parse() method and --parse CLI option","severity":"breaking","affected_versions":">=0.3.0"},{"fix":"Manually check for unclosed <% or %> before blaming the linter.","message":"Does not detect unclosed EJS tags; will show confusing errors on lines without scriptlets","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-05-01T00:00:00.000Z","next_check":"2026-07-30T00:00:00.000Z","problems":[{"fix":"Switch to import or use dynamic import: const ejsLint = (await import('ejs-lint')).default;","cause":"Using CommonJS require() on EJS-Lint v2+","error":"Error [ERR_REQUIRE_ESM]: require() of ES Module not supported"},{"fix":"Double-check all <% and %> tags are properly closed.","cause":"Forgot to close an EJS tag earlier in the template","error":"SyntaxError: Unexpected token (1:5) - line doesn't contain any scriptlets"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}