├── .babelrc ├── .npmignore ├── .gitignore ├── example ├── .babelrc └── src │ ├── ExampleService.js │ ├── ExampleController.js │ ├── ExampleDirective.js │ └── index.js ├── .eslintrc ├── package.json ├── README.md ├── LICENSE └── src └── index.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | src 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | .idea 3 | logs 4 | *.log 5 | 6 | # Dependency directory 7 | node_modules 8 | lib 9 | -------------------------------------------------------------------------------- /example/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"], 3 | "plugins": [ 4 | "transform-class-properties", 5 | "syntax-decorators", 6 | "ng-annotate" 7 | ] 8 | } -------------------------------------------------------------------------------- /example/src/ExampleService.js: -------------------------------------------------------------------------------- 1 | @Inject('$http') 2 | class ExampleService { 3 | 4 | getData() { 5 | return this.$http.get('...'); 6 | } 7 | } 8 | 9 | export default ExampleService; 10 | -------------------------------------------------------------------------------- /example/src/ExampleController.js: -------------------------------------------------------------------------------- 1 | 2 | @Inject('$exService') 3 | export class ExampleController { 4 | 5 | constructor() { 6 | this.data = ''; 7 | } 8 | 9 | load() { 10 | this.$exService 11 | .getData() 12 | .then(data => { 13 | this.data = data; 14 | }); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "rules": { 4 | "strict": 0, 5 | "quotes": [2, "single"], 6 | "no-underscore-dangle": 0, 7 | "no-use-before-define": 0, 8 | "no-new-func": 0, 9 | "no-console": 0, 10 | "no-var": 1, 11 | "new-cap": 0 12 | }, 13 | "env": { 14 | "es6": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /example/src/ExampleDirective.js: -------------------------------------------------------------------------------- 1 | 2 | class ExampleDirective { 3 | 4 | restrict = 'E'; 5 | controller = 'ExampleController'; 6 | controllerAs = '$exCtrl'; 7 | template = ` 8 | 9 | {{$exCtrl.data}} 10 | `; 11 | 12 | } 13 | 14 | export default ExampleDirective; 15 | -------------------------------------------------------------------------------- /example/src/index.js: -------------------------------------------------------------------------------- 1 | import ExampleDirective from './ExampleDirective'; 2 | import ExampleController from './ExampleController'; 3 | import ExampleService from './ExampleService'; 4 | 5 | angular 6 | .module('example', []) 7 | .controller('ExampleController', ExampleController) 8 | .directive('exDirective', ExampleDirective) 9 | .service('$exService', ExampleService); 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "babel-plugin-ng-annotate", 3 | "version": "0.3.2", 4 | "description": "Babel Plugin for AngularJS dependency injection annotations.", 5 | "dependencies": { 6 | "babel-plugin-syntax-decorators": "^6.5.0", 7 | "babel-plugin-transform-class-properties": "^6.6.0", 8 | "babel-preset-es2015": "^6.6.0", 9 | "babel-runtime": "^6.3.13" 10 | }, 11 | "author": "Maciej Chmielarski ", 12 | "license": "MIT", 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/mchmielarski/babel-plugin-ng-annotate.git" 16 | }, 17 | "main": "lib/index.js", 18 | "scripts": { 19 | "build": "babel src --out-dir lib" 20 | }, 21 | "keywords": [ 22 | "babel", 23 | "babel-plugin", 24 | "angular", 25 | "annotate" 26 | ], 27 | "devDependencies": { 28 | "babel-cli": "^6.6.5" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # babel-plugin-ng-annotate - babel 6.x 2 | 3 | ## How to install 4 | 5 | ``` 6 | $ npm install --save-dev babel-plugin-ng-annotate 7 | ``` 8 | 9 | Note: this library depends on the [syntax decorators](https://www.npmjs.com/package/babel-plugin-syntax-decorators) plugin for parsing. Simply `$ npm install --save-dev babel-plugin-syntax-decorators` and follow the setup instructions below. 10 | 11 | ## How to setup 12 | 13 | #### .babelrc 14 | ```js 15 | { 16 | "presets": ["es2015"], 17 | "plugins": ["syntax-decorators", "ng-annotate"] 18 | } 19 | ``` 20 | 21 | 22 | ## How to use 23 | 24 | ```js 25 | @Inject('service1', 'service2', 'service3') 26 | class MyController { 27 | 28 | constructor() { 29 | this.service1(); 30 | } 31 | 32 | method() { 33 | this.service2(); 34 | } 35 | 36 | anotherMethod() { 37 | this.service3(); 38 | } 39 | } 40 | 41 | angular.controller('MyController', MyController); 42 | ``` 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Maciej Chmielarski 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export default function ({ types: t }) { 2 | return { 3 | visitor: { 4 | ClassDeclaration(path) { 5 | if (!path.node.decorators) { 6 | return; 7 | } 8 | const inject = path.node.decorators.find(decorator => decorator.expression.callee.name === 'Inject'); 9 | 10 | if (!inject) { 11 | return; 12 | } 13 | path.node.decorators = path.node.decorators.splice(path.node.decorators.indexOf(inject), 1); 14 | 15 | const toInject = inject.expression.arguments.map(arg => arg.value); 16 | let ctor = path.node.body.body.find(el => el.kind === 'constructor'); 17 | let toParam; 18 | 19 | if (!ctor) { 20 | ctor = t.classMethod( 21 | 'constructor', 22 | t.identifier('constructor'), 23 | [], 24 | t.blockStatement([]) 25 | ); 26 | if (path.node.superClass) { 27 | ctor.body.body.unshift( 28 | t.expressionStatement(t.callExpression(t.super(), [])) 29 | ); 30 | } 31 | path.node.body.body.unshift(ctor); 32 | toParam = toInject; 33 | } else { 34 | toParam = toInject.filter(param => !ctor.params.find(p => p.name === param)); 35 | } 36 | 37 | toParam.forEach(i => { 38 | let fCmd; 39 | let sup; 40 | if (Array.isArray(ctor.body.body)) { 41 | fCmd = ctor.body.body[0]; 42 | } else { 43 | fCmd = ctor.body.body; 44 | } 45 | if (fCmd && fCmd.expression && fCmd.expression.callee && fCmd.expression.callee.type === 'Super') { 46 | sup = ctor.body.body.shift(); 47 | } 48 | 49 | ctor.body.body.unshift( 50 | t.expressionStatement( 51 | t.assignmentExpression( 52 | '=', 53 | t.memberExpression(t.thisExpression(), t.identifier(i)), 54 | t.identifier(i) 55 | ) 56 | ) 57 | ); 58 | 59 | if (sup) { 60 | ctor.body.body.unshift(sup); 61 | } 62 | }) 63 | 64 | ctor.params = ctor.params.concat(toParam.map(i => t.identifier(i))); 65 | 66 | const injectExp = t.expressionStatement(t.assignmentExpression( 67 | '=', 68 | t.memberExpression( 69 | t.identifier(path.node.id.name), 70 | t.identifier('$inject')), 71 | t.arrayExpression(toInject.map(d => t.stringLiteral(d))) 72 | )); 73 | 74 | if (path.parentPath.type === 'ExportNamedDeclaration') { 75 | path.parentPath.insertAfter(injectExp); 76 | } else { 77 | path.insertAfter(injectExp); 78 | } 79 | } 80 | } 81 | }; 82 | }; 83 | --------------------------------------------------------------------------------