node.jssassgruntjscompass-sassgrunt-contrib-compass

Grunt + Compass doesn't create CSS File


I get the following error when using grunt compass:

"You must compile individual stylesheets from the project directory."

I tried it with grunt 3 different ways. More below.

My folder structure:

test \
     Gruntfile.js
     package.json
     \ node_modules \
     \ _src \ (this is the root folder of my Jekyll site)
        \ config.rb
        \ index.html
        \ static/
            \ _sass \
            \ css \
            \ images \
            \ js \

What works:

Everything works fine without using grunt and using /_src/config.rb:

#project_path = "_src/"
http_path = "/"
css_dir = "css"
css_path = "static/" + css_dir
sass_dir = "_sass"
sass_path = "static/" + sass_dir
images_dir = "images"
images_path = "static/" + images_dir
output_style = :expanded
relative_assets = true
line_comments = false

So, in /src I can compile just fine with compass watch.


What doesn't work

Anyway, I decided to ditch all GUI apps and step it up with grunt. That's where the problems started.

I'm also up to date:

$ grunt --version
>> grunt-cli v0.1.13

$ npm -v
>> 1.4.3

$ node -v
>> v0.10.26

1st try

The first thing I tried was trying to use the existing config.rb:

module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        // Config
        watch: {
            compass: {
                files: ['**/*.{scss,sass}'],
                tasks: ['compass:dev']
            },
            js: {
                // PLACEHOLDER HERE
            }
        },
        compass: {
            dev: {
                // dev options
                // ↓↓↓ HERE'S THE COMPASS CONFIG FILE ↓↓↓
                options: { config: '_src/config.rb' }
            },
            prod: {
                // prod options
            },
        },
        jshint: {
            options: { jshintrc: '.jshintrc' },
            all: ['Gruntfile.js', '_src/static/js/*.js']
        },
        browserSync: {
            files: {
                src : [
                    '_src/static/css/*.css',
                    '_src/static/images/*',
                    '_src/static/js/*.js',
                    '_src/**/*.html'
                ],
            },
            options: {
                watchTask: true
            }
        }
    });
    // Load the Grunt plugins.
    grunt.loadNpmTasks('grunt-contrib-compress');
    grunt.loadNpmTasks('grunt-contrib-compass');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-browser-sync');
    // Register the default tasks.
    grunt.registerTask('default', ['compass:dev', 'browserSync', 'watch']);
    grunt.registerTask('prod', ['compass:prod']);
};

Running grunt from /test works without an error, it even recognizes file changes, but doesn't compile my sass. No css file gets created.

I tried grunt compass watch --verbose and it aborts:

Running "compass:prod" (compass) task
Verifying property compass.prod exists in config...OK
File: [no files]
Options: cssDir=["_src/static/css"], sassDir=["_src/static/_sass"], imagesDir=["_src/static/images"], javascriptsDir=["_src/static/js"], fontsDir=["_src/static/fonts"], outputStyle="compressed", relativeAssets="true", noLineComments="true"
Options: cssDir=["_src/static/css"], sassDir=["_src/static/_sass"], imagesDir=["_src/static/images"], javascriptsDir=["_src/static/js"], fontsDir=["_src/static/fonts"], outputStyle="compressed", relativeAssets="true", noLineComments="true", time
You must compile individual stylesheets from the project directory.
Warning: ↑ Use --force to continue.

Aborted due to warnings.

… which I don't get at all.

2nd try – preferred attempt

Since I don't like having the config.rb sitting around in /_src/ anyway, I deleted it and replaced options: { config: '_src/config.rb' } in Gruntfile.js with:

options: {
    //config: '_src/config.rb'
    cssDir: ['_src/static/css'],
    sassDir: ['_src/static/_sass'],
    imagesDir: ['_src/static/images'],
    javascriptsDir: ['_src/static/js'],
    fontsDir: ['_src/static/fonts'],
    outputStyle: 'expanded',
    relativeAssets: 'true',
    noLineComments: 'false'
}

The error is exactly the same as the former one:

You must compile individual stylesheets from the project directory.

3rd try

As a last resort I tried putting the config.rb in the root (/test) add project_path = "_src" to it and use options: { config: 'config.rb' } in the Gruntfile. This did work as poor as my other trials.

I'd really like the Gruntfile-only version to work. I guess the base path for compass isn't working out too well, but can't figure out what to do.


Excerpt of what I already read on StackExchange to solve this

I already read:

PS: I also use RVM and Git. But I guess these don't matter here.


UPDATE:

Small steps… some progress (not really):

/Gruntfile.js

compass: {
    dev: {
        // dev options
        options: {
            config: 'config.rb',
            cssDir: '_src/static/css',
            sassDir: '_src/static/_sass'
        }
    },

I don't get why adding the config.rb (instead of writing it all down like in "2nd try" above changes everything and grunt decides to finally output an css file.

/config.rb

http_path = "/"
css_dir = "static/css"
sass_dir = "static/_sass"
images_dir = "static/images"
javascript_dir = "static/js"
fonts_dir = "static/fonts"
relative_assets = false

SASS:

.logo {
    background-image: image-url($logo);
    //width: image-width($logo);
    //height: image-height($logo);
}

Rendered CSS:

// relative_assets = true
// image still shows up, but it's not the sites root
// /test/_src/static/images ==> _src should be the root
background-image: url('../../../static/images/gaya-design-logo.png');

// relative_assets = false
background-image: url('/static/images/gaya-design-logo.png');

I also get an error:

WARNING: 'gaya-design-logo.png' was not found (or cannot be read) in /Users/pattulus/Sites/test/static/images

That's "fine" since I also get this one when using regular compass watch. However, with grunt, when I uncomment the two lines in the SASS code it aborts spitting out this:

Errno::ENOENT on line ["28"] of /Users/pattulus/.rvm/gems/ruby-2.0.0-p451@test/gems/compass-0.12.6/lib/compass/sass_extensions/functions/image_size.rb: No such file or directory - /Users/patte/Sites/test/static/images/gaya-design-logo.png

Strange since "normal compass" works. I didn't install compass globally, the gem is only active in this project folder. So that possibility is ruled out.


Solution

  • In the end (and after a day of trial and error) it boiled down to setting relativeAssets to false.

    My mistake with the "2nd try" was putting the boolean values in like this relativeAssets: 'false', instead of relativeAssets: false,.

    That and some tweaking basePath and "more".

    module.exports = function(grunt) {
    
        // Project configuration.
        grunt.initConfig({
            pkg: grunt.file.readJSON('package.json'),
    
            // Config
            watch: {
                compass: {
                    files: ['**/*.{scss,sass}'],
                    tasks: ['compass:dev']
                },
            },
    
            compass: {
                dev: {
                    // dev options
                    options: {
                        httpPath: '/',
                        basePath: '_src',
                        cssDir: 'static/css',
                        sassDir: 'static/_sass',
                        imagesDir: 'static/images',
                        javascriptsDir: 'static/js',
                        fontsDir: 'static/fonts',
                        outputStyle: 'expanded',
                        relativeAssets: false,
                        noLineComments: false
                    }
                },
            },
            jshint: {
                options: {
                    jshintrc: '.jshintrc'
                },
                all: ['Gruntfile.js', '_src/static/js/*.js']
            },
            browserSync: {
                files: {
                    src : [
                        '_src/static/css/*.css',
                        '_src/static/images/*',
                        '_src/static/js/*.js',
                        '_src/**/*.html'
                    ],
                },
                options: {
                    watchTask: true
                }
            }
    
        });
    
        // Load the Grunt plugins.
        grunt.loadNpmTasks('grunt-contrib-compress');
        grunt.loadNpmTasks('grunt-contrib-compass');
        grunt.loadNpmTasks('grunt-contrib-watch');
        grunt.loadNpmTasks('grunt-contrib-jshint');
        grunt.loadNpmTasks('grunt-browser-sync');
    
        // Register the default tasks.
        grunt.registerTask('default', ['compass:dev', 'browserSync', 'watch']);
        grunt.registerTask('prod', ['compass:prod']);
    };
    

    This sure was a long day… matter of fact I've been trying to get this running exactly like this since Friday (with browserSync and the whole loot). Hope the helps the next fellow.