docs: function transformLayout(statement) {
      // Transform to layout function
      var actions = statement.expression.children;
  
      var blocks = [];
      var o = t.identifier('o');
      var type = t.memberExpression(o, t.identifier('type'));
      var config = t.memberExpression(o, t.identifier('config'));
      var childrenPush = t.memberExpression(
        t.memberExpression(o, t.identifier('children')),
        t.identifier('push')
      );
      var childrenUnshift = t.memberExpression(
        t.memberExpression(o, t.identifier('children')),
        t.identifier('unshift')
      );
      var element = t.memberExpression(o, t.identifier('element'));
      var stopRender = t.memberExpression(o, t.identifier('stopRender'));
  
      for (var ii = 0, actionsLength = actions.length; ii < actionsLength; ii++) {
        var action = actions[ii];
        if (!t.isJSXElement(action)) {
          continue;
        }
  
        // Check if conditions
        var tests = [], configCondition = true, falseCondition = false;
        var conditions = action.openingElement.attributes;
        var children = childrenPush;
        for (var j = 0, conditionsLength = conditions.length; j < conditionsLength; j++) {
          var condition = conditions[j];
          if (condition.name.name === 'type') {
            // Type condition
            if (t.isJSXExpressionContainer(condition.value)) {
              tests.push(t.binaryExpression(
                '===',
                type,
                condition.value.expression
              ));
            } else {
              falseCondition = true;
              break;
            }
          } else if (condition.name.name === '_top') {
            children = childrenUnshift;
          } else {
            if (configCondition) {
              tests.push(config);
              configCondition = false;
            }
            tests.push(t.binaryExpression(
              '===',
              t.memberExpression(config, t.stringLiteral(condition.name.name), true),
              t.isJSXExpressionContainer(condition.value) ?
                condition.value.expression :
                (condition.value === null ? t.booleanLiteral(true) : condition.value)
            ));
          }
        }
        if (falseCondition) {
          continue;
        }
  
        var statements = [];
        // Transform each action to block
        switch (action.openingElement.name.name) {
          // Transform content
          case 'addChildren':
          case 'update':
            for (var j = 0, childrenLen = action.children.length; j < childrenLen; j++) {
              var child = action.children[j];
              var param = undefined;
              if (t.isJSXElement(child)) {
                // @TODO process 'before' and 'after' element
                if (child.openingElement.name.name === 'props') {
                  // Update props
                  var attributes = child.openingElement.attributes;
                  for (var jj = 0, attsLength = attributes.length; jj < attsLength; jj++) {
                    if (jj === 0) {
                      statements.push(t.assignmentExpression('=', config, t.logicalExpression(
                        '||', config, t.objectExpression([])
                      )));
                    }
                    var att = attributes[jj];
                    var left = t.memberExpression(config, t.stringLiteral(att.name.name), true);
                    var right;
                    if (t.isJSXExpressionContainer(att.value)) {
                      right = att.value.expression;
                    } else if (att.value === null) {
                      right = t.booleanLiteral(true);
                    } else {
                      right = att.value;
                    }
                    statements.push(t.assignmentExpression('=', left, right));
                  }
                } else {
                  // JSX element
                  param = child;
                }
              } else if (t.isJSXExpressionContainer(child)) {
                // JS expression
                param = child.expression;
              } else if (child.value.trim().length > 0) {
                // Text string
                param = t.stringLiteral(child.value);
              }
              if (param !== undefined) {
                statements.push(t.callExpression(children, [param]))
              }
            }
            break;
          case 'replace':
            for (var j = 0, childrenLen = action.children.length; j < childrenLen; j++) {
              var child = action.children[j];
              if (t.isJSXExpressionContainer(child)) {
                statements.push(t.assignmentExpression('=', element, child.expression));
                break;
              } else if (t.isJSXElement(child)) {
                statements.push(t.assignmentExpression('=', element, child));
                break;
              }
            }
            break;
          case 'remove':
            statements.push(t.assignmentExpression('=', stopRender, t.booleanLiteral(true)));
            break;
          default:
            // Do not transform
        }
        if (statements.length === 0) {
          continue;
        }
        statements = statements.map(function(exp) {
          return t.expressionStatement(exp);
        });
  
        // Append to blocks
        if (tests.length === 0) {
          blocks = blocks.concat(statements);
        } else {
          blocks.push(t.ifStatement(
            tests.reduce(function(l, r) {
              return t.logicalExpression('&&', l, r);
            }),
            t.blockStatement(statements)
          ));
        }
      }
  
      statement.expression = t.assignmentExpression(
        '=',
        t.memberExpression(t.identifier('module'), t.identifier('exports')),
        t.functionExpression(null, [o], t.blockStatement(blocks))
      );
    }