less.js
less.js copied to clipboard
Can’t use @import inside each()
Have this piece of code that imports component files based on a variable.
@components: {
columns: true;
ratios: false;
};
each(@components, {
& when (@value = true) {
@import "components/@{key}.less";
}
});
It errors, with: error evaluating function 'each': variable @key is undefined.
But it is defined, because this works:
// LESS
each(@components, {
& when (@value = true) {
.test {
content: @key;
}
}
});
// CSS Output
.test {
content: columns;
}
It’s not due to the variable being a map, or the usage of a guard, this example using a list creates the same error:
each(@components, {
@import "components/@{value}.less";
});
Is there an alternative way to achieve this?
Interpolating variables in an import is a challenging problem in Less because it can create circular evaluation.
Less @imports essentially expose in scope all mixins, variables, other imports, etc in the parent scope. As a result, Less tries to evaluate @imports first, if possible. And as a result of THAT, there are places where it won't work. (There are probably related bugs around placing an interpolated import in a block scope, which I'd appreciate if someone could find.)
So, my feeling is this isn't a bug specific to each(), but related to issues around interpolated @imports.
The better way to do this is to import all imports, and instead expose a mixin that takes the value, so that you have something like:
@import "components/all";
each(@components, {
& when (@value = true) {
.do-thing(@key);
}
});
I marked this as a bug but this should get linked to other interpolated @import issues.
Related to https://github.com/less/less.js/issues/3486 Related to https://github.com/less/less.js/issues/2531