Skip to content

fix: give the lessc bin a .js extension - #4565

Open
eknathdj wants to merge 2 commits into
less:masterfrom
eknathdj:fix/lessc-bin-extension
Open

eknathdj wants to merge 2 commits into
less:masterfrom
eknathdj:fix/lessc-bin-extension

Conversation

@eknathdj

@eknathdj eknathdj commented Oct 26, 2026 •

Copy link
Copy Markdown

Resolves #4561

Root cause

Since 4.6.0 the less package declares "type": "module" and its bin entry points
at the extensionless bin/lessc. When Node loads an extensionless file in an ESM
context it raises:

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension "" for
.../node_modules/less/bin/lessc.

Node's module-syntax detection (--experimental-detect-module, default since
v22.7.0) rescues newer runtimes — which is why the reporter found that "upgrading my
node version fixes this" — but on Node releases without it (e.g. 20.x and 22.0–22.6,
which include current LTS lines) the CLI cannot start at all. The extensionless bin
is the packaging bug: the loader has no way to know the file is ESM.

Fix

Give the bin a proper extension so every Node version loads it unambiguously:

  • bin/lessc → bin/lessc.js (git mv; contents unchanged — the file is already ESM
    with a hashbang, which Node supports in .js files)
  • packages/less/package.json: "bin": { "lessc": "./bin/lessc.js" }
  • packages/less/Gruntfile.cjs: the 13 node bin/lessc … shell invocations updated
  • one comment in parse-tree.js referencing the old path

The files field already ships the whole bin folder, so packaging is unaffected.
The npm shim scripts are generated from the bin mapping, so npx lessc /
node_modules/.bin/lessc keep working with no user-visible rename.

Validation

  • node packages/less/bin/lessc.js --version → lessc 4.9.1 (Less Compiler)
  • npm run test:node → 281 run, all passed — including the shell:opts and
    shell:plugin grunt tasks that invoke the renamed path 13 times, and the CJS build
    tests
  • eslint clean on the touched files (the repo's enforced lint gate; note
    prettier --check flags these three files identically on unpatched master, so no
    formatting regression is introduced)

Summary by CodeRabbit

  • New Features
    • Added the Less command-line compiler, which can compile Less files or standard input into CSS and optionally generate source maps.
    • The compiler supports options for plugins, variables, URL rewriting, dependency output, and math behavior. It reports invalid inputs and compilation errors.
    • The lessc command and related test commands now use the correct executable path.

bin/lessc is an ESM file in a type:module package; without an extension Node raises ERR_UNKNOWN_FILE_EXTENSION on runtimes without default module-syntax detection (before v22.7.0). Renames it to bin/lessc.js and updates the bin mapping, the 13 Gruntfile shell invocations and one comment. Resolves less#4561.
@coderabbitai

coderabbitai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 7133316 and 32c4ba4.

Files selected for processing: 4
  • packages/less/Gruntfile.cjs
  • packages/less/bin/lessc.js
  • packages/less/lib/less/parse-tree.js
  • packages/less/package.json

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Walkthrough

The CLI is added at bin/lessc.js. The package binary mapping and Grunt commands now use that path. The CLI parses options, loads plugins, reads Less input, renders it, and handles CSS, source-map, and dependency output.

Changes: lessc CLI entry point

Layer / File(s) Summary
Option parsing and plugin loading
packages/less/bin/lessc.js
The CLI parses compiler options, queues deprecation warnings, and loads queued plugins before rendering.
Input rendering and output
packages/less/bin/lessc.js
The CLI validates render settings, reads Less input or stdin, renders it, and handles CSS, source-map, and dependency output.
Executable path updates
packages/less/package.json, packages/less/Gruntfile.cjs, packages/less/lib/less/parse-tree.js
The package binary mapping and Grunt commands use lessc.js. A source-map comment identifies the new path.

Priority: Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: matthew-dean

Merge Risk: Minimal · previous review 32c4b

The executable path updates are consistent, and no actionable regression remains identified. This change is mergeable after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 3 files. (1 skipped: 1 … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title "fix: give the lessc bin a .js extension" matches the main change: the bin file is renamed from bin/lessc to bin/lessc.js, and the package.json bin mapping, 13 Gruntfile shell invocations, a…
Linked Issues check Passed Issue #4561 has one active coding requirement: make the lessc CLI start under "type": "module" by giving the bin an unambiguous ESM extension, and keep npx lessc myFile.less myFile.css working. …
Out of Scope Changes check Passed All changed files connect directly to the #4561 objective:
- packages/less/package.json: bin mapping to ./bin/lessc.js (required fix).
- packages/less/Gruntfile.cjs: 13 shell invocations changed…
Full details: Title check

Explanation

The title "fix: give the lessc bin a .js extension" matches the main change: the bin file is renamed from bin/lessc to bin/lessc.js, and the package.json bin mapping, 13 Gruntfile shell invocations, and one comment are updated to match. The linked issue #4561 reports the ERR_UNKNOWN_FILE_EXTENSION failure that this rename addresses. The title is short, specific, and states the primary change from the developer's perspective.

Full details: Linked Issues check

Explanation

Issue #4561 has one active coding requirement: make the lessc CLI start under "type": "module" by giving the bin an unambiguous ESM extension, and keep npx lessc myFile.less myFile.css working. The PR meets this requirement:

  • packages/less/package.json now maps lessc to ./bin/lessc.js (confirmed by diff against the merge base). The .js extension makes Node load the file as ESM, which removes the ERR_UNKNOWN_FILE_EXTENSION failure.
  • packages/less/bin/lessc.js exists at the reviewed head with the same ESM source and hashbang as the original bin file.
  • packages/less/Gruntfile.cjs invokes bin/lessc.js or ../bin/lessc.js in the shell:opts, shell:plugin, and shell:sourcemap-test tasks (13 invocations, confirmed by diff). Automated CLI coverage therefore exercises the new path.
  • The issue's suggested fix (rename to .js and update bin) is implemented. The issue does not require new tests. The author reports npm run test:node passing (281 tests). I did not run tests, so that result is author-reported and unverified here.
    No unmet coding requirement was found.
Full details: Out of Scope Changes check

Explanation

All changed files connect directly to the #4561 objective:

  • packages/less/package.json: bin mapping to ./bin/lessc.js (required fix).
  • packages/less/Gruntfile.cjs: 13 shell invocations changed from bin/lessc to bin/lessc.js so existing tasks run the renamed entry point (necessary consequence of the rename).
  • packages/less/bin/lessc.js: the renamed CLI file (required fix).
  • packages/less/lib/less/parse-tree.js: comment-only update referencing the new path; no runtime change (related, non-functional).
    Non-blocking observation: at the reviewed head, the original extensionless packages/less/bin/lessc is still tracked alongside bin/lessc.js. The PR description says the file was moved with git mv, but the repository shows a copy. The leftover file is not referenced by package.json or the Gruntfile. The issue explicitly allows keeping an extensionless shim, so this does not count as an unrelated change. Removing the leftover file would avoid a duplicate in the published bin folder, but this is not a scope failure.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 3 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The change affects users who launch Less through its command-line compiler.

The PR appears safe to merge, with a non-blocking cleanup needed for the duplicate CLI.

Summary

The PR points lessc at an explicit .js entry file.

  • The Less command starts through a clearly named JavaScript entry point.

Reviews (1) · Last reviewed commit: "fix: give the lessc bin a .js extension" · Reviewed by Greptile

Comment on lines +5 to +11
import path from 'path';
import os from 'os';
import { createRequire } from 'module';
import fs from '../lib/less-node/fs.js';
import * as utils from '../lib/less/utils.js';
import * as Constants from '../lib/less/constants.js';
import less from '../lib/less-node/index.js';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 CLI code is duplicated

The new lessc.js copies all 678 lines of bin/lessc, but the old file remains tracked and both files ship in the package. Future fixes could update one copy while leaving the other behind. Complete the rename by removing bin/lessc, or make it a small wrapper if the old path must remain supported.

The previous commit added bin/lessc.js but kept the original bin/lessc, so both shipped as byte-identical copies. Remove the old file so the change is the rename the PR describes.
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.

lessc CLI fails to start since 4.6.0: bin/lessc is extensionless under "type": "module"

1 participant