stealjs / steal-less

A less plugin for StealJS
https://www.npmjs.com/package/steal-less
MIT License
4 stars 2 forks source link

Less @imports and possibly other entities should use System.locate to find location of module. #11

Closed justinbmeyer closed 8 years ago

justinbmeyer commented 8 years ago

https://github.com/stealjs/steal/pull/565 adds a LOCATE() macro where files like less and css can use it to change a url to a path located by System.locate. For example:

@import LOCATE("package/styles.less")

might get converted to:

@import "../node_modules/package/styles.less"

The code for that extension starts here: https://github.com/stealjs/steal/pull/565/files#diff-abc90bebf14055b4190455e9af84a13eR1.

The problem with LESS, LOCATE, and @imports is that the @imported fill will be processed with LESS which doesn't allow the LOCATE hook to run.

The solution to this is to write a less plugin. I explained this better here: https://github.com/less/less.js/issues/2792

The solution is to make a less plugin that gets added when we "render" some less into CSS here: https://github.com/stealjs/steal-less/blob/master/less.js#L43

Plugins are documented here: http://lesscss.org/usage/#plugins

Notice that plugins can be added during render like:

lessEngine.render(load.source, { plugins: [myPlugin] })
   .then(function(output) {
    },
    function(error) {
    });

There are two options how the plugin could work.

Completely take over path resolution.

My guess is that the plugin will look like the npm-file-manager here: https://github.com/less/less-plugin-npm-import/blob/master/lib/npm-file-manager.js#L6

In this case LOCATE wouldn't be needed.

Look for LOCATE ourselves

In this case, it's likely we can use the "visitor" approach and identify when LOCATE is found and rewrite the AST less uses. I think this plugin does this: https://github.com/less/less-plugin-inline-urls/tree/master/lib

Take over loadFile

Similar to the npm-file-manager, we might be able to pre-process the source before it gets to less. Possibly by overwriting loadFile or loadFileSync.

This might be the easiest way of getting it done.

nlundquist commented 8 years ago

Unfortunately the visitor approach doesn't work without monkey patching the LESS ImportVisitor that runs while the tree is still being constructed. Plugin visitors unfortunately aren't run until the tree is complete. Considering that I'll be implementing this as a file manager.

nlundquist commented 8 years ago

Resolved to use new 'locate://' & 'pkg://' path schemes to denote module identifiers to rewrite. These changes will also replace the existing LOCATE & ~ behaviour in steal itself.

nlundquist commented 8 years ago

'locate://' scheme has been implemented. this issue is resolved. a new issue can be opened when we add a 'pkg://' scheme.