mrcrowl / vscode-easy-less

Easy LESS extension for Visual Studio Code
MIT License
67 stars 23 forks source link

Save multiple main files #20

Closed DifficultNick closed 7 years ago

DifficultNick commented 7 years ago

In this case: // main: file1.less, main: file2.less where file2.less contains @import "file1.css" I think it will be nice to wait while file1.css wil be saved before compile file2.less

mrcrowl commented 7 years ago

@DifficultNick I'm not sure I understand the use case in which a less file would @import a .css file. This isn't something I've come across before.

Can you provide an example of a situation in which you'd like to use this?

DifficultNick commented 7 years ago

Oh, sorry, i was wrong. Of course less, but not css. I meant following: i need to combine a lot of small less files into one big less file. I do it this way (combine.less):

// out: big.less
@import (inline) small_1.less
@import (inline) small_2.less

Also I need to compile a file (style.less) like this:

// out: true
@import "variables";
@import "big.less"

So when i compile a small.less with this settings: // main: combine.less, style.less

style.css always contains data of previous big.less version.

mrcrowl commented 7 years ago

Okay, just to confirm, this is how I understand your situation:

easy-less issue 20

... and when you save small_2.less you want combine.less to be output big.less before style.less imports it and outputs style.css?

DifficultNick commented 7 years ago

yes, this now works amazing! thank you!

DifficultNick commented 7 years ago

It seems this problem became actual again. Of course I can solve it by double saving (thanks to your latest release), but it would be very nice to make it in more propper way =)

yume-chan commented 7 years ago

Hi @DifficultNick,

Sorry for the inconvenience, the last update is contributed by me.

May I know one thing that, is your "big.less" opened in editor? In my test it works if I don't have "big.less" opened.

DifficultNick commented 7 years ago

It doesn't matter if it opened or not (both variants don't work for me). Here is the examle: https://drive.google.com/file/d/0B4BkdEiPDnKXSHZTSVhxZExRQWM/view?usp=sharing

By saving small1.less I suppose style.css to be the output of all compiled files, but combine.less imports small1.less before it was changed.

mrcrowl commented 7 years ago

Tricky. I think this is related to the save event moving to onWillSaveTextDocument. Will need to investigate further.

yume-chan commented 7 years ago

@DifficultNick Thanks for the repro, I found the problem now.

To support compiling unchanged files I had moved to onWillSaveTextDocument event to detect saving, but the event fires before the file is actually written to disk, so I need to help lessc find the correct imports using a plugin.

The problem is not multiple main files, but @import (inline), a minimal repro should be:

a.less:

// main: b.less

a { color: red; }

b.less

// out: c.less

@import (inline) "a.less";

For normal imports lessc will pass the file to my plugin, and I can replace it with the unsaved content I read from vscode editor, but for inline imports, lessc just read the file from disk and emit it to the output.

I tried to delay my plugin in lessc plugin system a bit, then the problem is gone, but I don't understand why, technically it doesn't make any change. I will try to find another better resolution.

mrcrowl commented 7 years ago

@CnSimonChan thanks for the minimal repro. Very good :) Did you have any success with a resolution?

yume-chan commented 7 years ago

@mrcrowl In my test if I change pluginManager.addPreProcessor(new LessDocumentResolver()); to pluginManager.addPreProcessor(new LessDocumentResolver(), 1000);, the problem is gone.

It's very strange because the argument 1000 only changed the order of plugins executes, but they should still run before files are saved.

Can you verify it for me?

mrcrowl commented 7 years ago

Been looking at this further. The problem is that a.less is never accessed by the LessDocumentResolverPlugin.ts, therefore the inlining still uses the saved version.

I think a reasonable solution is to only trigger less compile from the willSaveEvent when the document is clean (!isDirty). Otherwise stick with the didSaveEvent.

    // automatically compile less on save
    const willSaveEvent = vscode.workspace.onWillSaveTextDocument(e =>
    {
        if (e.document.fileName.endsWith(LESS_EXT) && !e.document.isDirty)
        {
            new CompileLessCommand(e.document, lessDiagnosticCollection).execute()
        }
    });

    // automatically compile less on save
    const didSaveEvent = vscode.workspace.onDidSaveTextDocument(document =>
    {
        if (document.fileName.endsWith(LESS_EXT))
        {
            new CompileLessCommand(document, lessDiagnosticCollection).execute()
        }
    });

By keeping your LessDocumentResolverPlugin in place, this also works with unsaved files.

mrcrowl commented 7 years ago

@DifficultNick Fix has been released in easy-less v1.4.5