Skip to content
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

Support importing from npm packages #1972

Closed
wants to merge 1 commit into from
Closed

Support importing from npm packages #1972

wants to merge 1 commit into from

Conversation

ForbesLindesay
Copy link
Contributor

This adds support for importing from npm packages installed to node_modules. For example, having installed twbs via npm you can import the entirety of bootstrap using:

@import (npm) "twbs";

or a specific file via:

@import (npm) "twbs/less/code";

The syntax and resolution algorithm will be familiar to most node.js developers, and is becoming increasingly popular on the client side too with libraries such as browserify.

closes #1965

@ForbesLindesay
Copy link
Contributor Author

I'm not sure how to go about adding tests to this, but all existing tests seem to pass locally.

@dignifiedquire
Copy link

Yes, please this is awesome!

@juliangruber
Copy link

+1

@drudge
Copy link

drudge commented Apr 14, 2014

This would be nice! +1

@englercj
Copy link

As cool as this is, it opens a can of worms by setting the precedent of the library supporting package managers. Does it also have to support bower, and whatever other manager people can think of?

@juliangruber
Copy link

npm is the package manager you already use to get less, so it kinda makes sense to do that one

@englercj
Copy link

@juliangruber It is also on bower, nuget, ruby gems, and others as well.

@jonschlinkert
Copy link
Contributor

As cool as this is, it opens a can of worms by setting the precedent of the library supporting package managers.

Given that less.js is already installed via npm, I'm not sure how that conclusion can be drawn.

It is also on bower, nuget, ruby gems, and others as well.

Actually, besides bower, this project does not directly support the others. We're glad they exist, but they are community maintained.

@englercj
Copy link

Given that less.js is already installed via npm, I'm not sure how that conclusion can be drawn.

Being published on a package manager, and supporting extra api for that manager are very different. Just wanted to point out the possible slippery slope. Thanks all!

@SomMeri
Copy link
Member

SomMeri commented Apr 15, 2014

Could custom importers be supported as plugins? Anyone could then add any less source type as he likes, be it package manager, database, key/value store, something that generates less on the fly etc. Custom importer does not have to need special import command directives, it can be simply given url string and parse it.

At least when it comes to less4j, people seemed to be interested in such customizations.

@seven-phases-max
Copy link
Member

+1 for doing this via plugin.

@jonschlinkert
Copy link
Contributor

agreed, plugins are the way to go!

@englercj
Copy link

👍 for a plugin, I think that makes the most sense to me!

@donaldpipowitch
Copy link

+1 I absolutely need this. Plugin would be fine, as it would allow us to do the same for (bower). But this should definitely be an officially supported plugin.

@andreypopp
Copy link

Can we combine (npm) import modifier with (reference)? I think this is desirable.


return info;
},
paths: process.env.NODE_PATH ? process.env.NODE_PATH.split(':') : []

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think on Windows separator is ;.

@jonschlinkert
Copy link
Contributor

Can we combine (npm) import modifier with (reference)? I think this is desirable.

these are completely separate concepts, I don't think combining them by default is a good idea. But you're underscoring the fact that one might need to either import or reference a npm stylesheet. I'm not sure how that would work.

@andreypopp
Copy link

Yeah, sorry, I didn't mean we should combine them by default.

@lukeapage
Copy link
Member

They can be combined e.g. (npm, reference) when required.

I like the idea but I agree it would be better as a plugin.
Also instead of adding a language keyword id rather it be part of the filename e.g npm://repo/path

I can look at adapting this pull request after 2 if you don't want to help development of the API to allow this.

@matthew-dean
Copy link
Member

As others have said: in general, I think the smartest design philosophy is that the core parsing library be one that can run in any JavaScript management with any package manager (or, as it has been historically, in the browser). But, as a plugin, it makes sense to extend specific environments. And it's another opportunity to build a more robust plugin library.

@lukeapage Is there a guide / process in mind for how people would submit pull requests for plugins?

@ForbesLindesay
Copy link
Contributor Author

Does anyone have any data on how often less is used in different environments? We could build it for node.js and have it work in all the browsers via browserify. Depends if there are lots of people using this in non-node.js & non-browser environments?

@matthew-dean
Copy link
Member

I don't think we have such data. And something else to consider: in some cases, the browser build is used in non-browser, non-Node environments because it's been more "environment-agnostic" than the Node version.

@lukeapage
Copy link
Member

Its seperation of concerns as much as anything. Browserify wouldn't work..
we build a version to run in eveeyones web page, not a version per less
compilation.

@lukeapage
Copy link
Member

P.s. re a guide, no I'm still writing a plugin api on the 2 branch. Anyone
can help!

@ForbesLindesay
Copy link
Contributor Author

The browserified version should work in any JavaScript environment, browser/node/rhino/whatever else. The separation of concerns is not cleanly done here. The coupling between all the different parts of the less parser/compiler is really tight. It would be nice to get clean separation into lexer, parser, code-generator, and file-system (i.e. all IO operations, including web requests).

It would require almost a total re-write, but I think would pay off in the long term. This probably isn't the right place for that discussion. I'd be happy to talk more about it, and possibly even do the initial refactoring work, but it's not directly related to adding support for importing less from npm, which I believe is a common enough use case that we should be looking to support it.

@lukeapage
Copy link
Member

@ForbesLindesay see #1902

I am trying to indicate what we are working towards.

As you can see it uses browserify. I don't see how using browserify would allow us to build a browser version that can fetch files from npm and even if that was possible I don't think it would be wanted for the core browser version.

@ForbesLindesay
Copy link
Contributor Author

#1902 looks exciting. I'll look into that as it seems more relevant.

You could use browserify to load files from npm if you used the asynchronous version of resolve and then implemented fs.stat and fs.readFile so that they made web-requests rather than attempting to read from the file system. This may not be a good idea though. I would probably be more inclined to only support reading from npm when used via node.js. I still think the feature belongs in core though. You could simply have the path resolution be doen in the node environment file: https://github.com/less/less.js/blob/2_0_0/lib/less/environment/node.js

@@ -82,6 +83,27 @@ less.Parser = function Parser(env) {
callback(e, root, importedPreviously, fullPath);
};

if (importOptions.npm) {
path = resolveNpmFile(path.replace(/\.less$/, ''), {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ForbesLindesay mind removing the regex/replace here? thx

@matthew-dean
Copy link
Member

It would be nice to get clean separation into lexer, parser, code-generator, and file-system

YES!

@jonschlinkert
Copy link
Contributor

It would be nice to get clean separation into lexer, parser, code-generator, and file-system

Agreed! I'm not intending to merge this yet, in case that's the concern. For now, while this PR is outstanding, I just want to continue doing testing directly from @ForbesLindesay's fork.

@ForbesLindesay
Copy link
Contributor Author

The replacement is necessary because less adds the extension if the user did not provide an extension. This means that @import (npm) twbs becomes @import (npm) twbs.less which would not work. Ideally we would not add .less in the first place for (npm)

@jonschlinkert
Copy link
Contributor

The replacement is necessary because less adds the extension if the user did not provide an extension.

It's not though. Less does not require a file extension for less files. Regardless, I've been testing extensively with, without, and every way in between.

This means that @import (npm) twbs becomes @import (npm) twbs.less which would not work.

It would if the repo's name is twbs.less.

Ideally we would not add .less in the first place for (npm)

This is just opinion, so let's drop the regex and leave that to users.

@matthew-dean
Copy link
Member

I think he's saying that the lib by default requests twbs.less if you only specify just twbs. Which would be true when importing files. Not sure about the npm context.

@jonschlinkert
Copy link
Contributor

I think he's saying that the lib by default requests twbs.less if you only specify just twbs. Which would be true when importing files. Not sure about the npm context.

currently the regex does a replace on the filepath/module name that's passed in, e.g. path.replace(/\.less$/, ''), which means that if the repo name happens to have .less in the name, it won't work. But if the regex is dropped, it works in every scenario, for both local and npm files - with and without .less. Again, tried and tested.

@lukeapage
Copy link
Member

This is now added as a plugin

@lukeapage lukeapage closed this Oct 11, 2014
@donaldpipowitch
Copy link

Awesome!

@lukeapage
Copy link
Member

Note: requires v2 branch..

Though am thinking of merging that to master soon..

@matthew-dean
Copy link
Member

Though am thinking of merging that to master soon..

Will there be a published API for comments?

@lukeapage
Copy link
Member

Which part of the api? I wrote the plugins doc on the plugins issue. I'll
see if I can branch less docs tomorrow - there are no changes for consumers
other than removing some ways of using less - every one is recommended to
use less.render
As I said before, if you want to understand the why's, the best place to
look is the v2 branch.

@luobotang
Copy link

GOOD!!!
less-plugin-npm-import is what I'm looking for!
Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for importing from npm packages: @import (npm) ...