parser.js 1.55 KB
Newer Older
liang ce committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
/* @flow */

// import { warn } from 'core/util/index'

// this will be preserved during build
// $flow-disable-line
const acorn = require('acorn') // $flow-disable-line
const walk = require('acorn/dist/walk') // $flow-disable-line
const escodegen = require('escodegen')

export function nodeToBinding (node: Object): any {
  switch (node.type) {
    case 'Literal': return node.value
    case 'Identifier':
    case 'UnaryExpression':
    case 'BinaryExpression':
    case 'LogicalExpression':
    case 'ConditionalExpression':
    case 'MemberExpression': return { '@binding': escodegen.generate(node) }
    case 'ArrayExpression': return node.elements.map(_ => nodeToBinding(_))
    case 'ObjectExpression': {
      const object = {}
      node.properties.forEach(prop => {
        if (!prop.key || prop.key.type !== 'Identifier') {
          return
        }
        const key = escodegen.generate(prop.key)
        const value = nodeToBinding(prop.value)
        if (key && value) {
          object[key] = value
        }
      })
      return object
    }
    default: {
      // warn(`Not support ${node.type}: "${escodegen.generate(node)}"`)
      return ''
    }
  }
}

export function generateBinding (exp: ?string): any {
  if (exp && typeof exp === 'string') {
    let ast = null
    try {
      ast = acorn.parse(`(${exp})`)
    } catch (e) {
      // warn(`Failed to parse the expression: "${exp}"`)
      return ''
    }

    let output = ''
    walk.simple(ast, {
      Expression (node) {
        output = nodeToBinding(node)
      }
    })
    return output
  }
}