Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Easy HTML5 applications
Ruby Other
tree: 4f6b17d984

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.

Wunderbar: Easy HTML5 applications

Wunderbar makes it easy to produce valid HTML5, wellformed XHTML, Unicode (utf-8), consistently indented, readable applications. This includes output that conforms to the Polyglot specification and the emerging results from the XML Error Recovery Community Group.

Wunderbar is both inspired by, and builds upon Jim Weirich's Builder, and provides the element id and class id syntax and based on the implementation from Markaby.

Wunderbar's JSON support is inspired by David Heinemeier Hansson's jbuilder.


The premise of Wunderbar is that output of various types are typically formed by appending either a series of key/value pairs or simple values, and those operations should be optimized for. Appending a key/value pair is done via:

_key value

... and appending a simple value is done thus:

_ value

For HTML, key/value is used for element nodes, and simple values are used for text nodes. For JSON, key/value is used for Hashes and simple values are used for arrays. For text, simple values are output via puts, and key/value pairs are not used.

Nesting is performed using blocks.

The underscore method, when passed no arguments, returns an object that can be used to perform a number of special functions. Some of those functions are unique to the output method. Others like logging methods are common.

The underscore method when passed multiple arguments or a combination of arguments and a block may do other common functions, depending on the types of the arguments passed.

Question mark, exclamation mark, and underscore suffixes to the method name may modify the results.

Quick Start (HTML)

Simple element:


Nested elements:

_div do

Element with text:

_h1 "My weblog"

Element with attributes:

_img src: '/img/logo.jpg', alt: 'site logo'

Element with both text and attributes:

_a 'search', href: ''

Element with boolean attributes:

_input 'Cheese', type: 'checkbox', name: 'cheese', checked: true

Element with optional (omitted) attributes:

_tr class: nil

Text (may contain markup):

_ "<em>hello</em>!!!"

Text (markup is escaped):

_? "<3"

Mixed content (autospaced):

_p do
  _ 'It is a'
  _em 'very'
  _ 'nice day.'

Mixed content (space controlled):

_p! do
  _ 'Source is on '
  _a 'github', href: ''
  _ '.'

Insert blank lines between rows in the HTML produced:

_tbody do
  _tr_ do
    _td 1
  _tr_ do
    _td 2
  _tr_ do
    _td 3

Capture exceptions:

_body? do

Class attribute shortcut (equivalent to class="front"):

div.front do

Id attributes shortcut (equivalent to id="search"):! do

Basic interface

A typical main program produces one or more of HTML, JSON, or plain text output. This is accomplished by providing one or more of the following:

_html do

_xhtml do

_json do

_text do

Arbitrary Ruby code can be placed in each. Form parameters are made available as instance variables (e.g., @name). Host environment (CGI, Rack, Sinatra) values are accessible as methods of the _ object: for example _.headers (CGI), _.set_cookie (Rack), _.redirect (Sinatra).

To append to the output produced, use the _ methods described below.

Methods provided to Wunderbar.html

Invoking methods that start with a Unicode low line character ("_") will generate a HTML tag. As with builder on which this library is based, these tags can have text content and attributes. Tags can also be nested. Logic can be freely intermixed.

Wunderbar knows which HTML tags need to be explicitly closed with separate end tags (example: textarea), and which should never be closed with separate end tags (example: br). It also takes care of HTML quoting and escaping of arguments and text.

Suffixes after the tag name will modify the processing.

  • !: turns off all special processing, including indenting
  • ?: adds code to rescue exceptions and produce tracebacks
  • _: adds extra blank lines between this tag and siblings

The "_" method serves a number of purposes. Calling it with a single argument inserts markup, respecting indendation. Inserting markup without reguard to indendatation is done using "_ << text". A number of other convenience methods are defined:

  • _?: insert text with indentation matching the current output
  • _!: insert text without indenting
  • -- was this invoked via HTTP POST?
  • _.system -- invokes a shell command, captures stdin, stdout, and stderr
  • _.submit -- runs command (or block) as a deamon process
  • _.xhtml? -- output as XHTML?

Access to all of the builder defined methods (typically these end in an esclamation mark) and all of the Wunderbar module methods can be accessed in this way. Examples:

  • _.tag! :foo: insert elements where the name can be dynamic
  • _.error 'Log message': write a message to the server log

XHTML differs from HTML in the escaping of inline style and script elements. XHTML will also fall back to HTML output unless the user agent indicates it supports XHTML via the HTTP Accept header.

In addition to the default processing of elements, text, and attributes, Wunderdar defines additional processing for the following:

  • _head: insert meta charset utf-8
  • _svg: insert svg namespace
  • _math: insert math namespace
  • _coffeescript: convert coffeescript to JS and insert script tag

Note that adding an exclamation mark to the end of the tag name disables this behavior.

If one of the attributes passed on the _html declaration is :_width, an attempt will be made to reflow text in order to not exceed this line width. This won't be done if it will affect what actually is displayed.

Methods provided to Wunderbar.json

Common operations are to return a Hash or an Array of values. Hashes are a series of name/value pairs, and Arrays are a series of values.

Wunderbar.json do
  _content format_content(@message.content)
  _ @message, :created_at, :updated_at 

  _author do
    _email_address @message.creator.email_address_with_name
    _url url_for(@message.creator, format: :json)

  if current_user.admin?
    _visitors calculate_visitors(@message)

  _comments @message.comments, :content, :created_at

  _attachments @message.attachments do |attachment|
    _filename attachment.filename
    _url url_for(attachment)

Invoking methods that start with a Unicode low line character ("_") will add a key/value pair to that hash. Hashes can also be nested. Logic can be freely intermixed.

The "_" method serves a number of purposes.

  • calling it with multiple arguments will cause the first argument to be treated as the object, and the remainder as the attributes to be extracted

    • Example: _ File.stat('foo'), :mtime, :size, :mode
  • calling it with a single Enumerable object and a block will cause an array to be returned based on mapping each objection from the enumeration against the block

    • Example: _([1,2,3]) {|n| n*n}
  • arrays can be also be built using the _ method:

    _ 1
    _ 2

The _ method returns a proxy to the object being constructed. This is often handy when called with no arguments. Examples:

    _['foo'] = 'bar'

Methods provided to Wunderbar.text

Appending to the output stream is done using the _ method, which is equivalent to puts. The _ method returns an object which proxies the output stream, which provides access to other useful methods, for example:

    _.print 'foo'
    _.printf "Hello %s!\n", 'world'

Secure by default

Wunderbar will properly escape all HTML and JSON output, eliminating problems of HTML or JavaScript injection. This includes calls to _ to insert markup directly when the input is tainted and not explicitly marked as html-safe? (when using Rails).

For all environments other than Rails, unless you call Wunderbar.unsafe! at the top of your script, Wunderbar will also set $SAFE=1 before processing requests. This means that you will need to untaint all inputs received from external sources before you make system calls or access the file system.

A special feature that effectively is only available in the Rails environment: if the first argument to call that creates an element is html_safe?, then that argument will be treated as a markup instead of as text. This allows one to make calls like _td link_to... without placing the call to link_to in a block.

Globals provided

  • $USER - Host user id
  • $HOME - Home directory
  • $SERVER - Server name
  • $HOME - user's home directory
  • $HOST - server host

Also, the following environment variables are set if they aren't already:

  • HOME
  • LANG

Finally, the (Ruby 1.9.x) default external and internal encodings are set to UTF-8. For Ruby 1.8, $KCODE is set to U

Builder extensions

  • indented_text!: matches text indentation to markup
  • indented_data!: useful for script and styles in HTML syntax
  • disable_indentation!: temporarily disable insertion of whitespace
  • margin!: insert blank lines between tags


  • _.debug: debug messages
  • informational messages
  • _.warn: warning messages
  • _.error: error messages
  • _.fatal: fatal error messages
  • _.log_level=: set logging level (default: :warn)
  • _.logger: return Logger instance

Command line options

When run from the command line, CGI name=value pairs can be specified. Additionally, the following options are supported:

  • --get: HTML (HTTP GET) output is expected
  • --post: HTML (HTTP POST) output is expected
  • --json: JSON (XML HTTP Request) output is expected
  • --html: force HTML output
  • --prompt or --offline: prompt for key/value pairs using stdin
  • --debug, --info, --warn, --error, --fatal: set log level
  • --install=path: produce an suexec-callable wrapper script
  • --rescue or --backtrace cause wrapper script to capture errors

Optional dependencies:

The following gems, if installed, will produce cleaner and prettier output:

  • nokogiri cleans up HTML fragments inserted via <<
  • escape prettier quoting of system commands
Something went wrong with that request. Please try again.