Generating Style Guides with KSS

Documenting style will always be a challenge. I think it’s up to you to decide the project’s balance between:

  • The need for providing clear documentation.
  • The practical use a styleguide would actually serve to the project’s stakeholders

And here’s the key one I’ve usually found a challenge on most projects:

For a style guide to be effective and worth your time,

It takes the concern and vested interest of the other developers on the team to carefully contribute to the documentation, while sticking to a set of style structure and organization.

This last one is always a problem. I’ve found that on the many projects I’ve been involved with, more often than not, the prjoect turns into a mess of tangled CSS code and rules. It doesn’t matter how well we structure the files and folders from the beginning; when push comes to shove, deadlines and pressure cause us to be messy developers. I’m guilty of it as well.

On this particular project, the team already had a style guide set up using static HTML. I knew there had to be a better way, and I found a perfect way to do it.

That’s where Knyle Style Sheets come in. The developer, Kyle Neath seems to enjoy the way Github does it and has created a nice solution to do it. It automatically parses your .scss, .less, or .css files when you write in the approrpiate syntax and generates some static HTML for you.

Unfortunately, when it comes to the grunt and node stack, it was really tricky for me to get it spinning up.

I ended up finding a winning combination: I used grunt-styleguide and this awesome template, plus a couple hacks to get it working.

I’ll leave out the entire Gruntfile. Our project compiles styles from assets/styles into the public/css/ directory.

styleguide task:
Gruntfile.coffee
1
2
3
4
5
6
7
8
9
10
11
styleguide:
  options:
    template:
      src: 'assets/vendor/styleguide-template'
    framework:
      name: 'kss'
      options:
        includeType: 'sass'
        includePath: 'public/css/application.css'
  all:
    files: ['_styleguide': 'assets/styles/**/*.scss']

assets/vendor/styleguide-template is a clone of the template repo mentioned earlier, with some minor customizations to the template.

This task generates static HTML/CSS for a styleguide into the _styleguide directory.

The tricky part was getting my styles to show up in the outputted code. Unfortuantely, though the grunt-styleguide docs say you can run precompiled code through and it will take care of the rest, no matter how hard I tried, that didn’t work.

In the end, it was just a simple matter of adding to my copy and watch tasks to copy the compiled CSS over.

watch task:
Gruntfile.coffee
1
2
3
4
5
6
7
8
9
10
11
12
watch:
  options:
    livereload: false
    spawn: false

  'sass-application':
    livereload: false
    files: [
      'assets/styles/application.scss',
      'assets/styles/**/*.scss'
    ]
    tasks: ['sass:application', 'copy:styles', 'styleguide']
copy:styles task:
Gruntfile.coffee
1
2
3
4
5
6
7
8
copy:
  styles:
    files: [
      expand: true
      cwd: 'public/css'
      src: '**/*'
      dest: '_styleguide/css'
    ]

As a bonus, add grunt-contrib-connect and have it boot up a little preview server. This was helpful on a project I was running because index.html wasn’t accessible.

Gruntfile.coffee
1
2
3
4
5
6
7
8
9
connect:
  styleguide:
    options:
      port: 9001
      base: '_styleguide'
      keepalive: true
      open:
        target: 'http://localhost:9001'
        appName: 'Google Chrome'

Pretty cool, huh? Now, in my _modules.scss file, I can add this before the code block I want to add:

_modules.scss
1
2
3
4
5
6
7
// Spacer
//
// A basic separator element to break up sections.
//
// Markup: <div class="spacer"></div>
//
// Styleguide 2.1

The kss-node project is pretty finicky, but when it works, it’s awesome. You can add modifier classes, and it will generate nice code samples and output for each of those modifier classes. You can even add markdown within your descriptions.

_modules.sass
1
2
3
4
5
6
7
8
9
10
// Alerts
//
// Indicate failure or success. <em>Required: `alert-success` or `alert-error`</em>
//
// Markup: <div class="alert {$modifiers}">You mistyped your password.</div>
//
// .alert-error - Indicate an error
// .alert-success - Indicate success
//
// Styleguide 2.2
Screenshot:

If you find things aren’t working, check to make sure you’re numbering things in the right order, that you haven’t already documented a section. I had to move a few of my sections around to match the order of the @import statements in my main .scss file.

You can pretty quickly and easily customize that template as well, if needed.

Here’s to hoping this helps our team stay on a solid set of rules and continued documentation!

Synchronous Streams with Gulp

I’ve been a huge Grunt fan for awhile now, and it wasn’t until recently that I started using an up and coming tool Gulp for my tasks.

Special thanks to Dan Tello over at Viget for his post that really inspired me to get into this.

With Gulp, it’s all about the stream, man. You use asyncronous node pipe methods to chain streams together. It’s really tricky to understand if you’re not familiar with this concept, and it took me awhile (I’m still only now just getting it as I type).

With Grunt, it’s all about configuration; with Gulp, it’s all about building your tasks dynamically. It only took me an hour or two to migrate an existing Gruntfile over to a gulpfile. Including a learning curve with a new framework, this isn’t too bad.

I won’t dive too deep into it today, but one problem I ran into was with actually getting the tasks to finish before I started another one. It seemed like a bug, until I realized what was happening:

Gulp was working so fast, one stream hadn’t finished in time for the other to occur.

Example:

A common use case for this is compiling CSS, then minifying it. Seems simple, right? With Grunt, you’d just stack the tasks together, and since Grunt runs them one at a time, you have no issues.

Gruntfile.js
1
grunt.registerTask('default', ["coffee", "stylus", "jst", "concurrent:compress", "watch"]);

With Gulp, however, it’s not quite as simple.

Just an FYI here, I’m following Dan’s model of modularizing my tasks into individual files, hence the alternate filenames in the task definitions below. If you’re going with a basic setup, these can all live in your gulpfile.

gulpfile.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
gulp.task("compile", [
  "coffee",
  "stylus"
]);

gulp.task("compress", [
  "concat_app",
  "concat_vendor",
  "uglify_vendor",
  "cssmin"
]);

gulp.task("default", [
  "compile",
  "compress",
  "watch"
]);

gulp.task("build", [
  "compile",
  "compress"
]);

This doesn’t work as you expect. If you remove all CSS files from your project and run gulp build, you’ll end up with a compiled CSS file, but no minified version. However, if you run gulp build again, you’ll get your minified version, because the CSS file is already there.

Fortunately, gulp ships with an orchestrator that allows you to essentially specify dependencies that other tasks require. These dependencies are other Gulp task definitions that return a stream.

To specify one, just add an array after you task name, as with my cssmin task below, where I’ve added ['stylus'].

Cssmin task:
cssmin.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var cssmin = require('gulp-cssmin'),
  rename = require('gulp-rename');

module.exports = function() {
  return gulp.task("cssmin", ['stylus'], function() {
    gulp.src("public/stylesheets/vendor.css")
      .pipe(cssmin())
      .pipe(rename("vendor.min.css"))
      .pipe(gulp.dest("public/stylesheets"));

    gulp.src("public/stylesheets/application.css")
      .pipe(cssmin())
      .pipe(rename("application.min.css"))
      .pipe(gulp.dest("public/stylesheets"));
  });

}
Stylus task:
stylus.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
var gulp = require("gulp"),
  accord = require("gulp-accord"),
  cssmin = require("gulp-minify-css"),
  rename = require("gulp-rename"),
  notify = require("gulp-notify"),
  livereload = require("gulp-livereload"),
  stylus = require('gulp-stylus');

module.exports = function() {
  gulp.task("stylus", function() {
    gulp.src("public/stylesheets/styl/application.styl")
      .pipe(stylus({
        set: [
          "resolve url",
          "include-css",
          "linenos",
          "compress"
        ]
      })).on("error", notify.onError({
        message: "<%= error.message %>",
        title: "Stylus Error"
      }))
      .pipe(gulp.dest("public/stylesheets"))
      .pipe(livereload());

    return gulp.src("public/stylesheets/styl/vendor.styl")
      .pipe(stylus({
        set: [
          "include css",
          "linenos"
        ]
      })).on("error", notify.onError({
        message: "<%= error.message %>",
        title: "Stylus Error"
      }))
      .pipe(gulp.dest("public/stylesheets"));
  });
};

Now for the tricky part. See on line 33 where I’m returning the task itself? If you omit this line, the dependency is considered resolved and will never run. This line is super important and was confusing the hell out of me for quite awhile there, so I thought I’d share in case someone else ends up confused.

Ideally, I could split this task into two separate task definitions, but for this project that was good enough. I always want my vendor to be compiled, and though it rarely changes, with Gulp the compilation was so fast it was not even noticeable without it.

That’s all for today: make sure you return that stream!