scoped-component-traverse.js 3.2 KB
Newer Older
fxy060608's avatar
fxy060608 已提交
1 2 3 4 5 6 7 8
const t = require('@babel/types')
const babelTraverse = require('@babel/traverse').default

const {
  parseComponents
} = require('./util')

function handleObjectExpression (declaration, path, state) {
fxy060608's avatar
fxy060608 已提交
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
  if (state.options) { // name,inheritAttrs
    Object.keys(state.options).forEach(name => {
      const optionProperty = declaration.properties.filter(prop => {
        return t.isObjectProperty(prop) &&
          t.isIdentifier(prop.key) &&
          prop.key.name === name
      })[0]
      if (optionProperty) {
        if (t.isStringLiteral(optionProperty.value)) {
          state.options[name] = JSON.stringify(optionProperty.value.value)
        } else {
          state.options[name] = optionProperty.value.value
        }
      }
    })
  }

fxy060608's avatar
fxy060608 已提交
26 27
  const componentsProperty = declaration.properties.filter(prop => {
    return t.isObjectProperty(prop) &&
fxy060608's avatar
fxy060608 已提交
28 29
      t.isIdentifier(prop.key) &&
      prop.key.name === 'components'
fxy060608's avatar
fxy060608 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
  })[0]

  if (componentsProperty && t.isObjectExpression(componentsProperty.value)) {
    const properties = componentsProperty.value.properties
      .filter(prop => t.isObjectProperty(prop) && t.isIdentifier(prop.value))
    state.components = parseComponents(properties.map(prop => {
      return {
        name: prop.key.name || prop.key.value,
        value: prop.value.name
      }
    }), path.scope.bindings, path)
  }
}

module.exports = function (ast, state = {
  type: 'Component',
fxy060608's avatar
fxy060608 已提交
46 47
  components: [],
  options: {}
fxy060608's avatar
fxy060608 已提交
48 49
}) {
  babelTraverse(ast, {
fxy060608's avatar
fxy060608 已提交
50 51 52 53 54 55 56 57 58 59 60 61
    AssignmentExpression (path) {
      const memberExpression = path.node.left
      const objectExpression = path.node.right
      if (
        t.isMemberExpression(memberExpression) &&
        t.isObjectExpression(objectExpression) &&
        memberExpression.object.name === 'global' &&
        memberExpression.property.value === '__wxVueOptions'
      ) {
        handleObjectExpression(objectExpression, path, state)
      }
    },
fxy060608's avatar
fxy060608 已提交
62 63 64 65 66
    ExportDefaultDeclaration (path) {
      const declaration = path.node.declaration
      if (t.isObjectExpression(declaration)) { // export default {components:{}}
        handleObjectExpression(declaration, path, state)
      } else if (t.isCallExpression(declaration) &&
fxy060608's avatar
fxy060608 已提交
67 68
        t.isMemberExpression(declaration.callee) &&
        declaration.arguments.length === 1) { // export default Vue.extend({components:{}})
fxy060608's avatar
fxy060608 已提交
69
        if (declaration.callee.object.name === 'Vue' && declaration.callee.property.name ===
fxy060608's avatar
fxy060608 已提交
70
          'extend') {
fxy060608's avatar
fxy060608 已提交
71 72 73
          handleObjectExpression(declaration.arguments[0], path, state)
        }
      } else if (t.isClassDeclaration(declaration) &&
fxy060608's avatar
fxy060608 已提交
74 75
        declaration.decorators &&
        declaration.decorators.length) { // export default @Component({components:{}}) class MyComponent extend Vue
fxy060608's avatar
fxy060608 已提交
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
        const componentDecorator = declaration.decorators[0]
        if (t.isCallExpression(componentDecorator.expression)) {
          const args = componentDecorator.expression.arguments
          if (args && args.length && t.isObjectExpression(args[0])) {
            handleObjectExpression(args[0], path, state)
          }
        }
      }
    }
  })
  return {
    ast,
    state
  }
}