Less.js: import.less test failing because of google font import

Created on 5 Oct 2011  ·  27Comments  ·  Source: less/less.js

Hello,

My LESS Java compiler bases on env.js, less.js and Rhino now almost passes all the https://github.com/cloudhead/less.js/tree/master/test tests.

Only 2 failing at the moment, both import.less and javascript.less.

Especially the failing import.less I would like to discuss.

My compiler is first resolving all the imports from less file as otherwise it cannot find them.

So in fact the import.less test

'''
@import url("import/import-test-a.less");
//@import url("import/import-test-a.less");
@import url(http://fonts.googleapis.com/css?family=Open+Sans);

import-test {

.mixin;
width: 10px;
height: @a + 10%;
}

'''

becomes

'''
@import "import-test-d.css";
@c: red;

import {

color: @c;
}

@b: 100%;

.mixin {
height: 10px;
color: @c;
}

@a: 20%;

//@import url("import/import-test-a.less");
@import url(http://fonts.googleapis.com/css?family=Open+Sans);

import-test {

.mixin;
width: 10px;
height: @a + 10%;
}
'''

before I run this String though the LESS Javascript Parser.
So basically the content of all resolved imports are included now.
Also note that the Google Font import has not been resolved as it should be resolved.

When I parse this the result is

'''
@import "import-test-d.css";

import {

color: red;
}
.mixin {
height: 10px;
color: red;
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans'), local('OpenSans'), url('http://themes.googleusercontent.com/static/fonts/opensans/v4/cJZKeOuBrn4kERxqtaUH3aCWcynf_cDxXwCLxiixG1c.ttf') format('truetype');
}

import-test {

height: 10px;
color: red;
width: 10px;
height: 30%;
}
'''

the actual @font-face declaration is included which is not expected, and hence my test fails.

Does the less.js parser does something special to choose to include/exclude the Google Font import?
What I could see from the code is that it checks if it is quoted or not, but as you can see above it's not quotes.
Or maybe does less.js something special, which is not supported by Rhino and env.js...

Would love to hear if you have any ideas...

For the javascript.less test that fails goes wrong based on a Mozilla Javascript Exception.
Does less.js do anything special to support Javascript inside the less?

Hope you can give me some help.
My code is anyway opensource and accessible via http://code.google.com/p/lesscss4j/

Cheers,
Marcel

bug medium priority

Most helpful comment

The workaround I've use is to append &.css to the font URL to trick the LESS parser into handling it like a normal CSS import. Like so:

@import url(http://fonts.googleapis.com/css?family=Open+Sans&.css);

BTW, I find it very unfortunate that LESS' original designers didn't use a separate @include directive, instead of reusing the poor old @import...

All 27 comments

@marceloverdijk i'd be curious to here what you think about #331 and how paths should be adjusted when importing style sheets.

The rule is simple: only import files which end with .less or have no extension, the rest is left to the browser. So @import "foo.css" is left untouched, @import "foo" and @import "foo.less" are parsed and the files are imported.

OK the rule is clear. Thanks.

But do you have any idea why the Google Font import is actually imported then?
The only difference is I'm using Env.js and Rhino instead of a real browser.

Is the less logic maybe using something to determine if it should import or not which is not understood (or incorrectly) by Env.js?

Any help appreciated.

Note that I'm using this to compile the LESS:

var result; var p = new less.Parser(); p.parse(input, function(e, tree) { result = tree.toCSS(); });

1 question about the rule. Do quotes matter?

I noticed this in the import.js less source:

    if (path instanceof tree.Quoted) {
        this.path = /\.(le?|c)ss$/.test(path.content) ? path.content : path.content + '.less';
    } else {
        this.path = path.value.content || path.value;
    }

The workaround I've use is to append &.css to the font URL to trick the LESS parser into handling it like a normal CSS import. Like so:

@import url(http://fonts.googleapis.com/css?family=Open+Sans&.css);

BTW, I find it very unfortunate that LESS' original designers didn't use a separate @include directive, instead of reusing the poor old @import...

I think it should work without that as suggested by the test https://github.com/cloudhead/less.js/blob/master/test/less/import.less

which contains

@import url("import/import-test-a.less");
//@import url("import/import-test-a.less");
@import url(http://fonts.googleapis.com/css?family=Open+Sans);

#import-test {
  .mixin;
  width: 10px;
  height: @a + 10%;
}

and expects

@import "import-test-d.css";

@import url(http://fonts.googleapis.com/css?family=Open+Sans);
#import {
  color: red;
}
.mixin {
  height: 10px;
  color: red;
}
#import-test {
  height: 10px;
  color: red;
  width: 10px;
  height: 30%;
}

which contains the Google Fonts import still.
I haven't tested these myself but assume it passes.

PS: This Google Fonts import is the only part not passing in my open source lesscss4j library.
All other compatibility tests are passing now.

So I'm really anxious to solve this last issue before releasing it. Hope somebody can help.

Thank you maranomynet for the great workaround for Google Web Fonts in LESS (I was having trouble using @import in LESS release 1.1.3). I agree that LESS handled this part of the syntax in an unfortunate way.

I even got more confused now.

I created a simple web project and added the below code to the head section:

<link rel="stylesheet/less" type="text/css" href="/less/google.less">
<link rel="stylesheet/less" type="text/css" href="/bootstrap/bootstrap.less">
<script src="/js/less-1.1.4.js" type="text/javascript"></script>

The compilation of Twitter Bootstrap is working but the google.less is not.
This google.less only contains the below line copied from the LESS compatibility test import.less

@import url(http://fonts.googleapis.com/css?family=Open+Sans);

The error I receive in the browser is:

Couldn't load http://localhost:8888/less/http://fonts.googleapis.com/css?family=Open+Sans (404)
http://localhost:8888/less/google.less

Now I really start wondering about the import.less compatibility test....

add &.css before close url import

from
@import url(http://fonts.googleapis.com/css?family=Open+Sans);

to
@import url(http://fonts.googleapis.com/css?family=Open+Sans&css);

I had a similar problem, so in case this helps anyone: I was trying to import multiple google fonts separated by '|':
@import url(http://fonts.googleapis.com/css?family=Inconsolata|Cantarell|Architects|Daughter&.css);
which would give an error " missing closing ) for url() "

Error was resolved by wrapping the URL in quotes (note: the &.css still must be at the end, otherwise the 404 import error occurred). All the fonts are also loaded successfully:
@import url("http://fonts.googleapis.com/css?family=Ubuntu+Mono|Cantarell|Architects|Daughter&.css");

good tips enoex :D thank !!!!

Err, it's difficult to see why this issue has been closed. Users have found an incredibly dodgy hack around it, one which could break if Google decides to attach a meaning to &.css; this needs fixing in lessc. Some method should exist to force a @import to be taken literally.

I agree. any suggestions?

@import css url(...);

is a possibility. It would also allow you to force Less importing with a .css extension.

That syntax looks fine (I'm not the one who writes the parser, so I don't know how well it fits).

My only concern is other less compilers. The code I had trouble with worked fine for the developers who wrote it, probably because their less compiler doesn't even do compile-time @import. So even if this was fixed in lessc, I would probably keep using the "&.css" hack. There's nothing you can do about that though.

Anyone found a fix?

I found that appending "&.css" and wrapping the URL in quotes only solves the compilation issues - the fonts i'm specifying still aren't being rendered....

re-opened as it sounds like it is still an issue - right?

a simple fix would be to not append anything to the url if it contains params (e.g. ?family=x)

@ntoft I can't reproduce the error any more.. using lessc.. what exactly is the problem remaining?

Thanks for following up.

I'm using the "append &.css" approach and it is working now (part user error :-/ ) Was simply curious if there was a better method. However, it does seem to be working so feel free to close it.

thanks.

it would be nice if it worked without the append .css approach.. so do you have an example of that?

Think I mis-understood... the problem is the css is being imported when you don't want it to be imported.

Maybe in 1.4.0 @import's should be left alone and @include should always be included

moving discussion to a single issue #1185

Just needed to escape characters like this, @import url(https\:\/\/fonts.googleapis.com\/css?family=Orbitron&.css);

@jas-naz The proper and more readable way is:

@import (css) url(https://fonts.googleapis.com/css?family=Orbitron);

For more see http://lesscss.org/features/#import-atrules-feature-import-options.

Hello, another hack to achieve this is to add "#css" at the end of the url, like this :

@import url('https://fonts.googleapis.com/css?family=Paytone+One#css');

@TyrionGraphiste

Bad idea. In recent versions Less will actually process this file (instead of leaving import as is).
That why (css) in front of it is obligatory. (In earlier versions it was just the wrong behaviour where the compiler decided by "some" css string in the url instead of the proper extension missing in this particular case).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

awebdev picture awebdev  ·  4Comments

briandipalma picture briandipalma  ·  6Comments

BrianMulhall picture BrianMulhall  ·  4Comments

Oskariok picture Oskariok  ·  6Comments

bassjobsen picture bassjobsen  ·  6Comments