less.js icon indicating copy to clipboard operation
less.js copied to clipboard

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

Open rjgotten opened this issue 4 years ago • 2 comments

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.

rjgotten avatar May 07 '20 10:05 rjgotten

Can you do:

& {
  @plugin "./plugins/lowercase.js";
  #namespaced {
    .mixin(@value) {
      value : lowercase(@value);
    }
  }

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

Other than workarounds, I don't think this can be reasonably addressed without rewriting the evaluation order algorithm.

matthew-dean avatar Jul 16 '20 15:07 matthew-dean

That's an interesting idea, but afaik won't publish the namespace. ...which is sort of what I was after, as I'm attempting to build library functionality for re-use elsewhere. :wink:

rjgotten avatar Jul 17 '20 07:07 rjgotten