Skip to content

fix(cli): handle directories with no matching templates#2144

Open
cyphercodes wants to merge 1 commit intohandlebars-lang:masterfrom
cyphercodes:fix-cli-directory-handling
Open

fix(cli): handle directories with no matching templates#2144
cyphercodes wants to merge 1 commit intohandlebars-lang:masterfrom
cyphercodes:fix-cli-directory-handling

Conversation

@cyphercodes
Copy link
Copy Markdown

Fixes #2109

Previously, when passing a directory to the handlebars CLI that either had no template files or no files matching the extension, the CLI would show the help message instead of processing the directory.

This fix:

  1. Updates the help condition to also check hasDirectory flag
  2. Adds a warning when a directory is specified but no templates are found

The CLI now properly processes directories and provides feedback when no templates are found instead of confusingly showing usage help.

Changes

  • bin/handlebars.mjs: Added !opts.hasDirectory to the help condition
  • lib/precompiler.js: Added warning when directory has no matching templates

Testing

  • Tested with empty directories
  • Tested with directories containing templates
  • Tested with directories containing no matching files
  • All existing unit tests pass

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes the Handlebars CLI behavior when a directory argument yields zero matching templates (empty dir or extension filter mismatch), ensuring the CLI doesn’t show usage help incorrectly and instead proceeds with directory processing while warning the user.

Changes:

  • Update CLI help-display condition to treat “directory provided but no templates found” as a valid invocation.
  • Add a warning from the precompiler CLI path when directories were scanned but no templates matched.

Reviewed changes

Copilot reviewed 1 out of 2 changed files in this pull request and generated 2 comments.

File Description
bin/handlebars.mjs Adjusts help condition to account for opts.hasDirectory so directories don’t trigger help output when empty/filtered.
lib/precompiler.js Emits a warning when directory scanning produces zero templates.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/precompiler.js Outdated
}

if (!opts.templates.length && opts.hasDirectory) {
console.warn('Warning: No templates found in the specified directory.');
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New warning output is not covered by existing unit tests and will currently leak to the real stderr because the test harness in spec/precompiler.js mocks console.log/console.error but not console.warn. Consider either (a) adding/adjusting tests to stub and assert console.warn for this case, or (b) routing this message through the existing console.error path so tests and consumers can consistently capture it.

Suggested change
console.warn('Warning: No templates found in the specified directory.');
console.error('Warning: No templates found in the specified directory.');

Copilot uses AI. Check for mistakes.
Comment thread lib/precompiler.js Outdated
}

if (!opts.templates.length && opts.hasDirectory) {
console.warn('Warning: No templates found in the specified directory.');
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning message is fairly generic; it would be more actionable if it included the directory path(s) that were scanned and (when applicable) the extension filter being used (e.g., --extension). This helps users distinguish between an empty directory vs. a directory with files that were filtered out.

Suggested change
console.warn('Warning: No templates found in the specified directory.');
const dirs =
(Array.isArray(opts.directories) && opts.directories.length
? opts.directories.join(', ')
: opts.directory) || 'unknown';
const extInfo = opts.extension ? ` with extension filter "${opts.extension}"` : '';
console.warn(
`Warning: No templates found in the specified directory/directories (${dirs})${extInfo}.`
);

Copilot uses AI. Check for mistakes.
Comment thread bin/handlebars.mjs Outdated
}

if (opts.help || (!opts.templates.length && !opts.version)) {
if (opts.help || (!opts.templates.length && !opts.hasDirectory && !opts.version)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is ~86 chars and is what's breaking CI — npm run lint:format (oxfmt --check) fails on bin/handlebars.mjs in the latest run. Running npm run lint:format -- --fix (or the oxfmt equivalent) will wrap it and unblock the build.

Comment thread lib/precompiler.js Outdated
}

if (!opts.templates.length && opts.hasDirectory) {
console.warn('Warning: No templates found in the specified directory.');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separately from the other feedback on this line: once we've warned the user that nothing was found, the function still falls through and executes the whole output pipeline below. With opts.output set, that means we silently overwrite the user's output file with the empty scaffold (function() { var template = Handlebars.template, templates = {}; })(); while also telling them no templates were found — which is surprising and can clobber a previously-good artifact.

Consider return; right after the warning (or turning this into a thrown Handlebars.Exception so callers see a non-zero exit), so we don't produce output when we just reported there's nothing to produce.

@kibertoad
Copy link
Copy Markdown
Contributor

kibertoad commented Apr 21, 2026

A couple of higher-level notes that don't fit on a specific line:

Test coverage for the new behavior is missing. The PR description says "All existing unit tests pass," but no new test was added. The pre-existing should handle empty/filtered directories test at spec/precompiler.js:71 only asserts "does not throw" — it doesn't assert that the new warning is emitted, and with the current beforeEach mocking only console.log/console.error, it can't (see Copilot's note about console.warn leaking). Once the mock/routing issue is addressed, please add an explicit assertion for the warning path so this doesn't regress silently.

Worth grounding the warning text in #2109's actual root cause. Re-reading the issue thread, the problem was almost certainly that their templates used .hbs while the CLI's default extension filter is .handlebars - so the directory wasn't empty, its files were just silently filtered out. Copilot already suggested including the directory and extension in the message; I'd go a step further and phrase it so a user in that exact situation recognizes themselves, e.g. No files matching *.<extension> found under <dir>. Pass --extension <ext> if your templates use a different extension. That turns the warning into a fix-it-yourself hint rather than a restatement of the symptom.

@cyphercodes cyphercodes force-pushed the fix-cli-directory-handling branch from dbd30de to 4cf387d Compare April 25, 2026 19:15
@cyphercodes
Copy link
Copy Markdown
Author

cyphercodes commented Apr 25, 2026

Updated this PR to address the recent review feedback:

  • rebased/recreated the branch on current master to clear the merge conflict
  • fixed the formatting issue that was failing lint
  • changed the empty/filtered-directory path to warn and return early, so it no longer falls through into the output pipeline
  • updated the warning to mention the matched extension and input directory, with a --extension <ext> hint for the common .hbs vs .handlebars case
  • added explicit test coverage for the warning/early-return behavior and mocked console.warn so it doesn't leak during tests

Local verification:

  • npm run lint
  • npm test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Precompiler doesn't take directories as input

3 participants