2

I have the following directory structure (only showing the relevant bits for illustration purposes):

proj \
     \ Gruntfile.js
     \ package.json
     \ test \ (all my tests are in this folder structure)
     \ app \
           \ index.html
           \ scripts \ (all my scripts are in here)
           \ views \ (all views are in here)
           \ styles \
                    \ style.css
                    \ oldie.css
                    \ print.css
           \ images \
                    \ hires \ (all high resolution images are here)
                    \ lowres \ (all low resolution images are here)

The compass section of my Gruntfile.js file looks like this:

compass: {
    options: {
        require: "susy",
        sassDir: '<%= my.app %>/styles',
        cssDir: '.tmp/styles',
        imagesDir: '<%= my.app %>/images',
        javascriptsDir: '<%= my.app %>/scripts',
        fontsDir: '<%= my.app %>/styles/fonts',
        importPath: 'app/components',
        relativeAssets: true
    },
    dist: {},
    server: {
        options: {
            debugInfo: true
        }
    }
}

The <%= my.app %> resolves to app. My problem is that I am unable to specify that the images in the generated CSS files should have paths that start with images/, and not app/images as they currently do.

If I change imagesDir: '<%= my.app %>/images' to imagesDir: 'images' (or add the latter as a value for the imagesPath option) I get the following error when compass tries to compile:

No files were found in the load path matching "lowres/sprites/*.png". Your current load paths are: /Users/joachimdyndale/Development/myProject/myapp_joachim/proj/images

I've tried adding a config: 'compass.rb' property and have the following in the compass.rb file:

http_images_path = '../images'
http_generated_images_path = '../images'

However, the above has no effect at all.

So my question is then: Is there some way I haven't discovered yet to configure all this so that it both finds the images and writes the correct path to the CSS file, or do I have to change my directory structure so that I move everything in the app folder one level up? I really like the current structure, but I concede this may currently be an edge case Compass simply doesn't support.

I'm using the grunt-contrib-compass grunt plugin.

Joe Dyndale
  • 1,073
  • 1
  • 15
  • 32
  • Does switching relativeAssets to `false` change anything for you? – imjared Jun 04 '13 at 17:02
  • Not quite sure what you mean. Yes, I've tried that some time ago on an almost identical project (which I simply ended up not using the compass task on), but I'll try again at work tomorrow just in case. However, I'm not sure what good it will do, as I have to have relative paths, as the URLs are different between my machine, and our Test, QA and Prod environments. – Joe Dyndale Jun 04 '13 at 21:25
  • So... Acutally, setting relativeAssets to false actually solved the problem. But: WTF?! Setting relativeAssets to false causes Compass to use relative paths when generating the CSS. That's the exact opposite of what the name implies and what the documentation states will happen. I call that a major bug... – Joe Dyndale Jun 05 '13 at 10:55
  • Thanks though. Please feel free to add that as an answer to this question, but then an explanation of why that works would be helpful as well ;) – Joe Dyndale Jun 05 '13 at 10:58

2 Answers2

5

I have the same problem, and solved.

The image-path in url() in the exported css is converted by the compass task and cssmin task. I wonder if the cssmin task's settings cause this problem rather than those of the compass task.

We expect relative paths to dist/styles (not to the cssDir), so relativeAssets should be set to false, and httpImagesPath to '../images'. You will see url(../images/hoge.jpg) in .tmp/styles/*.css when these options are set.

But relative paths exported from the compass task will be converted back to the absolute paths by the cssmin task. To avoid this, we should set the noRebase option to false in the cssmin task's options.

The following settings in Gruntfile.js are working as expected in my project:

compass: {
  options: {
    sassDir: '<%= yeoman.app %>/styles',
    cssDir: '.tmp/styles',
    generatedImagesDir: '.tmp/images/generated',
    imagesDir: '<%= yeoman.app %>/images',
    javascriptsDir: '<%= yeoman.app %>/scripts',
    fontsDir: '<%= yeoman.app %>/styles/fonts',
    importPath: '<%= yeoman.app %>/bower_components',
    httpImagesPath: '../images',
    httpGeneratedImagesPath: '../images/generated',
    httpFontsPath: '/styles/fonts',
    relativeAssets: false,
    assetCacheBuster: false,
    raw: 'Sass::Script::Number.precision = 10\n'
  },
}

cssmin: {
  options: {
    root: '<%= yeoman.app %>',
    noRebase: true
  }
}

Additionally, these settings might prevent the conversion to cache-bustered urls (for example, ../images/hoge.jpg -> ../images/43f78e35.hoge.jpg) in the usemin task. To avoid this, I set the following settings in the usemin task's options:

usemin: {
  html: ['<%= yeoman.dist %>/{,*/}*.html'],
  css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
  options: {
    assetsDirs: ['<%= yeoman.dist %>', '<%= yeoman.dist %>/styles']    // <- add styles directory
  }
}
Joe Dyndale
  • 1,073
  • 1
  • 15
  • 32
0

Just as followup to my comment, the trick should be setting relativeAssets to false. It's always been a weird description but I think the compass documentation explains it better than how it's explained at the docs for grunt-contrib-compass:

Indicates whether the compass helper functions should generate relative urls from the generated css to assets, or absolute urls using the http path for that asset type.

I've re-read your question a few times and it looks like that's possibly what was happening? The assets were relative to the stylesheets, not to your app dir? I'd have to see the before/after but glad it worked for you!

imjared
  • 19,492
  • 4
  • 49
  • 72
  • It was the exact opposite :) The paths it was writing to the CSS file were relative to the assets and not to the CSS file. Setting the relativeAssets to false reversed this, so it works now. I still think that description from the Compass docs is dead wrong. It's not setting absolute URLs in either case (as an absolute URL would either need to include the http:// and domain part, or include all the folders from my system root folder on my machine up unto the folder the assets were in, e.g. `/Users/joachimdyndale/Development/myProject/myapp_joachim/proj/dist/images`). – Joe Dyndale Jun 05 '13 at 13:43