group-props.js 2.5 KB
var makeMap = require('./make-map')
var isTopLevel = makeMap('class,staticClass,style,key,ref,refInFor,slot,scopedSlots')
var nestableRE = /^(props|domProps|on|nativeOn|hook)([\-_A-Z])/
var dirRE = /^v-/
var xlinkRE = /^xlink([A-Z])/

module.exports = function groupProps (props, t) {
  var newProps = []
  var currentNestedObjects = Object.create(null)
  props.forEach(function (prop) {
    var name = prop.key.value || prop.key.name
    if (isTopLevel(name)) {
      // top-level special props
      newProps.push(prop)
    } else {
      // nested modules
      var nestMatch = name.match(nestableRE)
      if (nestMatch) {
        var prefix = nestMatch[1]
        var suffix = name.replace(nestableRE, function (_, $1, $2) {
          return $2 === '-' ? '' : $2.toLowerCase()
        })
        var nestedProp = t.objectProperty(t.stringLiteral(suffix), prop.value)
        var nestedObject = currentNestedObjects[prefix]
        if (!nestedObject) {
          nestedObject = currentNestedObjects[prefix] = t.objectProperty(
            t.identifier(prefix),
            t.objectExpression([nestedProp])
          )
          newProps.push(nestedObject)
        } else {
          nestedObject.value.properties.push(nestedProp)
        }
      } else if (dirRE.test(name)) {
        // custom directive
        name = name.replace(dirRE, '')
        var dirs = currentNestedObjects.directives
        if (!dirs) {
          dirs = currentNestedObjects.directives = t.objectProperty(
            t.identifier('directives'),
            t.arrayExpression([])
          )
          newProps.push(dirs)
        }
        dirs.value.elements.push(t.objectExpression([
          t.objectProperty(
            t.identifier('name'),
            t.stringLiteral(name)
          ),
          t.objectProperty(
            t.identifier('value'),
            prop.value
          )
        ]))
      } else {
        // rest are nested under attrs
        var attrs = currentNestedObjects.attrs
        // guard xlink attributes
        if (xlinkRE.test(prop.key.name)) {
          prop.key.name = JSON.stringify(prop.key.name.replace(xlinkRE, function (m, p1) {
            return 'xlink:' + p1.toLowerCase()
          }))
        }
        if (!attrs) {
          attrs = currentNestedObjects.attrs = t.objectProperty(
            t.identifier('attrs'),
            t.objectExpression([prop])
          )
          newProps.push(attrs)
        } else {
          attrs.value.properties.push(prop)
        }
      }
    }
  })
  return t.objectExpression(newProps)
}