Edit in JSFiddle

/*! angular-component v0.0.6 | (c) 2016 @toddmotto | https://github.com/toddmotto/angular-component */
(function () {

  var ng = angular.module;

  function identifierForController(controller, ident) {
    if (ident && typeof ident === 'string') return ident;
    if (typeof controller === 'string') {
      var match = /^(\S+)(\s+as\s+(\w+))?$/.exec(controller);
      if (match) return match[3];
    }
  }

  function module() {

    var hijacked = ng.apply(this, arguments);

    if (hijacked.component) {
      return hijacked;
    }

    function component(name, options) {

      function factory($injector) {

        function makeInjectable(fn) {
          var closure;
          var isArray = angular.isArray(fn);
          if (angular.isFunction(fn) || isArray) {
            return function (tElement, tAttrs) {
              return $injector.invoke((isArray ? fn : [
                '$element',
                '$attrs',
                fn
              ]), this, {
                $element: tElement,
                $attrs: tAttrs
              });
            };
          } else {
            return fn;
          }
        }

        return {
          controller: options.controller || angular.noop,
          controllerAs: identifierForController(options.controller) || options.controllerAs || '$ctrl',
          template: makeInjectable(
            !options.template && !options.templateUrl ? '' : options.template
          ),
          templateUrl: makeInjectable(options.templateUrl),
          transclude: options.transclude === undefined ? true : options.transclude,
          scope: options.bindings || {},
          bindToController: !!options.bindings,
          restrict: options.restrict || 'E'
        };

      }

      for (var key in options) {
        if (key.charAt(0) === '$') {
          factory[key] = options[key];
        }
      }

      factory.$inject = ['$injector'];

      return hijacked.directive(name, factory);

    }

    hijacked.component = component;

    return hijacked;

  }

  angular.module = module;

})();

angular
.module('app', [])
.component('counter', {
    bindings: {
      count: '='
    },
    $canActivate: true,
    controller: 'CounterCtrl as counter',
    template: function ($element, $attrs) {
      return [
        '<div class="counter">',
          '<p>Counter component</p>',
          '<input type="text" ng-model="counter.count">',
          '<button type="button" ng-click="counter.decrement();">-</button>',
          '<button type="button" ng-click="counter.increment();">+</button>',
        '</div>'
      ].join('');
    }
})
.controller('CounterCtrl', function CounterCtrl() {
  function increment() {
    this.count++;
  }
  function decrement() {
    this.count--;
  }
  this.increment = increment;
  this.decrement = decrement;
})
.controller('MainCtrl', function MainCtrl() {
  this.count = 4;
});
<div ng-app="app">
  <div ng-controller="MainCtrl as vm">
    <counter count="vm.count"></counter>
  </div>
</div>