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.
http://github.com/assemble/assemble/
MIT License
66 stars 20 forks source link

Imports reference broken #22

Open AlistairB opened 10 years ago

AlistairB commented 10 years ago

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?

MarcDiethelm commented 10 years ago

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

jonschlinkert commented 10 years ago

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

jonschlinkert commented 10 years ago

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

MarcDiethelm commented 10 years ago

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.

MarcDiethelm commented 10 years ago

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.

jonschlinkert commented 10 years ago

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.

MarcDiethelm commented 10 years ago

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!

jonschlinkert commented 10 years ago

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!

jonschlinkert commented 10 years ago

See: https://github.com/assemble/assemble-less/commit/b8d41f60615fa28e3288fad6d7f191707d255e3f

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.

jonschlinkert commented 10 years ago

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.

jonschlinkert commented 10 years ago

@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
MarcDiethelm commented 10 years ago

:) 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:

 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?

jonschlinkert commented 10 years ago

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

MarcDiethelm commented 10 years ago

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.

jonschlinkert commented 10 years ago

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?

MarcDiethelm commented 10 years ago

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.

jonschlinkert commented 10 years ago

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.

MarcDiethelm commented 10 years ago

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.

jonschlinkert commented 10 years ago

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

MarcDiethelm commented 10 years ago

@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.

dirkjanm commented 9 years ago

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.