code: function parseTagSpec(specString) {
      if (!specString || !specString.match) throw new ParseError(specString)
      if (specCache[specString]) return specCache[specString]
  
      // Parse tagName, and optional type attribute
      var tagMatch = specString.match(tagNameRegex)
      if (!tagMatch) {
          if (specString.match(propsRegex)) tagMatch = ['div', 'div'] // create <div> if tagname omitted
          else throw new ParseError(specString)
      }
      var tagName = tagMatch[1]
      var props = {}
      var classes = []
  
      if (specString.match(autoKeyGenRegex)) props.key = specString
      if (tagMatch[2]) props.type = tagMatch[2]
      else if (tagName === 'button') props.type = 'button' // Saner default for <button>
  
      var matches = specString.match(propsRegex)
      matches && matches.forEach(function getRegexMatches(str) {
          if (!str) return
          else if (str[0] === '#') props.id = str.slice(1)
          else if (str[0] === '@') props.ref = str.slice(1)
          else if (str[0] === '.') classes.push(str.slice(1))
          else if (str[0] === '[') {
              var match = str.match(attrRegex)
              if (match) props[match[1]] = match[2] || true    // If no attr value given, use true
          }
      })
      if (classes.length) props.className = classes.join(' ')
  
      var spec = {
          tagName: tagName,
          props: props
      }
  
      specCache[specString] = spec
      return spec
  }
docs: Convert a tag specification string into an object eg. 'input:checkbox#foo.bar[name=asdf]' produces the output: { tagName: 'input', props: { type: 'checkbox', id: 'foo', className: 'bar', name: 'asdf' } }