Shouldn't the assets pipeline rewrite CSS paths?

There are some times where I add some JavaScript libraries as submodules to my project:

git submodule add git://... resources/project_name

cd assets/stylesheets/my_controller

ln -s ../../../resources/project_name/css/project_name.css

cd -

cd assets/images/my_controller

ln -s ../../../resources/project_name/img/sprite.png

While this works great in development mode, I have to create more

symbolic links to make it work under production as well.

Here is why. Under development mode the css is written like this:

.some-class { background: url(sprite.png) } /* relative URL */

Under development this file path is

“/assets/my_controller/project_name.css” while the image is located at “/assets/my_controller/sprite.png”.

When assets:precompile is run, project_name.css no longer exists and

the rule is appended to application.css, but the relative URL is not rewritten to ‘my_controller/sprite.png’ or ‘/assets/my_controller/sprite.png’.

The Grails Resources plugin supports URL rewriting for dealing with

this kind of issue that happens when using an asset pipeline:

http://grails.org/plugin/resources http://grails-plugins.github.com/grails-resources/ (sorry, documentation is not that good, but it works this way, I promiss)

It is not a good experience to have your application working under

development and stopping working under production due to things like this.

Also, I like the idea of grouping my assets in sub-directories.

Shouldn't the Rails assets generator support URL rewriting in CSS

for supporting such an organized tree both in development and production environment out of the box?

Am I missing something?

Best,

Rodrigo.

Yes, it should and it does. Please take a look at the Assets pipeline guide[1].

[1] http://guides.rubyonrails.org/asset_pipeline.html#coding-links-to-assets

As far as I understand this won’t work for files I don’t own, like linked files from external resources in submodule directories.

I don't like the idea of copying the files from external projects

and rewriting them.

Cheers,

Rodrigo.

I’ve had this problem with the asset pipeline as well, even though I don’t use submodules. I agree with Rodrigo that a solution is needed, but I have not yet figured out what the best solution is–that’s why I haven’t yet tried to contribute a solution myself.

To recap, the problem occurs when integrating third party client-side assets that include CSS which has relative paths to images or fonts. A couple of real examples:

// Chosen:

background: url(‘chosen-sprite.png’) right top no-repeat;

// Font-Awesome-More:

@font-face {

font-family: 'FontAwesome';

** src: url(‘…/font/fontawesome-webfont.eot’);**

}

The relative paths work fine in development mode but fail in production when the CSS asset is packaged into application.css, which is at a different directory level than the images and fonts. The “…” case is especially tricky to work around.

If it helps, I think this is a decent set of requirements for any solution we come up with:

  • Vendor’s JS and CSS can be packaged in the minified JS and CSS files for the app, as described in the Rails Guide to the Asset Pipeline, even if the CSS has relative path references to other assets.
  • Each JS library is in a directory named after it. Personally, this only matters to me when a JS library has multiple files (e.g., JS, CSS, and images). For single-file libraries I don’t mind having them sit together in a single directory.
  • Let app developers keep each JS library’s original directory structure when copying it into an app. In other words, something like vendor/chosen, not vendor/javascripts/chosen.js + vendor/stylesheets/chosen.css. Why? So later on, when you download a newer version, you don’t have to go finding where you moved all the files.
  • Don’t require the use of a gem just to use a JavaScript library. Why? Because not all JavaScript libraries have corresponding gems and even when there is one I have low confidence that it will be kept up-to-date. The library and the gem are often written by different people. It’s darn likely that the gem maintainer will not bother updating the gem in a timely manner every time the JS library gets an update.
  • Don’t require app developers to modify the asset references in the JavaScript library or its CSS. That becomes a maintenance headache. E.g., I don’t want to replace background-image: url(bkgnd.png) with background-image: url(<%= asset_path(bkgnd.png) %>) throughout the CSS files in someone else’s library.
  • Keep it simple. :slight_smile: In other words, there might be an easy solution that does not require parsing and rewriting CSS, and would work even in JavaScript libraries that dynamically update CSS background paths. Thanks.

Brian