Stylus or Less Support #290

Closed
djensen47 opened this Issue Jan 6, 2013 · 13 comments

Projects

None yet

4 participants

@djensen47

So either there is no support for a CSS framework or it is not documented, in either case it's an "issue."

Or can I implement something in config? Again, documentation is lacking.

Commentary:
Developing with vanilla CSS is painful and nearly every other Node.js framework out there supports swapping in CSS engines, specifically Stylus or Less. Why not geddy? I was super excited when I recently found geddy, until I couldn't find any documentation around CSS engines.

@djensen47

I'm digging through the code geddy/lib/app.js and there doesn't seem to be a good place to fit this type of support. I guess I could just create a controller to handle this with some code in the config to compile everything on server start.

Thoughts?

@djensen47

Here's my initial rudimentary stab at this. It works but it has a few issues:

  • Compiles the .styl files on every request. Instead, it should only recompile if the file has changed.
  • No configuration.
  • Should compile everything in /public/stylus on server start
  • /public/stylus should be configurable
// router.js
router.match('/styles/*file.css').to('StylusController.render');

PS, the * notation is not documented per se.

// stylus_controller.js
var stylus = require('stylus')
  , fs = require('fs');

//  this.respondsWith = ['css'];

var StylusController = function () {

  this.render = function(req, res, params) {
    var self = this;
    var path = process.cwd()+ '/public/stylus/';
    var filename =  path+params.file+'.styl';

    fs.readFile(filename, 'utf8', function(err, str) {
      if (err) {
        var notFoundError = new Error(filename + ' not found.');
        notFoundError.statusCode = 404;
        self.error(notFoundError);
      } else {
        stylus(str).set('paths', [path]).render(function(err, css){
          if (err) {
            self.error(err);
          } else {
            geddy.log.debug('css: '+css);
            self.respond(css, {layout: false});
          }
        });
      }
    });
  }
}

exports.StylusController = StylusController;
@larzconwell

This would be an incredibly large project, it would almost be easier to build a module from scratch that acts as a daemon that compiles, re-compiles on changes and manages other FS events for those files. Then add a nice API to manage the paths to watch assets from, and other configs. And call the API when Geddy is in it's init position.

A few ideas for a asset module

  • init api with config options
  • FS daemon to compile and recompile on changes
  • handle languages for both JS(CoffeeScript, TypeScript) and CSS(Stylus, SCSS, LESS, SASS)
  • JSON manifest files in source path similar to Rails Asset Pipeline's so the module knows what files to compile, and which to ignore(Manifests would be held in the jsPath/cssPath inside source path, i,e,. $source/$jsPath/manifest.json)

Possibly options for a asset module

  • source Directory where source paths are held
  • destination Directory where compiled paths are written
  • cache Boolean decide whether or not to cache the FS contents of source files
  • jsPath Path in source/directory where JS type files are held
  • cssPath Path in source/directory where CSS type files are held
  • helpers Object/Array of helpers to give to the file when compiling

A few ideas for the Geddy side

  • Source files in app/assets
  • Compiled files in public
  • View helper to include a set of styles/scripts that should point to a JSON manifest
  • Add view helpers to the asset module on init, after helpers have been created.
@djensen47

Yeah, that does look like a large undertaking. Stylus does have a command line utility. At the same time, an asset module is essential.

@larzconwell

But in the mean time I'll write you a script that'll compile js/css assets in app/assets to public and re-compile on FS changes.

@larzconwell

Here you go @djensen47 a simple asset compiler, it'll handle deep asset paths like app/assets/js/ui/buttons/main.js by creating all the needed directories in the public dir.

All you need to do is create a config/after_start.js file and paste these contents into it. Then all assets in app/assets/js will be compiled to public/js and app/assets/css will be compiled to public/css, giving you a log of the files written as well. On change events for files being watched, it'll re-compile the files.

https://gist.github.com/4470370

EDIT: You can use this in production, since it compiles files on init, and only updates on changes. So it wouldn't cause any lag on the server, well unless you start changing the assets on the production server.

@Techwraith
@djensen47

@larzconwell: Thanks for the script.

@Techwraith: Sure, I'm willing to pitch in.

@larzconwell

Yeah I've had the ideas in my head for some time now, haha When should we meet on IRC? By the way @djensen47 our IRC is #geddyjs on freenode, we would love the help!

@mde
mde commented Jan 7, 2013

I've got a few ideas on how to approach this, given how Rails does it, and how we handle our build-step here at Yammer (using Node). I'll start a pull-request for us so we can all comment on what we think is needed.

@larzconwell

Okay sounds good.

@mde
mde commented Jan 8, 2013

Pull-request here -- just a place to start talking: #292

@ben-ng ben-ng referenced this issue May 17, 2013
Closed

Asset management #361

@larzconwell

Closing in favor of #292 for general asset management.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment