assemble / assemble-less

Grunt task for compiling LESS to CSS. This task does for less what Assemble does for HTML, making it much easier to modularize and reduce repetition in stylesheets.

Home Page:http://github.com/assemble/assemble/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Imports reference broken

AlistairB opened this issue · comments

Hi,

I updated from (i think) .5 to .7 and imports > reference stopped working

        less: {
            prod: {
                options: {
                    paths: styleLocation,
                    imports: {
                        reference: ["mixins.less", "variables.less", "images.less"]
                    },
                    syncImport: true
                },
                files: [{
                    expand: true,
                    cwd: styleLocation,
                    src: ["**/*.less", "!container.less", "!variables.less", "!mixins.less", "!**/external/*.less"],
                    dest: styleLocation + "/temp",
                    ext: ".css"
                }]
            }
        },

I have changed imports > less to imports > reference. But it wont compile because it can't find mixins in mixins.less.

Any ideas? Any way I can get more information on what is happening?

So it's not just me doing something wrong. :) Confirmed.

Strange, sorry I don't know how I missed this issue. wasn't intentional. I'll look into it!

I've been trying to debug this, but it's working fine for me. I have a hunch that it has something to do with self-referencing files. Have you both tried using the feature with just a couple of files? that will help me know where to focus

That's weird then. I just did some testing and reduced my case down to just two minimal files. One for reference use containing a single mixin definition. And one 'regular' src file. No import statements in either file.

less: {
    ref: {
        options: {
            imports: {
                reference : ['<%=tcBase%>/css/lib/reference/test.less']
            }
        }
        ,src  : '<%=tcBase%>/css/lib/test.less'
        ,dest: '<%=destCss%>/ref.css'
    }
}

But Less doesn't know about the mixin and aborts. I tried it with relative and absolute paths.
Did you already try to debug this with a assemble-less installed via npm? Not that it makes much sense. But maybe there's some subtle difference.

Aha! just wrote some garbage in the 'reference' file, but Less did not complain about that at all. Just about the missing mixing. Apparently the file is not being read at all.

It might be that the templates aren't being expanded. Yeah, I just pulled it down and started playing around with it from scratch. I also installed Bootstrap using bower, then I setup a task to compile each less file to a separate CSS file using imports.reference. It works fine until I get to utilities. I'm doing actual debugging now, but I have a cold so I'm not sure if I'll get it worked out today or not. sorry for the mess.

Haha, well you did warn me that assemble-less is experimental in nature.

So you are reproducing the problem?

For me there's no urgency to get this fixed. If you can debug it sometime next week that's fine with me. Get well soon!

Yes, I did in fact reproduce the issue. one problem is that files added to any of the imports are not getting removed from the actual src files, I was counting on globbing patterns to help there. but it's just error prone. I've already completely reworked the logic and it's working great, it's a lot cleaner:

// Probably the biggest hit on task execution time.
var parseImports = function(options) {
  var directives = _.pairs(options.imports);
  var statement = '';

  directives.forEach(function(pair) {
    pair[1].map(function(filepath) {

      // Don't add a circular reference.
      if (!!~srcFile.search(filepath)) {
        return;
      }
      statement += '@import (' + pair[0] + ') "' + filepath + '";\n';
    });
  });
  return statement;
};

srcCode += parseImports(options);
srcCode += file.readFileSync(srcFile);

Now I'm refactoring how metadata works so that it doesn't mutate upstream values and cause unexpected issues in other grunt tasks! Yikes! I'm probably going to have to implement more rigid conventions around how data is defined. ... huh, actually I completely forgot that I created this lib until just now lol. I can use this to solve it.

I'll let you know when I have something...

and thank you! I appreciate it!

See: b8d41f6

This is the v0.8.0 branch, you'll have to pull it down with git or download manually to test it. let me know if it works for you. If there are problems unrelated to this one, please open new tickets for those.

also, if you set debug: true in the options, the task will generate some before/after files (.less and .json) into a tmp directory, so you can inspect what's happening.

@AlistairB / @MarcDiethelm ping. any feedback on v0.8.0? Just do this to install:

git clone -b "v0.8.0" https://github.com/assemble/assemble-less.git && cd assemble-less && npm i

:) Today is the first day that I actually have time to test it. So I just opened this issue again to check out your instructions for testing and I find your new comment...

It's working! Albeit there's another issue:

  • The path is not being expanded (globbing doesn't work)
 paths: ['<%=assetBase%>/css/lib/reference']
,imports: {
    reference : ['*.less'] // no worky
}

FYI: I initially constructed the path myself:

reference: [path.relative(srcAbsolute, '<%=assetBase%>/css/lib/reference')+'/helpers.less']

That's probably quite a bit more efficient than using paths, especially for big projects that specify a lot of imports? What's your take on this?

Yeah I think I mentioned in the commit messages that I intentionally took that out, because it increases build time and it's just brittle. Even if you only reference files one folder deep (e.g. *.less) every loop will scan every one of those files. I can see it being useful though, I guess I can look at re-implementing it if necessary

Mmh yes, for me it's a prerequisite to using it. I don't want users to have to configure Grunt, instead they can use folders to drop their assets into, like the reference folder in my example. Of course globbing can be abused (not just in this instance), but most users will never actually need to use @import (reference) anyway. Those who do should know what they're doing.

those who do should know what they're doing.

Well, let me clarify. The additional logic required for this feature slows down the build appreciably when any patterns are used. period. however, since I didn't do any actual benchmarking and I don't have any numbers to report, the amount is still conjecture. So I'll try re-adding it and see how it works out.

One more thing. The problem exponentially compounds when you add paths. for every path you add to the paths option, reference has another pattern to expand. I personally think it would be better to NOT use paths with the imports options, and instead require the full paths for each pattern. Templates could still be used though. thoughts?

I personally think it would be better to NOT use paths with the imports options

I was actually surprised that it did work and paths was being applied to imports. After what you just explained using reference, patterns and paths together certainly seems like a potential way to shoot yourself in the foot.

However to an extent (which I don't understand) it surely depends on how its being used. Adding some stern warnings in the docs might be the thing to do here. Because it's also nice to be able to use this power if someone needs it.

I really don't understand enough about the internals of assemble-less and the relationship between it and less to make any sound judgements, I'm afraid.

But I'll use my use case as an example here. I'm 'only' looking for files to use with reference in one folder, but I can't know the file names. I experimented with using paths because it saved me from constructing a relative path from src (a single file containing regular @imports statements constructed in a previous task) to the reference folder). However as I noted in my previous comment and don't really need to use paths for this. Templates however, yes please.

Using reference with an absolute path didn't work for me. Bug?
Not sure about this, but maybe we could use a base option, that if supplied is used to create the relative paths for less to import.

Using reference with an absolute path didn't work for me. Bug?

Currently it's tied to paths. So remove the paths option first, then try it.

maybe we could use a base option, that if supplied is used to create the relative paths for less to import.

this can be done with lodash templates. e.g.

base: 'foo'
less: {
  options: {
    imports: {
      reference: ['<%= base %>/mixins.less']
    }
  }
}

Okay, I need to think about this a little bit. maybe we should create an example project where each of us adds a config and some example less files, so we can share our practices and see how things can be improved. I have a hunch this can resolve some things tool.

Thanks for all your great help so far! Re: example project... Sure let's do that. My actual 'real' use case is something that I have not started implementing yet. Which would be 'bundling' some frontend 'modules/components' together (JS, CSS, maybe also markup/templates) to be used as assets for discrete sections of a website. That's what I think I'll eventually be using import (reference) for.

It probably best if you set up a repo and maybe add me as a collaborator. Or, if you prefer I can do it.

Sure, I'll set something up. Might be tomorrow, I'll let you know when I have something

@jonschlinkert: My turn to remind you.
I'm preparing a release of dependent software. Btw, are you planning a bump to less 1.7? You already did.

I ran into this issue today and I'm a bit surprised that it has been fixed already for almost a year in the 0.8 branch but is still broken in the version that npm installs. Would be nice to get it working from there too.