-
-
Notifications
You must be signed in to change notification settings - Fork 250
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
Recompile less when changing imports #189
Comments
Id love to see this feature, would be a massive time saver. |
This is really important for us as well. We've had to use other methods to work with LESS as changes made to our LESS file (included at the end of Bootstrap.less) are not reflected unless you also save Bootstrap.less. |
Implementing this would require that WE scan your entire project for LESS files every time you save, to find and update referencing files. I'd like to write a file dependency cache which will cache the reference information and refresh itself on save and on project reload to avoid this perf hit. (this would also help perf for bundle updates) I'll probably write that soon. |
Such a cache exist and is public. I forgot the name... But it doesn't walk up the chain |
In what assembly? |
Probably in Web.Extensions |
So far, I found |
Yes, that's it |
No wait, it's specific to LESS so it's probably not in the CSS assembly |
But still, it only walks down the import chain. Not up |
|
The interface is probably public. Then do an [Import] if I remember correctly |
There is no interface |
I had in mind a wrapper around |
I'll ask the developer when I get back to the office Monday then |
Great to see that you are considering how to implement this. I should add that it would be awesome to have the less variables from the parent document available in the child documents as well. I know it works when compiling, but I am still getting a less error saying that the variable is undefined. Thank you for the good work! |
@madebysoren That should work already. Note that I'll be rather busy for the next few weeks, so I probably won't implement this before December. |
Maybe I am just using it the wrong way. I'm still pretty new to this. I have the following structure: general.less:
another.less
This would give me the following error: "LESS: variable @red is undefined". And btw December is perfect. No stress. I'm just delighted that you guys are actually making this stuff. |
@madebysoren, apparently you need to (re)define |
You're using it backwards from the way variables are usually used: variables.less: @red: #f5406b; mypage.less: @import "variables";
.someclass {
background: @red;
} Supporting that approach would require me to hook my dependency logic into |
Of course. That makes much more sense. Thank you. |
@madskristensen, can you make this logic extensible for the next VS update? This problem is especially annoying in Bootstrap, which has about a dozen LESS files that are imported by |
@am11 He doesn't need to; his approach is perfectly fine. |
@SLaks, indeed. I didn't thought about the variable scope and that it doesn't take all the variables in the scope into consideration. Only "walking down" as Mads put it. @madskristensen, any word on the existing scope-aware cache? |
Since any .less file can be referenced by multiple parent .less files, walking up the import chain isn't really a good idea. Just because bootstrap has chosen this approach doesn't mean that everyone else should |
I'd love to see this taken care of, even with a perf-hit...a php\sublime guy here who's using VS2013 keeps WinLess open in the background and shuts off WebEssentials since it does do the recompile on _import save. ...I'm considering the same thing because it's so inconvenient |
Walking up the import chain is something that CodeKit implements, so it's been painful for our Mac guy to use VS, since it doesn't provide that. If your tools don't work with the most popular project using the framework, I'd suggest it may be worth looking into getting that working, even if it's difficult to do performantly. When we were investigating less and trying to decide how to structure our code, we looked to bootstrap as an example, and I'd guess we're not alone in that. I totally understand that what I'm asking may be a very large undertaking, but I hope my feedback is useful. As an alternative, when we used Sublime, the less compiler we used could be setup to compile a specific file every time any less file in the project was saved, which helped. I'll have to see if WinLess will work for us, instead of Web Essentials, for the time being, thanks @stevescotthome :-) |
We've had our front end guys using node and less-watch package, however there are differences between the way it compiles paths for images and Web Essentials. Basically, this remains a huge pain point, a simple setting with regard to recompiling a specific file on save (so we can point it at bootstrap) is, well, shortsighted but it would solve all the issues we have. |
here's the API: IDocumentImportManager manager = Microsoft.CSS.Editor.CssDocumentHelpers.DocumentImportManager;
IEnumerable<IDocumentReference> imports = manager.GetImports(either ITextBuffer or StyleSheet);
manager.ImportsChanged += OnImportsChanged; |
@madskristensen, that's great! Which means; we can maintain a simple tree in // using Microsoft.CSS.Editor.CssDocumentHelpers;
IDocumentImportManager manager = DocumentImportManager;
IEnumerable<IDocumentReference> imports = manager.GetImports(fileSaved);
foreach(var document in imports)
{
foreach(var lessFilePath in _importTree.FindParents(document.SourceUri.AbsolutePath))
LessCompiler.Compile(lessFilePath);
...
} Also, we can look into the way to batch-compile within node environment. Then write a JS file on-the-fly and execute |
BTW, I just finished rewriting the margin code; it is now far far smaller. This code would go in a derived version of https://github.com/SLaks/WebEssentials2013/blob/confoxide/EditorExtensions/Compilers/CompilerRunner.cs#L104 to affect all compilations to disk. |
For batch-compile, see #381; this would only touch the |
@SLaks are you ready to send the PR? Perhaps we should wait till the weekend to release 1.7 so we get more time to test all the new code |
No; it doesn't even compile yet. |
Ok |
I still need to finish writing the compiler providers (very simple), rewrite minification as a compilation listener & a save listener consuming MEF-ContentType-exported minifiers, and move the compile-on-build logic to one place. Then comes unit tests for everything. |
@madskristensen, @SLaks, the AncestryManager.cs is a almost ready. I can't figure out how to implement Please take a look whenever its convenient. |
Wouldn't it be sufficient to be able to specify how dependencies are set up, what should trigger a recompile like for example CodeKit does. This feature would include:
This way it's up to the developer to set up dependencies the way he/she wants. For example:
Seems like a simple way of implementing it, plus there's always a big risk of making bad assumptions when walking some kind of dependency chain and deciding the what behavior the develop wants. Storing the config in the project root also makes it easy to check in the configs with the source code making sure that all developers on different machines have the same config for project minification. |
@tidyui, we can certainly maintain a blacklist in settings. Here is the latest version of ancestry maker: // In ProjectHelpers
// Call this on solution load and save it as var ancestryDictionary.
public static Dictionary<string, HashSet<string>> GetAncestory()
{
var ancestry = new Dictionary<string, HashSet<string>>();
var files = new[] { "*.less", "*.sass" }.SelectMany(extension =>
Directory.EnumerateFiles(GetSolutionFolderPath(),
extension,
SearchOption.AllDirectories));
foreach (var file in files)
{
ancestry = UpdateAncestryForSingleDocument(file, ancestry);
}
return ancestry;
}
// We can use it as the event handler onSavng Sass or Less document.
public static Dictionary<string, HashSet<string>> UpdateAncestryForSingleDocument(
string filePath,
Dictionary<string, HashSet<string>> ancestry)
{
var directoryName = Path.GetDirectoryName(filePath);
var paths = new CssItemAggregator<string>(s => s is ImportDirective)
.Crawl(new CssParser().Parse(File.ReadAllText(filePath), false))
.SelectMany(s => s.Split(' ', ','))
.Select(s =>
{
var path = Path.Combine(directoryName, s + Path.GetExtension(filePath));
return Path.GetFullPath(path);
});
// Now paths is IEnumerable<string>.
foreach (var path in paths)
{
var item = ancestry[path] ?? new HashSet<string>();
item.Add(filePath);
ancestry.Add(path, item);
}
return ancestry;
}
// Now compile all files returned by ancestryDictionary[targetLessOrSassFilePath]
// TODO: cache results? Depends on how expensive is CssItemAggregator.Crawl() Before calling |
* Menu item to add file in ignore list. * Needs testing.
* Menu item to add file in ignore list. * Needs testing.
* Menu item to add file in ignore list. * Needs testing.
@SLaks, is BTW, adding a new setting is SUPER easy now! 👍 |
* Menu item to add file in ignore list. * Needs testing.
* Menu item to add file in ignore list. * Needs testing.
* Menu item to add file in ignore list. * Needs testing.
@madskristensen, this should be closed with #589. |
Feature: Chain compile for LESS and SASS (#189)
It would be really cool if less documents was recompiled whenever changes are made in their "child" documents. So if I import another less document and make changes to this, the "parent" document should be recompiled as well, so I don't need to open that one and make a change to save it again and force a recompilation.
Thanks for doing an awesome good job on this!
The text was updated successfully, but these errors were encountered: