All files index.js

100% Statements 34/34
100% Branches 22/22
100% Functions 12/12
100% Lines 29/29
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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 761x   16x 16x         12x 26x 26x           12x 26x 17x 17x     9x 3x         6x 1x         5x 26x   1x   1x 1x 1x       12x 12x   12x       12x 12x 12x         12x       13x   10x                    
 const babelPluginSyntaxJSX = require('babel-plugin-syntax-jsx')
 
const componentExpression = t => properties => (
  t.callExpression(t.memberExpression(t.identifier('Gruu'), t.identifier('createComponent')), [
    t.objectExpression(properties)
  ])
)
 
const prepareChildren = t => children => children.reduce((acc, child) => {
  const item = child.expression || child
  return {
    dynamic: acc.dynamic || t.isFunction(item),
    items: [...acc.items, item]
  }
}, { items: [], dynamic: false })
 
const parseChildren = t => children => children.map(child => {
  if (t.isJSXText(child) || t.isStringLiteral(child)) {
    const string = child.value.replace(/^[\n ]*/g, '').replace(/[\n ]*$/g, '')
    return string ? t.stringLiteral(string) : null
  }
 
  if (t.isFunction(child)) {
    return componentExpression(t)([
      t.objectProperty(t.identifier('$children'), child)
    ])
  }
 
  if (t.isArrayExpression(child) || t.isCallExpression(child)) {
    return componentExpression(t)([
      t.objectProperty(t.identifier('children'), child)
    ])
  }
 
  return child
}).filter(v => v)
 
const excludedAttributes = ['_type', 'children', '$children']
 
module.exports = (babel) => {
  const t = babel.types
  return {
    inherits: babelPluginSyntaxJSX,
    visitor: {
      JSXElement (path) {
        const { openingElement, children } = path.node
        const { name: { name: componentType }, attributes } = openingElement
 
        const typeProperty = componentType !== '$'
          ? [t.objectProperty(t.identifier('_type'), t.stringLiteral(componentType))]
          : []
 
        const preparedChildren = prepareChildren(t)(children)
        const items = (parseChildren(t)(preparedChildren.items))
        const childrenProperty = items.length > 0 ? [t.objectProperty(
          t.identifier('children'),
          t.arrayExpression(items)
        )] : []
 
        path.replaceWith(componentExpression(t)([
          ...typeProperty,
          ...childrenProperty,
          ...attributes
            .filter(({ name }) => !excludedAttributes.includes(name.name))
            .map(({ name, value }) => (
              t.objectProperty(
                t.identifier(name.name),
                t.isStringLiteral(value) ? value : value.expression
              )
            ))
        ]))
      }
    }
  }
}