Skip to content

allow undefined variables to be falsy - bad recursive variable declaration error #1494

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sojournerc opened this issue Aug 14, 2013 · 8 comments

Comments

@sojournerc
Copy link

I would like to do some theme switching using a variable "colors.less" file, but guarded expressions aren't quite doing what I would expect. My hope is that when calling a guarded mixin, undefined variables won't throw an error but will rather be treated as falsy:

in theme-main.less:

@themeColorPath: '/theme/colors.less';
@import url('main.less');   

in main.less:

.themeOn (@themeColorPath) when not (@themeColorPath) {
@colorPath: 'colors.less'
}
.themeOn (@themeColorPath) when (isstring(@themeColorPath)) {
@colorPath: @themeColorPath;
}
.themeOn(@themeColorPath);
@import url(@colorPath);

In javascript, an undefined variable is falsy, so I would expect "when not(@themeColorPath)" to be satisfied if @themeColorPath isn't defined, but instead the compiler complains.

I'm not sure of any other way to dynamically load "colors.less" based on what a theme-main.less defines

@sojournerc
Copy link
Author

Solved this issue by doing:

@colorPath: `(@{themeColorPath}) ? @{themeColorPath} : 'colors.less'`; 

@sojournerc
Copy link
Author

I thought that fixed it, but when @themeColorPath is undefined I am getting a recursive variable definition error:

NameError: Recursive variable definition for @colorPath

As far as I can tell, there is nothing recursive about the code. If I remove the @import and just try to declare the variable with the ternary, I get the following, which I assume is another complaint about an undefined variable:

non_object_property_loadError: Cannot read property 'filename' of undefined

This is my code:

@baseVariable: '../theme/base/variables.less';
@baseColor: '../theme/base/colors.less';
@colorPath: `(@{themeColorPath}) ? @{themeColorPath} : @{baseColor}`;
@variablePath: `(@{themeVariablePath}) ? @{themeVariablePath} : @{baseVariable}`;

@import url(@colorPath);
@import url(@variablePath);

It appears to me the compiler errantly considers something recursive which isn't.

@lukeapage
Copy link
Member

Hi,

Please could you give us a full repro example? the example you say is your code.. what file is that? what other files are there?

@sojournerc
Copy link
Author

The goal I am trying to achieve is to be able to compile themed versions of the stylesheets. So I want to be able to compile main.less to main.css and theme-main.less to theme-main.css. My intention is to add theme-main.less as a layer above main.less and change the path it uses to import colors.less and variables.less

main.less :

@baseColor: 'colors.less';
@baseVariable: 'variables.less';
@colorPath: `(@{themeColorPath}) ? @{themeColorPath} : @{baseColor}`;
@variablePath: `(@{themeVariablePath}) ? @{themeVariablePath} : @{baseVariable}`;
@import url(@colorPath);
@import url(@variablePath);

..... (additional imports)....

When I try to compile with main.less as src, I get the recursive declaration error:

>> NameError: Recursive variable definition for @colorPath in src/main/webapp/less/main.less on line 8, column 13:
>> 7 @variablePath: `(@{themeVariablePath}) ? @{themeVariablePath} : @{baseVariable}`;
>> 8 @import url(@colorPath); 
>> 9 @import url(@variablePath);

with theme/theme-main.less as:

@themeColorPath: 'theme/colors.less';
@themeVariablePath: 'theme/variables.less';

@import url('../main.less');

When I compile with theme/theme-main.less, it compiles and imports as expected.

@jlukic
Copy link

jlukic commented Nov 20, 2013

I'm running into this same issue using a very similar set-up, could see this solved by either allowing undefined values in guards or allowing any sort of "default value" setup with foo || baz syntax.

@seven-phases-max
Copy link
Member

My intention is to add theme-main.less as a layer above main.less and change the path it uses to import colors.less and variables.less

Just in case, this can be achieved without any conditionals, for example:

// .........
// main.less

.default-paths {
    @colorPath:    'colors.less';
    @variablePath: 'variables.less';
} .default-paths;

@import '@{colorPath}';
@import '@{variablePath}';

// ..........
// theme.less

@colorPath:    'theme/colors.less';
@variablePath: 'theme/variables.less';

@import 'main.less';

Basically, variables defined in .default-paths get into global scope only if it has no such variables already defined.

@sojournerc
Copy link
Author

Awesome, thx @seven-phases-max, that's exactly what I was looking for.

@seven-phases-max
Copy link
Member

Closed as duplicate of #1400.

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

No branches or pull requests

4 participants