versions/0.2.2/oj.js
function _compileTag(ojml, options){

    // Empty list compiles to undefined
    if (ojml.length === 0) return

    // The first part of ojml is the tag
    var tag = ojml[0],
      tagType = typeof tag,
      u = oj.unionArguments(ojml.slice(1)),
      attributes = u.options,
      children = u.args,
      styles,
      selector

    // Allow the tag parameter to be 'table' (string) or oj.table (function) or oj.Table (object)
    if ((tagType === 'function' || tagType === 'object'))
      tag = _d(_getTagName(tag), tag)

    // Fail if no tag found
    if (!(oj.isString(tag) && tag.length > 0))
      _e('compile', 'tag name is missing')

    // Record tag as encountered
    options.tags[tag] = true

    // Instance oj object if tag is capitalized
    if (_isCapitalLetter(tag[0]))
      return _compileDeeper(_compileAny, new oj[tag](ojml.slice(1)), options)

    // Compile to css if requested
    if (options.css && tag === 'css'){

      // Extend options.css with rules
      for (selector in attributes){
        styles = attributes[selector]
        options.css['oj'] = _d(options.css['oj'], {})
        options.css['oj'][selector] = _d(options.css['oj'][selector], {})
        _extend(options.css['oj'][selector], styles)
      }
    }

    // Compile DOCTYPE as special case because it is not really an element
    // It has attributes with spaces and cannot be created by dom manipulation
    // In this way it is HTML generation only.

    if (tag === '!DOCTYPE'){
      _v('compile', 1, ojml[1], 'string')
      if (!options.ignore[tag]){
        if (options.html)
          options.html.push("<" + tag + " " + ojml[1] + ">")
        // options.dom is purposely ignored
      }
      return
    }
    if (!options.ignore[tag]){
      var events = _attributesProcessedForOJ(attributes), el

      // Compile to dom if requested
      // Add dom element with attributes
      if (options.dom && (typeof document !== _udf && document !== null)){

        // Create element
        el = document.createElement(tag)

        // Add self to parent
        if (oj.isDOMElement(options.dom))
          options.dom.appendChild(el)

        // Push ourselves on the dom stack (to handle children)
        options.dom = el

        // Set attributes in sorted order for consistency
        if (oj.isPlainObject(attributes)){
          var keys = _keys(attributes).sort(), ix, attrName, attrValue
          for (ix = 0; ix < keys.length; ix++){
            attrName = keys[ix]
            attrValue = attributes[attrName]

            // Boolean attributes have no value
            if (attrValue === true)
              el.setAttributeNode(document.createAttribute(attrName))
            else
              el.setAttribute(attrName, attrValue)
          }
        }

        // Bind events
        _attributesBindEventsToDOM(events, el, options.inserts)
      }

      // Compile to html if requested
      // Add tag with attributes
      if (options.html){
        var attr = _d(_attributesFromObject(attributes), ''),
          space = attr === '' ? '' : ' '
        options.html.push("<" + tag + space + attr + ">")
        // Recurse through children if this tag isn't ignored deeply
      }
    }
    if (options.ignore[tag] !== 'deep'){
      for (ix = 0; ix < children.length; ix++){
        var child = children[ix]
        // Skip indention if there is only one child
        if (options.html != null && !options.minify && children.length > 1)
          options.html.push("\n\t" + options.indent)
        _compileDeeper(_compileAny, child, options)
      }
    }

    // Skip indention if there is only one child
    if (options.html != null && !options.minify && children.length > 1)
      options.html.push("\n" + options.indent)

    // End html tag if you have children or your tag closes
    if (!options.ignore[tag]){

      // Close tag if html
      if (options.html != null && (children.length > 0 || oj.tag.isClosed(tag)))
        options.html.push("</" + tag + ">")

      // Pop ourselves if dom
      if (options.dom)
        options.dom = options.dom.parentNode
    }
  }
function _compileTag(ojml, options){

    // Empty list compiles to undefined
    if (ojml.length === 0) return

    // The first part of ojml is the tag
    var tag = ojml[0],
      tagType = typeof tag,
      u = oj.unionArguments(ojml.slice(1)),
      attributes = u.options,
      children = u.args,
      styles,
      selector

    // Allow the tag parameter to be 'table' (string) or oj.table (function) or oj.Table (object)
    if ((tagType === 'function' || tagType === 'object'))
      tag = _d(_getTagName(tag), tag)

    // Fail if no tag found
    if (!(oj.isString(tag) && tag.length > 0))
      _e('compile', 'tag name is missing')

    // Record tag as encountered
    options.tags[tag] = true

    // Instance oj object if tag is capitalized
    if (_isCapitalLetter(tag[0]))
      return _compileDeeper(_compileAny, new oj[tag](ojml.slice(1)), options)

    // Compile to css if requested
    if (options.css && tag === 'css'){

      // Extend options.css with rules
      for (selector in attributes){
        styles = attributes[selector]
        options.css['oj'] = _d(options.css['oj'], {})
        options.css['oj'][selector] = _d(options.css['oj'][selector], {})
        _extend(options.css['oj'][selector], styles)
      }
    }

    // Compile DOCTYPE as special case because it is not really an element
    // It has attributes with spaces and cannot be created by dom manipulation
    // In this way it is HTML generation only.

    if (tag === '!DOCTYPE'){
      _v('compile', 1, ojml[1], 'string')
      if (!options.ignore[tag]){
        if (options.html)
          options.html.push("<" + tag + " " + ojml[1] + ">")
        // options.dom is purposely ignored
      }
      return
    }
    if (!options.ignore[tag]){
      var events = _attributesProcessedForOJ(attributes), el

      // Compile to dom if requested
      // Add dom element with attributes
      if (options.dom && (typeof document !== _udf && document !== null)){

        // Create element
        el = document.createElement(tag)

        // Add self to parent
        if (oj.isDOMElement(options.dom))
          options.dom.appendChild(el)

        // Push ourselves on the dom stack (to handle children)
        options.dom = el

        // Set attributes in sorted order for consistency
        if (oj.isPlainObject(attributes)){
          var keys = _keys(attributes).sort(), ix, attrName, attrValue
          for (ix = 0; ix < keys.length; ix++){
            attrName = keys[ix]
            attrValue = attributes[attrName]

            // Boolean attributes have no value
            if (attrValue === true)
              el.setAttributeNode(document.createAttribute(attrName))
            else
              el.setAttribute(attrName, attrValue)
          }
        }

        // Bind events
        _attributesBindEventsToDOM(events, el, options.inserts)
      }

      // Compile to html if requested
      // Add tag with attributes
      if (options.html){
        var attr = _d(_attributesFromObject(attributes), ''),
          space = attr === '' ? '' : ' '
        options.html.push("<" + tag + space + attr + ">")
        // Recurse through children if this tag isn't ignored deeply
      }
    }
    if (options.ignore[tag] !== 'deep'){
      for (ix = 0; ix < children.length; ix++){
        var child = children[ix]
        // Skip indention if there is only one child
        if (options.html != null && !options.minify && children.length > 1)
          options.html.push("\n\t" + options.indent)
        _compileDeeper(_compileAny, child, options)
      }
    }

    // Skip indention if there is only one child
    if (options.html != null && !options.minify && children.length > 1)
      options.html.push("\n" + options.indent)

    // End html tag if you have children or your tag closes
    if (!options.ignore[tag]){

      // Close tag if html
      if (options.html != null && (children.length > 0 || oj.tag.isClosed(tag)))
        options.html.push("</" + tag + ">")

      // Pop ourselves if dom
      if (options.dom)
        options.dom = options.dom.parentNode
    }
  }
_compileTag: Recursive helper for compiling ojml tags