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 protocol @imports #85

Closed
XhmikosR opened this issue Mar 22, 2013 · 33 comments
Closed

Support protocol @imports #85

XhmikosR opened this issue Mar 22, 2013 · 33 comments
Assignees
Milestone

Comments

@XhmikosR
Copy link
Contributor

Example:

@import url(http://weloveiconfonts.com/api/?family=zocial);
@GoalSmashers
Copy link
Contributor

As @abarre commented in #85 - we should consider:

  • handling relative URLs
  • overriding request options because of proxy, authentification, host header...

@abarre
Copy link
Contributor

abarre commented Jul 19, 2013

Regarding this issue, I'm not sure that it's a real good idea.
You might end up with an outdated css if the external css is updated afterwards. It's a bad side effect.

@GoalSmashers
Copy link
Contributor

Let's see if anyone asks for it. Maybe there's no real "business" value behind it.

@XhmikosR
Copy link
Contributor Author

I'm not sure I follow... Wouldn't it be simpler to just keep the import at the beginning instead of going all through the trouble to download the css etc?

@abarre
Copy link
Contributor

abarre commented Jul 19, 2013

@XhmikosR, it's also my opinion.

@GoalSmashers
Copy link
Contributor

Sure, let's see if there's any interest in it.

@terinjokes
Copy link

I officially register interest in such feature.

@GoalSmashers
Copy link
Contributor

@terinjokes can you share your use case if it's any different from the example on top?

@terinjokes
Copy link

Have a tool that creates static versions of webpages by inlining resources. Right now I'm combing though CSS with parserlib, reconstructing the stylesheet and inlining the resources as I come to them. Because this doesn't minify the CSS, I then run the reconstructed stylesheet through clean-css.

Seems a bit wasteful to parse the stylesheet twice.

If you don't want to handle setting up the fetches, I'm happy to take a callback.

@GoalSmashers
Copy link
Contributor

@terinjokes Thanks for your use case!

Since @abarre suggested we should expose an ability to override request properties (in case of proxies, authentication, etc) it makes me wonder if it's doable via CLI or should we make it the lib option only.

A timeout option may be enough for CLI.

@GoalSmashers
Copy link
Contributor

Since fetching external data will be asynchronous and clean-css is synchronous, here's an idea how to handle it.

  1. We add an optional callback to minify method:
new CleanCSS().minify(source, function(clenCSSInstance, minified) {
...
});
  1. Output debug info to stderr every time external URL is processed.
  2. Makes sure URL resolving is recursive.
  3. If callback not given add warnings on every external URL found.
  4. Still support synchronous mode the same way as we do now.

CLI will have a timeout option only. Overriding any http.get / https.get option will be possible when using the library directly.

@terinjokes
Copy link

Sounds like a good start from this end, I'm already using the library.

@GoalSmashers
Copy link
Contributor

Great! I should have some spare time to push it forward in the coming days.

GoalSmashers pushed a commit that referenced this issue Dec 10, 2013
* Rewrote inliner to process data asynchronously.
* Supports 2xx responses, redirects, errors, and timeouts.
* Supports cyclical references.
* Supports protocol-less requests too (defaults to HTTP).
* Supports overriding request options - see http://nodejs.org/api/http.html#http_http_request_options_callback
* Supports timeout in binary via --timeout / -t switches.
@GoalSmashers
Copy link
Contributor

@terinjokes @abarre if you would like to give it a try then a preliminary but fully functional version is on f-imports-85 branch.

No changes are necessary when running via CLI.
When minifying via a library make sure to use a callback as fetching all data from remote hosts is asynchronous, i.e.:

new CleanCSS().minify(source, function(errors, minified) {
  ...
});

One can also override requests' options via:

var options = {
  inliner: {
    request: { ... }
  }
};
new CleanCSS(options).minify(source, function(errors, minified) {
  ...
});

@terinjokes
Copy link

Overall, it looks good, but some feedback before we go any farther.

If a callback is provided to minify it automatically resolves external resources as this.options.processImport defaults to true. That's a breaking API change because of this next point.

When this.options.processImport is true, the callback could be called on a future tick (via inlineRemoteResource). Previously, and when this option is false, the callback is called on the same tick. This releases Zalgo. 😦

@GoalSmashers
Copy link
Contributor

@terinjokes Thanks for the feedback - the thing is callback handling is not finished yet as minify() will run the very same way as it runs now so API will be backwards compatible.

Thanks for pointing current/next tick thing. Will make sure it's always deferred.

@terinjokes
Copy link

You can't be API backwards compatible and change when the callback gets called. I think that's as much as part of the API as the method signatures.

@GoalSmashers
Copy link
Contributor

But there is no callback in the current version of clean-css. It will be added in 2.1.

@terinjokes
Copy link

D'oh! It was already there in the commit added above, so I assumed it was already on master.

@GoalSmashers
Copy link
Contributor

No worries - this branch adds callbacks too!

GoalSmashers pushed a commit that referenced this issue Dec 11, 2013
* Rewrote inliner to process data asynchronously.
* Supports 2xx responses, redirects, errors, and timeouts.
* Supports cyclical references.
* Supports protocol-less requests (defaults to HTTP).
* Supports overriding request options - see http://nodejs.org/api/http.html#http_http_request_options_callback
* Supports timeout in ./bin/cleancss via --timeout / -t switches.
* Supports inlining local resources only without a callback.
* Supports rebasing URLs in remote @imports.
* Always triggers callback asynchronously.
GoalSmashers pushed a commit that referenced this issue Dec 11, 2013
* Rewrote inliner to process data asynchronously.
* Supports 2xx responses, redirects, errors, and timeouts.
* Supports cyclical references.
* Supports protocol-less requests (defaults to HTTP).
* Supports overriding request options - see http://nodejs.org/api/http.html#http_http_request_options_callback
* Supports timeout in ./bin/cleancss via --timeout / -t switches.
* Supports inlining local resources only without a callback.
* Supports rebasing URLs in remote @imports.
* Always triggers a callback asynchronously.
@GoalSmashers
Copy link
Contributor

@terinjokes That should be it. Callback will always be deferred via process.nextTick even when resolving local assets. It is now also possible to resolve local imports when not using a callback and remote URLs (images, fonts, etc) are also rebased.

Not sure if we should go for Output debug info to stderr every time external URL is processed. as in my comment above since I see no real value in it.

What do you think?

@terinjokes
Copy link

I don't think that's really an error, maybe if you had sort of debug mode on.

I'll give it a run this afternoon and let you know.

GoalSmashers pushed a commit that referenced this issue Dec 11, 2013
* Rewrote inliner to process data asynchronously.
* Supports 2xx responses, redirects, errors, and timeouts.
* Supports cyclical references.
* Supports protocol-less requests (defaults to HTTP).
* Supports overriding request options - see http://nodejs.org/api/http.html#http_http_request_options_callback
* Supports timeout in ./bin/cleancss via --timeout / -t switches.
* Supports inlining local resources only without a callback.
* Supports rebasing URLs in remote @imports.
* Always triggers a callback asynchronously.
@GoalSmashers
Copy link
Contributor

@terinjokes Cool, thanks! It indeed makes sense to show that info under debug mode - thanks for the tip.

GoalSmashers pushed a commit that referenced this issue Dec 12, 2013
* Rewrote inliner to process data asynchronously.
* Supports 2xx responses, redirects, errors, and timeouts.
* Supports cyclical references.
* Supports protocol-less requests (defaults to HTTP).
* Supports overriding request options - see http://nodejs.org/api/http.html#http_http_request_options_callback
* Supports timeout in ./bin/cleancss via --timeout / -t switches.
* Supports inlining local resources only without a callback.
* Supports rebasing URLs in remote @imports.
* Always triggers a callback asynchronously.
GoalSmashers pushed a commit that referenced this issue Dec 21, 2013
* Rewrote inliner to process data asynchronously.
* Supports 2xx responses, redirects, errors, and timeouts.
* Supports cyclical references.
* Supports protocol-less requests (defaults to HTTP).
* Supports overriding request options - see http://nodejs.org/api/http.html#http_http_request_options_callback
* Supports timeout in ./bin/cleancss via --timeout / -t switches.
* Supports inlining local resources only without a callback.
* Supports rebasing URLs in remote @imports.
* Always triggers a callback asynchronously.
@GoalSmashers
Copy link
Contributor

@terinjokes Did you have a chance to give it a try? Would like to merge it into master soon.

@terinjokes
Copy link

@GoalSmashers No, been working on other things. going to try it now.

@terinjokes
Copy link

I get an error on inliner.js:43 where data is an object that doesn't have the function "indexOf".

@GoalSmashers
Copy link
Contributor

Thanks for checking! Could you give it a try with --debug flag to find out it fails on a local or remote import (the latter one I presume).
Additionally if it inlines publicly available assets could you share your CSS at dev (at) goalsmashers.com?

On Dec 21, 2013, at 8:41 PM, Terin Stock notifications@github.com wrote:

I get an error on inliner.js:43 where data is an object that doesn't have the function "indexOf".


Reply to this email directly or view it on GitHub.

GoalSmashers pushed a commit that referenced this issue Jan 3, 2014
* Rewrote inliner to process data asynchronously.
* Supports 2xx responses, redirects, errors, and timeouts.
* Supports cyclical references.
* Supports protocol-less requests (defaults to HTTP).
* Supports overriding request options - see http://nodejs.org/api/http.html#http_http_request_options_callback
* Supports timeout in ./bin/cleancss via --timeout / -t switches.
* Supports inlining local resources only without a callback.
* Supports rebasing URLs in remote @imports.
* Always triggers a callback asynchronously.
@GoalSmashers
Copy link
Contributor

@terinjokes The issue you've reported regarding indexOf was very likely fixed in 0dbb54a - would be great if you could give it a try now so we can proceed with this feature.

@terinjokes
Copy link

Works now, however are there any chance to dictate how to inline other, non-css, resources?

Sorry, I didn't see the other comment.

@GoalSmashers
Copy link
Contributor

Don't worry, I'm just happy it works well now!

To inline other resources you can pipe output of clean-css to https://github.com/GoalSmashers/enhance-css - is it an option for you?

GoalSmashers pushed a commit that referenced this issue Jan 6, 2014
* Rewrote inliner to process data asynchronously.
* Supports 2xx responses, redirects, errors, and timeouts.
* Supports cyclical references.
* Supports protocol-less requests (defaults to HTTP).
* Supports overriding request options - see http://nodejs.org/api/http.html#http_http_request_options_callback
* Supports timeout in ./bin/cleancss via --timeout / -t switches.
* Supports inlining local resources only without a callback.
* Supports rebasing URLs in remote @imports.
* Always triggers a callback asynchronously.
GoalSmashers pushed a commit that referenced this issue Jan 6, 2014
* Rewrote inliner to process data asynchronously.
* Supports 2xx responses, redirects, errors, and timeouts.
* Supports cyclical references.
* Supports protocol-less requests (defaults to HTTP).
* Supports overriding request options - see http://nodejs.org/api/http.html#http_http_request_options_callback
* Supports timeout in ./bin/cleancss via --timeout / -t switches.
* Supports inlining local resources only without a callback.
* Supports rebasing URLs in remote @imports.
* Always triggers a callback asynchronously.
GoalSmashers pushed a commit that referenced this issue Jan 6, 2014
* Rewrote inliner to process data asynchronously.
* Supports 2xx responses, redirects, errors, and timeouts.
* Supports cyclical references.
* Supports protocol-less requests (defaults to HTTP).
* Supports overriding request options - see http://nodejs.org/api/http.html#http_http_request_options_callback
* Supports timeout in ./bin/cleancss via --timeout / -t switches.
* Supports inlining local resources only without a callback.
* Supports rebasing URLs in remote @imports.
* Always triggers a callback asynchronously.
@GoalSmashers
Copy link
Contributor

Merged to master to be included in 2.1. Thanks for all the help!

@Slava
Copy link

Slava commented Jan 11, 2014

Hi, I think this is not resolved:

cleanCss = require('clean-css');
inst = new cleanCss;
inst.minify('@import url("//fonts.googleapis.com/css?family=Oleo Script Swash Caps");\n.block2 { font-family: \'Oleo Script Swash Caps\'; }\n');

resolves into

@import url(//fonts.googleapis.com/css?family=Oleo) Script Swash Caps);.block2{font-family:'Oleo Script Swash Caps'}

Which is obviously wrong, look at the "Oleo) Script Swash Caps", why is the closing bracket found after "Oleo"?

@GoalSmashers
Copy link
Contributor

@Slava thanks for bringing that up - have just opened an issue in your name. We will deal with it quickly!

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

No branches or pull requests

5 participants