text: var dummer, object, sanitizer,
    __hasProp = {}.hasOwnProperty;
  
  object = require('utila').object;
  
  sanitizer = require('./sanitizer');
  
  module.exports = dummer = {
    toDom: function(o) {
      if (!Array.isArray(o)) {
        if (!object.isBareObject(o)) {
          throw Error("toDom() only accepts arrays and bare objects as input");
        }
      }
      o = sanitizer.sanitize(o);
      return dummer._children(o);
    },
    _children: function(a, parent) {
      var children, node, prev, v, _i, _len;
      if (parent == null) {
        parent = null;
      }
      children = [];
      prev = null;
      for (_i = 0, _len = a.length; _i < _len; _i++) {
        v = a[_i];
        if (typeof v === 'string') {
          node = dummer._textNode(v);
        } else {
          node = dummer._objectToDom(v, parent);
          node.prev = null;
          node.next = null;
          node.parent = parent;
          if (prev != null) {
            node.prev = prev;
            prev.next = node;
          }
          prev = node;
        }
        children.push(node);
      }
      return children;
    },
    _objectToDom: function(o) {
      var attribs, children, i, k, key, name, node, v, val, _ref;
      i = 0;
      for (k in o) {
        if (!__hasProp.call(o, k)) continue;
        v = o[k];
        if (i > 0) {
          throw Error("_objectToDom() only accepts an object with one key/value");
        }
        key = k;
        val = v;
        i++;
      }
      node = {};
      if (typeof key !== 'string') {
        throw Error("_objectToDom()'s key must be a string of tag name and classes");
      }
      if (typeof val === 'string') {
        children = [dummer._textNode(val)];
      } else if (Array.isArray(val)) {
        children = dummer._children(val, node);
      } else {
        inspect(o);
        throw Error("_objectToDom()'s key's value must only be a string or an array");
      }
      node.type = 'tag';
      _ref = dummer._parseTag(key), name = _ref.name, attribs = _ref.attribs;
      node.name = name;
      node.attribs = attribs;
      node.children = children;
      return node;
    },
    _textNode: function(s) {
      return {
        type: 'text',
        data: s
      };
    },
    _nameRx: /^[a-zA-Z\-\_]{1}[a-zA-Z0-9\-\_]*$/,
    _parseTag: function(k) {
      var attribs, classes, cls, id, m, name, parts;
      if (!k.match(/^[a-zA-Z0-9\#\-\_\.\[\]\"\'\=\,\s]+$/) || k.match(/^[0-9]+/)) {
        throw Error("cannot parse tag `" + k + "`");
      }
      attribs = {};
      parts = {
        name: '',
        attribs: attribs
      };
      if (m = k.match(/^([^\.#]+)/)) {
        name = m[1];
        if (!name.match(dummer._nameRx)) {
          throw Error("tag name `" + name + "` is not valid");
        }
        parts.name = name;
        k = k.substr(name.length, k.length);
      }
      if (m = k.match(/^#([a-zA-Z0-9\-]+)/)) {
        id = m[1];
        if (!id.match(dummer._nameRx)) {
          throw Error("tag id `" + id + "` is not valid");
        }
        attribs.id = id;
        k = k.substr(id.length + 1, k.length);
      }
      classes = [];
      while (m = k.match(/\.([a-zA-Z0-9\-\_]+)/)) {
        cls = m[1];
        if (!cls.match(dummer._nameRx)) {
          throw Error("tag class `" + cls + "` is not valid");
        }
        classes.push(cls);
        k = k.replace('.' + cls, '');
      }
      if (classes.length) {
        attribs["class"] = classes.join(" ");
      }
      return parts;
    }
  };
  