less / less/less.js

3.9 | Functions added by @plugin inside #namespace cannot be referenced

Open
#3,500 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug medium priority
Dominant language
JavaScript
Stars
17k
Forks
3.4k
Avg merge
7h 42m
Merged PRs (30d)
26

Description

Functions that are added to a #namespace by a @plugin directive cannot be referenced by mixins residing in the namespace.

Given a simple plugin that adds a trivial plugin function, let's say lowercase , and the following Less sample:

#namespaced {
  @plugin "./plugins/lowercase.js";

  .mixin(@value) {
    value : lowercase(@value);
  }
}

.test {
  #namespaced.mixin("FOO");
}

the actual output I'd get is:

.test {
  value : lowercase("FOO");
}

whereas the expected output would be:

.test {
  value : "foo";
}

WORKAROUND

Problem has two easy workarounds, both of which have issues of their own:

  1. make the @plugin directive global -- but this leaks it to other stylesheets (!!)
  2. scope the @plugin directive to the mixin -- but this is not practical for multiple mixins and not possible for functions used in when mixin guards.

(I actually think leaking it to other stylesheets is a regression. Don't think the 2.x @plugin directive did that...)

The only bullet-proof workaround is using an unlocking-mixins pattern: That is:

  1. nest all the actual mixin functionality of the namespace in yet another mixin;
  2. create facade duplicates of the original mixins and put those directly in the namespace; and finally
  3. 'unlock' the nested mixins inside inside the facades and chain the call.

E.g.

#namespaced {

  .mixin(@value) {
    #namespaced._();
    .mixin(@value);
  }

  ._() {
    @plugin "./plugins/lowercase.js";

    .mixin(@value) {
      value : lowercase(@value);
    }
}

.test {
  #namespaced.mixin("FOO");
}

Needless to say; this is a lot of undesired boilerplate.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the namespace, @plugin, and mixin-resolution entry points implicated by the reproduction; the payload does not name specific files or tests. Reproduce the Less sample and trace why lowercase remains unresolved inside the namespace. Done means the sample emits value: "foo" without requiring global or unlocking-mixin workarounds.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.