Text

Stylus gets @extend

@extend is a great little feature which originated in SASS, and now finds a home in Stylus. If you’ve ever written CSS like this, you know it can become quite the pain to maintain large lists of selectors:

.message,
.warning,
.error {
  px;
  padding: 5px 10px;
  border: 1px solid #eee;
  border-radius: 5px;
}

.warning {
  color: yellow;
}

.error {
  color: red;
}

@extend makes this process flow naturally, and even supports inheritance. In Stylus you may use @extend or @extends, I prefer the latter personally but that’s up to you! Using this feature you would define .message on it’s own, and simply __@extend_ it from within the other rulesets:

.message {
  px;
  padding: 5px 10px;
  border: 1px solid #eee;
  border-radius: 5px;
}

.warning {
  @extends .message;
  color: yellow;
}

.error {
  @extends .message;
  color: red;
}

Taking this even further with inheritance:

.fatal-error {
  @extends .error;
  font-weight: bold
}

Would yield the following CSS:

.message,
.warning,
.error,
.fatal-error {
  px;
  padding: 5px 10px;
  border: 1px solid #eee;
  border-radius: 5px;
}
.warning {
  color: #ff0;
}
.error,
.fatal-error {
  color: #f00;
}
.fatal-error {
  font-weight: bold;
}

Here’s another example:

form
  button
    padding: 10px
    border: 1px solid #eee
    border-radius: 5px

ul
  li a
    @extends form button

Yielding:

form button,
ul li a {
  padding: 10px;
  border: 1px solid #eee;
  border-radius: 5px;
}

And of course you may utilize the alternative Stylus syntax if you prefer:

.message
  px
  padding: 5px 10px
  border: 1px solid #eee
  border-radius: 5px

.warning
  @extends .message
  color: yellow

.error
  @extends .message
  color: red

.fatal-error
  @extends .error
  font-weight: bold

Grab Stylus 0.22.4 for these goodies!

Tags: nodejs stylus css
January 11, 2012
3 notes
Link

Why Stylus is the most CSS-like high-level stylesheet language

This short Vimeo screencast illustrates why Stylus is the most like CSS as a stylesheet “preprocessor”. More on Stylus here.

Tags: js nodejs stylus screencast
December 11, 2011
7 notes
Text

Connect 1.8.0 - multipart support

Connect 1.8.0 is a tiny but substantial release because it adds multipart/form-data support via Felix Geisendörfer’s fantastic multipart parser formidable, it’s great and chances are you’re already using it!

The bodyParser() middleware now unifies multipart, json, and x-www-form-urlencoded parsing, providing the req.body object containing the parsed data. For security purposes the files are placed in a separate object, req.files, however just as accessible. A constant struggle that I’ve seen in the community is the concept of “missing” request data events so this will prevent further confusion. The downside to this is that if you wish to report upload progress, or access files and fields as the request is streamed, you will have to use formidable directly.

Before this addition your use of formidable might look something like the following (with Express):

  app.post('/someform', function(req, res, next){
    var form = new formidable.IncomingForm;
    form.parse(req, function(err, fields, files){
      if (err) return next(err);
      // do something with files.image etc
    });
  });

With the new bodyParser() all you need is:

  app.use(express.bodyParser());

  app.post('/some-form', function(req, res){
    // do something with req.files.image
  })

The middleware takes the same options that are mentioned on formidable’s GitHub repo page, so you can specify things like size limits, retaining extensions, the upload directory etc.

  app.use(express.bodyParser({
    uploadDir: '/tmp/uploads'
  }));

That’s it! but I think this will cover well above the 80% use-case and prevent a lot of headaches that people have with the previous the inconsistencies.

Tags: connect nodejs
November 17, 2011
16 notes
Text

Stylus 0.15.1 - new property reference & @keyframes fabrication features

Stylus 0.15.x adds a bunch of cool new functionality as well as some important bug fixes.

@keyframes fabrication

The new keyframes fabrication support automatically duplicates your @keyframes definitions to support vendor prefixes. Note that this is only a default, as shown below:

@-moz-keyframes foo {
  0% {
    color: #000;
  }

  100% {
    color: #fff;
  }
}
@-webkit-keyframes foo {
  0% {
    color: #000;
  }

  100% {
    color: #fff;
  }
}
@keyframes foo {
  0% {
    color: #000;
  }

  100% {
    color: #fff;
  }
}

one can tweak this functionality using the vendors list as shown in the following snippet which will only expand to the -webkit- vendor prefix.

vendors = moz official

@keyframes foo {
  from {
    color: black
  }
  to {
    color: white
  }
}

The vendors property may be utilized more in the future, and perhaps in frameworks like “nib” to unify configuration.

Property reference

The syntax @<property> has been introduced to reference values of existing properties. For example if you want to re-use values, you may typically do something like below instead of typing the value several times, also allowing you to use functions with w.

.button
  w = 50px
  w

The new property reference syntax allows you to treat properties as variables, which can also be accessed within mixins:

.button
  px
  @width

Comment compilation

When the compress option is true Stylus will not output single-line nor multi-line comments, which are commonly found used for licensing in stylesheet frameworks etc, so it’s useful to strip these out however you can now force output with the ! character /*!.

New built-in functions

The math functions cos() and sin() were added, as well as exposing PI.

Bug fixes

  • Fixed @import on windows
Tags: stylus nodejs js
September 01, 2011
6 notes
Text

Connect 1.7.0 - fast static file memory cache and more

Be sure to update Connect to the latest release 1.7.0 for the following goodies!

staticCache() middleware

1.7.0 now provides a new middleware named staticCache(), acting as a memory cache on top of the regular static() middleware. Older versions of Connect used to provide memory caching, however it was baked right into static(), bloating the middleware more than necessary.

Benchmarks

The test file for these benchmarks is a small 4kb readme:

$ du -h Readme.md 
4.0K    Readme.md

and the following ApacheBench command:

$ ab -n 5000 -c 50 -k local/Readme.md

First up we have Connect static(), which does not perform any caching, performing disk I/O each request, serving ~2400rps.

connect()
  .use(connect.static(__dirname))
  .listen(3000)

Next up we have node-static one of the other popular node solutions, serving ~3800rps

var static = require('node-static')
  , file = new static.Server(__dirname);

http.createServer(function(req, res){
  file.serve(req, res);
}).listen(3000);

Then we have the new staticCache() middleware paired with static() serving ~5000rps, a 24% increase over node-static (which also performs memory caching), and ~52% over static() alone.

connect()
  .use(connect.staticCache())
  .use(connect.static(__dirname))
  .listen(3000)

staticCache() is configurable, allowing you to specify the maximum number of cache objects to store, and the maximum size allowed, so you can cap resources appropriately. The middleware implements a Least Recently Used algorithm to prioritize popular files, knocking less popular objects out of the cache.

res.headerSent

Node core has a private flag named res._headerSent, allowing you to check if the header has been written or not, this is extremely useful in some cases, so Connect has publicized this property as res.headerSent until Node core does (if ever), using a getter to reference the private property.

logger() immediate option

The logger() middleware now provides { immediate: true }, as by default this middleware will log the response of a request, not when the request is first received, allowing logging of response-times etc.

Tags: connect nodejs
September 01, 2011
11 notes
Text

commander.js - nodejs command-line interfaces made easy

Commander.js is a small node.js module allowing you to define options and interacte with the user’s terminal in a simple and natural way, inspired by the Ruby library of the same name.

Features

  • self-documenting code
  • auto-generated help
  • combined short flags (“-abc” == “-a -b -c”)
  • option defaults
  • option coercion
  • command parsing
  • prompts

Example

A basic commander program looks something like the following (taken from serve). It’s extremely easy to see what’s going on, all the options provided by the executable are laid out infront of you.

program
  .version('0.0.1')
  .option('-p, --port <port>', 'specify the port [3000]', Number, 3000)
  .option('-H, --hidden', 'enable hidden file serving')
  .option('-I, --no-icons', 'disable file icons')
  .option('-L, --no-logs', 'disable request logging')
  .parse(process.argv);

In the previous example only --port accepts an argument, and the value of program.port defaults to 3000. The options --no-icons and --no-logs default their properties to true, only when --no-icons is specified will program.icons be false.

The usage information is free!:

$ serve --help

  Usage: serve [options]

  Options:

    -v, --version      output the version number
    -p, --port <port>  specify the port [3000]
    -H, --hidden       enable hidden file serving
    -I, --no-icons     disable file icons
    -L, --no-logs      disable request logging
    -h, --help         output usage information

Utilities

Commander is bundled with some utilities for prompting user input, confirmations, passwords, lists of choices etc. Most of these utilities will ask for input if the user simply hits enter and should respond.

Below is an example of asking for a name using a single-line input prompt:

program.prompt('name: ', function(name){
  console.log('hi %s', name);
});

Multi-line input is easy too, just leave out the trailing space in the message:

program.prompt('description:', function(name){
  console.log('hi %s', name);
});

Coercion is useful for dates, numbers etc:

 program.prompt('Age: ', Number, function(age){
  console.log('age: %j', age);
});

Password prompts masking off input:

program.password('Password: ', function(pass){
  console.log('got "%s"', pass);
});

Or providing a mask char:

program.password('Password: ', '*', function(pass){
  console.log('got "%s"', pass);
});

Confirmations require “yes” or “y” to result in true:

 program.confirm('continue? ', function(ok){
   console.log(' got %j', ok);
 });

There’s also choice support, so users can select from a list:

var list = ['tobi', 'loki', 'jane', 'manny', 'luna'];

console.log('Choose the coolest pet:');
program.choose(list, function(i){
  console.log('you chose %d "%s"', i, list[i]);
});

presenting:

Choose the coolest pet:
  1) tobi
  2) loki
  3) jane
  4) manny
  5) luna

Commands

Though I haven’t had time to polish them up yet, commander supports the idea of .. well… “commands”. The “root” executable is an instanceof Command, and well you can recursively define these to create a rich interface. GIT is a great example of this, many larger utilities use sub-command such as git remote to accept arguments, and may all then have their own options etc, using the same API as the root command. The following is a simple example:

#!/usr/bin/env node

var program = require('../');

program
  .version('0.0.1')
  .option('-C, --chdir <path>', 'change the working directory')
  .option('-c, --config <path>', 'set config path [./deploy.conf]')
  .option('-T, --no-tests', 'ignore test hook')

// $ deploy setup stage
// $ deploy setup
program
  .command('setup [env]')
  .description('run setup commands for all envs')
  .action(function(env){
    env = env || 'all';
    console.log('setup for %s env(s)', env);
  });

// $ deploy stage
// $ deploy production
program
  .command('*')
  .action(function(env){
    console.log('deploying "%s"', env);
  });

program.parse(process.argv);

Moar Libraries!

Dont forget to check out these other great CLI-related libraries:

  • cli-table awesome unicode tables by Guillermo
  • node-multimeter, ascii progress-bars by SubStack
Tags: node nodejs commander ruby
August 18, 2011
40 notes
Archive Random Next Page Page 1 of 4

About

spacer

A blog about server side technologies, nodejs, language design and more.

gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.