├── .eslintignore ├── src ├── index.js └── core.js ├── .npmignore ├── .travis.yml ├── .gitignore ├── test ├── fixtures │ ├── execute-direct │ │ ├── actual.js │ │ └── expected.js │ ├── as-arguments │ │ ├── actual.js │ │ └── expected.js │ ├── execute-member │ │ ├── actual.js │ │ └── expected.js │ ├── multiple-words │ │ ├── actual.js │ │ └── expected.js │ ├── variable-declarator │ │ ├── actual.js │ │ └── expected.js │ ├── camel-to-dash-option │ │ ├── actual.js │ │ └── expected.js │ ├── array │ │ ├── actual.js │ │ └── expected.js │ ├── property │ │ ├── actual.js │ │ └── expected.js │ ├── import-theme │ │ ├── actual.js │ │ └── expected.js │ ├── import-all-css │ │ ├── actual.js │ │ └── expected.js │ ├── import-module │ │ ├── actual.js │ │ └── expected.js │ ├── import-theme-custom │ │ ├── actual.js │ │ └── expected.js │ ├── import-theme-custom-path │ │ ├── actual.js │ │ └── expected.js │ ├── independent-theme-package │ │ ├── actual.js │ │ └── expected.js │ ├── react-element │ │ ├── actual.js │ │ └── expected.js │ ├── independent-theme-package-mixin │ │ ├── actual.js │ │ └── expected.js │ ├── independent-theme-package-custom │ │ ├── actual.js │ │ └── expected.js │ ├── assignment-expression │ │ ├── actual.js │ │ └── expected.js │ ├── specifier-alias │ │ ├── actual.js │ │ └── expected.js │ ├── import-theme-all-compo │ │ ├── actual.js │ │ └── expected.js │ ├── import-css │ │ ├── actual.js │ │ └── expected.js │ ├── custom-css-filename │ │ ├── actual.js │ │ └── expected.js │ ├── conditions │ │ ├── actual.js │ │ └── expected.js │ └── multiple-module │ │ ├── actual.js │ │ └── expected.js └── index-test.js ├── .eslintrc ├── package.json └── README.md /.eslintignore: -------------------------------------------------------------------------------- 1 | **/*/__tests__ 2 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./core')('element-ui'); 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .idea 2 | tmp 3 | node_modules 4 | coverage 5 | __tests__ 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - "4" 5 | - "5" 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | tmp 3 | node_modules 4 | coverage 5 | lib 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /test/fixtures/execute-direct/actual.js: -------------------------------------------------------------------------------- 1 | import { message } from 'element-ui'; 2 | 3 | message('xxx'); 4 | -------------------------------------------------------------------------------- /test/fixtures/as-arguments/actual.js: -------------------------------------------------------------------------------- 1 | import { Modal } from 'element-ui'; 2 | const _Modal = bind({})(Modal); 3 | -------------------------------------------------------------------------------- /test/fixtures/execute-member/actual.js: -------------------------------------------------------------------------------- 1 | import { message } from 'element-ui'; 2 | 3 | message.success('xxx'); 4 | -------------------------------------------------------------------------------- /test/fixtures/multiple-words/actual.js: -------------------------------------------------------------------------------- 1 | import { InputNumber } from 'element-ui'; 2 | 3 | ; 4 | -------------------------------------------------------------------------------- /test/fixtures/variable-declarator/actual.js: -------------------------------------------------------------------------------- 1 | import { Button } from 'element-ui'; 2 | 3 | const a = Button; 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint-config-airbnb/base", 3 | "rules": { 4 | "no-console": [0] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/fixtures/camel-to-dash-option/actual.js: -------------------------------------------------------------------------------- 1 | import { inputNumber } from 'antd'; 2 | 3 | console.log(inputNumber); 4 | -------------------------------------------------------------------------------- /test/fixtures/array/actual.js: -------------------------------------------------------------------------------- 1 | import { Button } from 'element-ui'; 2 | 3 | new Vue({ 4 | components: [Button] 5 | }); 6 | -------------------------------------------------------------------------------- /test/fixtures/property/actual.js: -------------------------------------------------------------------------------- 1 | import { Button } from 'element-ui'; 2 | 3 | ReactDOM.render(
); 4 | -------------------------------------------------------------------------------- /test/fixtures/import-theme/actual.js: -------------------------------------------------------------------------------- 1 | import { Button, Alert } from 'element-ui'; 2 | 3 | console.log(Button); 4 | console.log(Alert); 5 | -------------------------------------------------------------------------------- /test/fixtures/import-all-css/actual.js: -------------------------------------------------------------------------------- 1 | import Element from 'element-ui'; 2 | 3 | console.log(Element.Button); 4 | console.log(Element); 5 | -------------------------------------------------------------------------------- /test/fixtures/import-module/actual.js: -------------------------------------------------------------------------------- 1 | import Element from 'element-ui'; 2 | 3 | console.log(Element.Button); 4 | console.log(Element); 5 | -------------------------------------------------------------------------------- /test/fixtures/import-theme-custom/actual.js: -------------------------------------------------------------------------------- 1 | import { Button, Alert } from 'element-ui4'; 2 | 3 | console.log(Button); 4 | console.log(Alert); 5 | -------------------------------------------------------------------------------- /test/fixtures/import-theme-custom-path/actual.js: -------------------------------------------------------------------------------- 1 | import { Button, Alert } from 'element-ui5'; 2 | 3 | console.log(Button); 4 | console.log(Alert); 5 | -------------------------------------------------------------------------------- /test/fixtures/independent-theme-package/actual.js: -------------------------------------------------------------------------------- 1 | import { Button, Alert } from 'element-ui3'; 2 | 3 | console.log(Button); 4 | console.log(Alert); 5 | -------------------------------------------------------------------------------- /test/fixtures/react-element/actual.js: -------------------------------------------------------------------------------- 1 | import { Button } from 'element-ui'; 2 | 3 | ReactDOM.render(
4 | 5 |
); 6 | -------------------------------------------------------------------------------- /test/fixtures/independent-theme-package-mixin/actual.js: -------------------------------------------------------------------------------- 1 | import { Button, Alert } from 'element-ui7'; 2 | 3 | console.log(Button); 4 | console.log(Alert); 5 | -------------------------------------------------------------------------------- /test/fixtures/independent-theme-package-custom/actual.js: -------------------------------------------------------------------------------- 1 | import { Button, Alert } from 'element-ui6'; 2 | 3 | console.log(Button); 4 | console.log(Alert); 5 | -------------------------------------------------------------------------------- /test/fixtures/assignment-expression/actual.js: -------------------------------------------------------------------------------- 1 | import { MessageBox } from 'element-ui'; 2 | import Vue from 'vue'; 3 | 4 | Vue.$prototype.$message = MessageBox; 5 | -------------------------------------------------------------------------------- /test/fixtures/specifier-alias/actual.js: -------------------------------------------------------------------------------- 1 | import { Button as Button1 } from 'element-ui'; 2 | 3 | ReactDOM.render(
4 | xxxx 5 |
); 6 | -------------------------------------------------------------------------------- /test/fixtures/import-theme-all-compo/actual.js: -------------------------------------------------------------------------------- 1 | import Components from 'element-ui2'; 2 | import { Button, Alert } from 'element-ui2'; 3 | 4 | console.log(Components); 5 | console.log(Button, Alert); 6 | -------------------------------------------------------------------------------- /test/fixtures/import-css/actual.js: -------------------------------------------------------------------------------- 1 | import { message } from 'element-ui'; 2 | import { Button } from 'element-ui'; 3 | 4 | message('xxx'); 5 | ReactDOM.render(
6 | 7 |
); 8 | -------------------------------------------------------------------------------- /test/fixtures/custom-css-filename/actual.js: -------------------------------------------------------------------------------- 1 | import { message } from 'element-ui'; 2 | import { Button } from 'element-ui'; 3 | 4 | message('xxx'); 5 | ReactDOM.render(
6 | 7 |
); 8 | -------------------------------------------------------------------------------- /test/fixtures/conditions/actual.js: -------------------------------------------------------------------------------- 1 | import { Select } from 'element-ui'; 2 | 3 | if (a === Select) {} 4 | if (Select) {} 5 | 6 | Select ? 'a' : 'b'; 7 | a ? Select : 2; 8 | 9 | Select || 'a'; 10 | a || Select; 11 | -------------------------------------------------------------------------------- /test/fixtures/execute-direct/expected.js: -------------------------------------------------------------------------------- 1 | require("element-ui/lib/message/style.css"); 2 | 3 | var _message = _interopRequireDefault(require("element-ui/lib/message")).default; 4 | 5 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 6 | 7 | _message('xxx'); 8 | -------------------------------------------------------------------------------- /test/fixtures/variable-declarator/expected.js: -------------------------------------------------------------------------------- 1 | require("element-ui/lib/button/style.css"); 2 | 3 | var _Button = _interopRequireDefault(require("element-ui/lib/button")).default; 4 | 5 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 6 | 7 | var a = _Button; 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/as-arguments/expected.js: -------------------------------------------------------------------------------- 1 | require("element-ui/lib/modal/style.css"); 2 | 3 | var _Modal2 = _interopRequireDefault(require("element-ui/lib/modal")).default; 4 | 5 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 6 | 7 | var _Modal = bind({})(_Modal2); 8 | -------------------------------------------------------------------------------- /test/fixtures/execute-member/expected.js: -------------------------------------------------------------------------------- 1 | require("element-ui/lib/message/style.css"); 2 | 3 | var _message = _interopRequireDefault(require("element-ui/lib/message")).default; 4 | 5 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 6 | 7 | _message.success('xxx'); 8 | -------------------------------------------------------------------------------- /test/fixtures/camel-to-dash-option/expected.js: -------------------------------------------------------------------------------- 1 | require("antd/lib/inputNumber/style.css"); 2 | 3 | var _inputNumber = _interopRequireDefault(require("antd/lib/inputNumber")).default; 4 | 5 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 6 | 7 | console.log(_inputNumber); 8 | -------------------------------------------------------------------------------- /test/fixtures/array/expected.js: -------------------------------------------------------------------------------- 1 | require("element-ui/lib/button/style.css"); 2 | 3 | var _Button = _interopRequireDefault(require("element-ui/lib/button")).default; 4 | 5 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 6 | 7 | new Vue({ 8 | components: [_Button] 9 | }); 10 | -------------------------------------------------------------------------------- /test/fixtures/import-all-css/expected.js: -------------------------------------------------------------------------------- 1 | require("element-ui/lib/style.css"); 2 | 3 | var _Element = _interopRequireDefault(require("element-ui/lib")).default; 4 | 5 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 6 | 7 | console.log(_Element.Button); 8 | console.log(_Element); 9 | -------------------------------------------------------------------------------- /test/fixtures/import-module/expected.js: -------------------------------------------------------------------------------- 1 | require("element-ui/lib/abc/style.css"); 2 | 3 | var _Element = _interopRequireDefault(require("element-ui/lib/abc")).default; 4 | 5 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 6 | 7 | console.log(_Element.Button); 8 | console.log(_Element); 9 | -------------------------------------------------------------------------------- /test/fixtures/multiple-module/actual.js: -------------------------------------------------------------------------------- 1 | import { message } from 'antd'; 2 | import { Button } from 'antd'; 3 | import { Alert2 } from 'antd'; 4 | import { Alert } from 'test-module'; 5 | 6 | message('xxx'); 7 | ReactDOM.render(
8 | 9 | xxxx 10 | xxx 11 |
); 12 | -------------------------------------------------------------------------------- /test/fixtures/multiple-words/expected.js: -------------------------------------------------------------------------------- 1 | require("element-ui/lib/input-number/style.css"); 2 | 3 | var _InputNumber = _interopRequireDefault(require("element-ui/lib/input-number")).default; 4 | 5 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 6 | 7 | React.createElement(_InputNumber, null); 8 | -------------------------------------------------------------------------------- /test/fixtures/property/expected.js: -------------------------------------------------------------------------------- 1 | require("element-ui/lib/button/style.css"); 2 | 3 | var _Button = _interopRequireDefault(require("element-ui/lib/button")).default; 4 | 5 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 6 | 7 | ReactDOM.render(React.createElement("div", { 8 | component: _Button 9 | })); 10 | -------------------------------------------------------------------------------- /test/fixtures/specifier-alias/expected.js: -------------------------------------------------------------------------------- 1 | require("element-ui/lib/button/style.css"); 2 | 3 | var _Button = _interopRequireDefault(require("element-ui/lib/button")).default; 4 | 5 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 6 | 7 | ReactDOM.render(React.createElement("div", null, React.createElement(_Button, null, "xxxx"))); 8 | -------------------------------------------------------------------------------- /test/fixtures/react-element/expected.js: -------------------------------------------------------------------------------- 1 | require("element-ui/lib/button/style.css"); 2 | 3 | var _Button = _interopRequireDefault(require("element-ui/lib/button")).default; 4 | 5 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 6 | 7 | ReactDOM.render(React.createElement("div", null, React.createElement(_Button, null, "xxxx"))); 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/conditions/expected.js: -------------------------------------------------------------------------------- 1 | require("element-ui/lib/select/style.css"); 2 | 3 | var _Select = _interopRequireDefault(require("element-ui/lib/select")).default; 4 | 5 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 6 | 7 | if (a === _Select) {} 8 | 9 | if (_Select) {} 10 | 11 | _Select ? 'a' : 'b'; 12 | a ? _Select : 2; 13 | _Select || 'a'; 14 | a || _Select; 15 | -------------------------------------------------------------------------------- /test/fixtures/assignment-expression/expected.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | require("element-ui/lib/message-box/style.css"); 4 | 5 | var _messageBox = _interopRequireDefault(require("element-ui/lib/message-box")); 6 | 7 | var _vue = _interopRequireDefault(require("vue")); 8 | 9 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 10 | 11 | _vue.default.$prototype.$message = _messageBox.default; 12 | -------------------------------------------------------------------------------- /test/fixtures/import-css/expected.js: -------------------------------------------------------------------------------- 1 | require("element-ui/lib/button/style.css"); 2 | 3 | var _Button = _interopRequireDefault(require("element-ui/lib/button")).default; 4 | 5 | require("element-ui/lib/message/style.css"); 6 | 7 | var _message = _interopRequireDefault(require("element-ui/lib/message")).default; 8 | 9 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 10 | 11 | _message('xxx'); 12 | 13 | ReactDOM.render(React.createElement("div", null, React.createElement(_Button, null, "xxxx"))); 14 | -------------------------------------------------------------------------------- /test/fixtures/custom-css-filename/expected.js: -------------------------------------------------------------------------------- 1 | require("element-ui/lib/button/style.css"); 2 | 3 | var _Button = _interopRequireDefault(require("element-ui/lib/button")).default; 4 | 5 | require("element-ui/lib/message/style.css"); 6 | 7 | var _message = _interopRequireDefault(require("element-ui/lib/message")).default; 8 | 9 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 10 | 11 | _message('xxx'); 12 | 13 | ReactDOM.render(React.createElement("div", null, React.createElement(_Button, null, "xxxx"))); 14 | -------------------------------------------------------------------------------- /test/fixtures/import-theme-custom/expected.js: -------------------------------------------------------------------------------- 1 | var _Alert2 = _interopRequireDefault(require("element-ui4/lib/theme-custom/alert.css")).default; 2 | 3 | var _Alert = _interopRequireDefault(require("element-ui4/lib/alert")).default; 4 | 5 | var _Button2 = _interopRequireDefault(require("element-ui4/lib/theme-custom/button.css")).default; 6 | 7 | var _Button = _interopRequireDefault(require("element-ui4/lib/button")).default; 8 | 9 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 10 | 11 | console.log(_Button); 12 | console.log(_Alert); 13 | -------------------------------------------------------------------------------- /test/fixtures/independent-theme-package-mixin/expected.js: -------------------------------------------------------------------------------- 1 | var _Alert2 = _interopRequireDefault(require("element-ui7/lib/alert/style.css")).default; 2 | 3 | var _Alert = _interopRequireDefault(require("element-ui7/lib/alert")).default; 4 | 5 | var _Button2 = _interopRequireDefault(require("element-ui7/lib/button/style.css")).default; 6 | 7 | var _Button = _interopRequireDefault(require("element-ui7/lib/button")).default; 8 | 9 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 10 | 11 | console.log(_Button); 12 | console.log(_Alert); 13 | -------------------------------------------------------------------------------- /test/fixtures/import-theme-custom-path/expected.js: -------------------------------------------------------------------------------- 1 | var _Alert2 = _interopRequireDefault(require("element-ui5/lib/theme-custom-path/alert/alert.css")).default; 2 | 3 | var _Alert = _interopRequireDefault(require("element-ui5/lib/alert")).default; 4 | 5 | var _Button2 = _interopRequireDefault(require("element-ui5/lib/theme-custom-path/button/button.css")).default; 6 | 7 | var _Button = _interopRequireDefault(require("element-ui5/lib/button")).default; 8 | 9 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 10 | 11 | console.log(_Button); 12 | console.log(_Alert); 13 | -------------------------------------------------------------------------------- /test/fixtures/independent-theme-package/expected.js: -------------------------------------------------------------------------------- 1 | var _Alert2 = _interopRequireDefault(require("__theme__/theme/alert.css")).default; 2 | 3 | require("__theme__/theme/base.css"); 4 | 5 | var _Alert = _interopRequireDefault(require("element-ui3/lib/alert")).default; 6 | 7 | var _Button2 = _interopRequireDefault(require("__theme__/theme/button.css")).default; 8 | 9 | require("__theme__/theme/base.css"); 10 | 11 | var _Button = _interopRequireDefault(require("element-ui3/lib/button")).default; 12 | 13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 14 | 15 | console.log(_Button); 16 | console.log(_Alert); -------------------------------------------------------------------------------- /test/fixtures/independent-theme-package-custom/expected.js: -------------------------------------------------------------------------------- 1 | var _Alert2 = _interopRequireDefault(require("__theme__/theme/alert/alert.css")).default; 2 | 3 | require("__theme__/theme/base.css"); 4 | 5 | var _Alert = _interopRequireDefault(require("element-ui6/lib/alert")).default; 6 | 7 | var _Button2 = _interopRequireDefault(require("__theme__/theme/button/button.css")).default; 8 | 9 | require("__theme__/theme/base.css"); 10 | 11 | var _Button = _interopRequireDefault(require("element-ui6/lib/button")).default; 12 | 13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 14 | 15 | console.log(_Button); 16 | console.log(_Alert); 17 | -------------------------------------------------------------------------------- /test/fixtures/import-theme/expected.js: -------------------------------------------------------------------------------- 1 | var _Alert2 = _interopRequireDefault(require("element-ui/lib/theme-default/alert.css")).default; 2 | 3 | require("element-ui/lib/theme-default/base.css"); 4 | 5 | var _Alert = _interopRequireDefault(require("element-ui/lib/alert")).default; 6 | 7 | var _Button2 = _interopRequireDefault(require("element-ui/lib/theme-default/button.css")).default; 8 | 9 | require("element-ui/lib/theme-default/base.css"); 10 | 11 | var _Button = _interopRequireDefault(require("element-ui/lib/button")).default; 12 | 13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 14 | 15 | console.log(_Button); 16 | console.log(_Alert); 17 | -------------------------------------------------------------------------------- /test/fixtures/import-theme-all-compo/expected.js: -------------------------------------------------------------------------------- 1 | var _Alert2 = _interopRequireDefault(require("element-ui2/lib/alert")).default; 2 | 3 | var _Alert = _interopRequireDefault(require("element-ui2/lib/alert")).default; 4 | 5 | var _Button2 = _interopRequireDefault(require("element-ui2/lib/button")).default; 6 | 7 | var _Button = _interopRequireDefault(require("element-ui2/lib/button")).default; 8 | 9 | var _Components2 = _interopRequireDefault(require("element-ui2/lib/theme-default/index.css")).default; 10 | 11 | var _Components = _interopRequireDefault(require("element-ui2/lib")).default; 12 | 13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 14 | 15 | console.log(_Components); 16 | console.log(_Button, _Alert); 17 | -------------------------------------------------------------------------------- /test/fixtures/multiple-module/expected.js: -------------------------------------------------------------------------------- 1 | require("antd/lib/alert2/style.css"); 2 | 3 | var _Alert2 = _interopRequireDefault(require("antd/lib/alert2")).default; 4 | 5 | require("test-module/lib/alert/style.css"); 6 | 7 | var _Alert = _interopRequireDefault(require("test-module/lib/alert")).default; 8 | 9 | require("antd/lib/button/style.css"); 10 | 11 | var _Button = _interopRequireDefault(require("antd/lib/button")).default; 12 | 13 | require("antd/lib/message/style.css"); 14 | 15 | var _message = _interopRequireDefault(require("antd/lib/message")).default; 16 | 17 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 18 | 19 | _message('xxx'); 20 | 21 | ReactDOM.render(React.createElement("div", null, React.createElement(_Button, null, "xxxx"), React.createElement(_Alert, null, "xxxx"), React.createElement(_Alert2, null, "xxx"))); 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "babel-plugin-component", 3 | "version": "1.1.1", 4 | "description": "Modular build plugin for babel.", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "build": "rm -rf lib && babel src --out-dir lib --ignore __tests__", 8 | "test": "mocha --require @babel/register", 9 | "debug": "mocha --require @babel/register --require @babel/polyfill --no-timeouts", 10 | "lint": "eslint --ext .js src", 11 | "coveralls": "cat ./coverage/lcov.info | coveralls", 12 | "prepublish": "npm run build" 13 | }, 14 | "pre-commit": [ 15 | "lint" 16 | ], 17 | "keywords": [ 18 | "babel-plugin" 19 | ], 20 | "author": [ 21 | "chencheng ", 22 | "qingwei-li " 23 | ], 24 | "license": "MIT", 25 | "devDependencies": { 26 | "@babel/cli": "7.0.0-beta.35", 27 | "@babel/core": "7.0.0-beta.35", 28 | "@babel/node": "7.0.0-beta.35", 29 | "@babel/preset-env": "7.0.0-beta.35", 30 | "@babel/preset-react": "7.0.0-beta.35", 31 | "@babel/preset-stage-0": "7.0.0-beta.35", 32 | "@babel/register": "7.0.0-beta.35", 33 | "coveralls": "^2.11.6", 34 | "eslint": "^2.7.0", 35 | "eslint-config-airbnb": "^6.2.0", 36 | "expect": "^1.13.4", 37 | "mocha": "4.0.1", 38 | "pre-commit": "~1.1.2" 39 | }, 40 | "repository": "ElementUI/babel-plugin-component", 41 | "homepage": "https://github.com/ElementUI/babel-plugin-component#readme", 42 | "bugs": { 43 | "url": "https://github.com/ElementUI/babel-plugin-component/issues" 44 | }, 45 | "babel": { 46 | "presets": [ 47 | "@babel/preset-env", 48 | "@babel/preset-react" 49 | ] 50 | }, 51 | "files": [ 52 | "lib", 53 | "package.json", 54 | "README.md" 55 | ], 56 | "dependencies": { 57 | "@babel/helper-module-imports": "7.0.0-beta.35" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # babel-plugin-component 2 | 3 | [![NPM version](https://img.shields.io/npm/v/babel-plugin-component.svg)](https://npmjs.org/package/babel-plugin-component) 4 | [![Build Status](https://travis-ci.org/ElementUI/babel-plugin-component.svg?branch=master)](https://travis-ci.org/ElementUI/babel-plugin-component) 5 | [![Coverage Status](https://coveralls.io/repos/github/QingWei-Li/babel-plugin-component/badge.svg?branch=master)](https://coveralls.io/github/QingWei-Li/babel-plugin-component?branch=master) 6 | 7 | ## Install 8 | 9 | ```shell 10 | npm i babel-plugin-component -D 11 | 12 | # For babel6 13 | npm i babel-plugin-component@0 -D 14 | ``` 15 | 16 | ## Example 17 | 18 | Converts 19 | 20 | ```javascript 21 | import { Button } from 'components' 22 | ``` 23 | 24 | to 25 | 26 | ```javascript 27 | var button = require('components/lib/button') 28 | require('components/lib/button/style.css') 29 | ``` 30 | 31 | ## styleLibraryName Example 32 | 33 | Converts 34 | 35 | ```javascript 36 | import Components from 'components' 37 | import { Button } from 'components' 38 | ``` 39 | 40 | to 41 | 42 | ```javascript 43 | require('components/lib/styleLibraryName/index.css') 44 | var button = require('components/lib/styleLibraryName/button.css') 45 | ``` 46 | 47 | ## Usage 48 | 49 | Via `.babelrc` or babel-loader. 50 | 51 | ```javascript 52 | { 53 | "plugins": [["component", options]] 54 | } 55 | ``` 56 | 57 | ## Multiple Module 58 | ```javascript 59 | { 60 | "plugins": [xxx, 61 | ["component", { 62 | libraryName: "antd", 63 | style: true, 64 | }, "antd"], 65 | ["component", { 66 | libraryName: "test-module", 67 | style: true, 68 | }, "test-module"] 69 | ] 70 | } 71 | ``` 72 | 73 | ### Component directory structure 74 | ``` 75 | - lib // 'libDir' 76 | - index.js // or custom 'root' relative path 77 | - style.css // or custom 'style' relative path 78 | - componentA 79 | - index.js 80 | - style.css 81 | - componentB 82 | - index.js 83 | - style.css 84 | ``` 85 | 86 | ### Theme library directory structure 87 | ``` 88 | - lib 89 | - theme-default // 'styleLibraryName' 90 | - base.css // required 91 | - index.css // required 92 | - componentA.css 93 | - componentB.css 94 | - theme-material 95 | - ... 96 | - componentA 97 | - index.js 98 | - componentB 99 | - index.js 100 | ``` 101 | or 102 | ``` 103 | - lib 104 | - theme-custom // 'styleLibrary.name' 105 | - base.css // if styleLibrary.base true 106 | - index.css // required 107 | - componentA.css // default 108 | - componentB.css 109 | - theme-material 110 | - componentA 111 | -index.css // styleLibrary.path [module]/index.css 112 | - componentB 113 | -index.css 114 | - componentA 115 | - index.js 116 | - componentB 117 | - index.js 118 | ``` 119 | 120 | ### options 121 | 122 | - `["component"]`: import js modularly 123 | - `["component", { "libraryName": "component" }]`: module name 124 | - `["component", { "styleLibraryName": "theme_package" }]`: style module name 125 | - `["component", { "styleLibraryName": "~independent_theme_package" }]`: Import a independent theme package 126 | - `["component", { "styleLibrary": {} }]`: Import a independent theme package with more config 127 | ``` 128 | styleLibrary: { 129 | "name": "xxx", // same with styleLibraryName 130 | "base": true, // if theme package has a base.css 131 | "path": "[module]/index.css", // the style path. e.g. module Alert => alert/index.css 132 | "mixin": true // if theme-package not found css file, then use [libraryName]'s css file 133 | } 134 | ``` 135 | - `["component", { "style": true }]`: import js and css from 'style.css' 136 | - `["component", { "style": cssFilePath }]`: import style css from filePath 137 | - `["component", { "libDir": "lib" }]`: lib directory 138 | - `["component", { "root": "index" }]`: main file dir 139 | - `["component", { "camel2Dash": false }]`: whether parse name to dash mode or not, default `true` 140 | -------------------------------------------------------------------------------- /test/index-test.js: -------------------------------------------------------------------------------- 1 | import { transformFileSync } from '@babel/core'; 2 | import { join } from 'path'; 3 | import { readdirSync, readFileSync } from 'fs'; 4 | import plugin from '../src/index'; 5 | import expect from 'expect'; 6 | import { resolve } from 'path'; 7 | 8 | describe('index', () => { 9 | const fixturesDir = join(__dirname, 'fixtures'); 10 | let fixtures = readdirSync(fixturesDir); 11 | const onlyFixtures = fixtures.filter(fixture => fixture.indexOf('-only') > -1); 12 | 13 | if (onlyFixtures.length) { 14 | fixtures = onlyFixtures; 15 | } 16 | 17 | fixtures.map(caseName => { 18 | const fixtureDir = join(fixturesDir, caseName); 19 | const actualFile = join(fixtureDir, 'actual.js'); 20 | const expectedFile = join(fixtureDir, 'expected.js'); 21 | let expected = readFileSync(expectedFile, 'utf-8'); 22 | 23 | it(`should work with ${caseName.split('-').join(' ')}`, () => { 24 | 25 | let cssPlugin; 26 | if (caseName === 'import-css') { 27 | cssPlugin = [plugin, { 28 | style: true, 29 | }]; 30 | } 31 | 32 | if (caseName === 'import-module') { 33 | cssPlugin = [plugin, { 34 | style: true, 35 | root: 'abc', 36 | }]; 37 | } 38 | 39 | if (caseName === 'import-all-css') { 40 | cssPlugin = [plugin, { 41 | style: true, 42 | }]; 43 | } 44 | 45 | if (caseName === 'import-theme') { 46 | cssPlugin = [plugin, { 47 | libraryName: 'element-ui', 48 | styleLibraryName: 'theme-default', 49 | }]; 50 | } 51 | 52 | if (caseName === 'import-theme-custom') { 53 | cssPlugin = [plugin, { 54 | libraryName: 'element-ui4', 55 | styleLibrary: { 56 | base: false, 57 | name: 'theme-custom', 58 | }, 59 | }]; 60 | } 61 | 62 | if (caseName === 'import-theme-custom-path') { 63 | cssPlugin = [plugin, { 64 | libraryName: 'element-ui5', 65 | styleLibrary: { 66 | base: false, 67 | name: 'theme-custom-path', 68 | path: '[module]/[module].css', 69 | }, 70 | }]; 71 | } 72 | 73 | if (caseName === 'import-theme-all-compo') { 74 | cssPlugin = [plugin, { 75 | libraryName: 'element-ui2', 76 | styleLibraryName: 'theme-default', 77 | }]; 78 | } 79 | 80 | if (caseName === 'independent-theme-package') { 81 | expected = expected.replace(/__theme__/g, process.cwd()); 82 | cssPlugin = [plugin, { 83 | libraryName: 'element-ui3', 84 | styleLibraryName: '~theme', 85 | }]; 86 | } 87 | 88 | if (caseName === 'independent-theme-package-custom') { 89 | expected = expected.replace(/__theme__/g, process.cwd()); 90 | cssPlugin = [plugin, { 91 | libraryName: 'element-ui6', 92 | styleLibrary: { 93 | base: true, 94 | name: '~theme', 95 | path: '[module]/[module].css', 96 | }, 97 | }]; 98 | } 99 | 100 | if (caseName === 'independent-theme-package-mixin') { 101 | cssPlugin = [plugin, { 102 | libraryName: 'element-ui7', 103 | styleLibrary: { 104 | mixin: true, 105 | name: '~theme', 106 | path: '[module]/[module].css', 107 | }, 108 | style: true, 109 | }]; 110 | } 111 | 112 | if (caseName === 'custom-css-filename') { 113 | cssPlugin = [plugin, { style: 'style.css' }]; 114 | } 115 | 116 | if (caseName === 'multiple-module') { 117 | cssPlugin = [ 118 | [plugin, { 119 | libraryName: 'antd', 120 | style: true, 121 | }, 'antd'], 122 | [plugin, { 123 | libraryName: 'test-module', 124 | style: true, 125 | }, 'test-module'], 126 | ]; 127 | } 128 | 129 | if (caseName === 'camel-to-dash-option') { 130 | cssPlugin = [plugin, { 131 | libraryName: 'antd', 132 | camel2Dash: false, 133 | }]; 134 | } 135 | 136 | const actual = transformFileSync(actualFile, { 137 | presets: ['@babel/react'], 138 | plugins: cssPlugin && Array.isArray(cssPlugin[1]) ? cssPlugin : [cssPlugin || plugin], 139 | }).code; 140 | 141 | 142 | if (onlyFixtures.length) { 143 | console.warn(); 144 | console.warn(actual); 145 | } 146 | 147 | expect(actual.trim()).toEqual(expected.trim()); 148 | }); 149 | }); 150 | }); 151 | -------------------------------------------------------------------------------- /src/core.js: -------------------------------------------------------------------------------- 1 | const { addSideEffect, addDefault } = require('@babel/helper-module-imports'); 2 | const resolve = require('path').resolve; 3 | const isExist = require('fs').existsSync; 4 | const cache = {}; 5 | const cachePath = {}; 6 | const importAll = {}; 7 | 8 | module.exports = function core(defaultLibraryName) { 9 | return ({ types }) => { 10 | let specified; 11 | let libraryObjs; 12 | let selectedMethods; 13 | let moduleArr; 14 | 15 | function parseName(_str, camel2Dash) { 16 | if (!camel2Dash) { 17 | return _str; 18 | } 19 | const str = _str[0].toLowerCase() + _str.substr(1); 20 | return str.replace(/([A-Z])/g, ($1) => `-${$1.toLowerCase()}`); 21 | } 22 | 23 | function importMethod(methodName, file, opts) { 24 | if (!selectedMethods[methodName]) { 25 | let options; 26 | let path; 27 | 28 | if (Array.isArray(opts)) { 29 | options = opts.find(option => 30 | moduleArr[methodName] === option.libraryName || 31 | libraryObjs[methodName] === option.libraryName 32 | ); // eslint-disable-line 33 | } 34 | options = options || opts; 35 | 36 | const { 37 | libDir = 'lib', 38 | libraryName = defaultLibraryName, 39 | style = true, 40 | styleLibrary, 41 | root = '', 42 | camel2Dash = true, 43 | } = options; 44 | let styleLibraryPath = options.styleLibraryPath; 45 | let _root = root; 46 | let isBaseStyle = true; 47 | let modulePathTpl; 48 | let styleRoot; 49 | let mixin = false; 50 | const ext = options.ext || '.css'; 51 | 52 | if (root) { 53 | _root = `/${root}`; 54 | } 55 | 56 | if (libraryObjs[methodName]) { 57 | path = `${libraryName}/${libDir}${_root}`; 58 | if (!_root) { 59 | importAll[path] = true; 60 | } 61 | } else { 62 | path = `${libraryName}/${libDir}/${parseName(methodName, camel2Dash)}`; 63 | } 64 | const _path = path; 65 | 66 | selectedMethods[methodName] = addDefault(file.path, path, { nameHint: methodName }); 67 | if (styleLibrary && typeof styleLibrary === 'object') { 68 | styleLibraryPath = styleLibrary.name; 69 | isBaseStyle = styleLibrary.base; 70 | modulePathTpl = styleLibrary.path; 71 | mixin = styleLibrary.mixin; 72 | styleRoot = styleLibrary.root; 73 | } 74 | if (styleLibraryPath) { 75 | if (!cachePath[libraryName]) { 76 | const themeName = styleLibraryPath.replace(/^~/, ''); 77 | cachePath[libraryName] = styleLibraryPath.indexOf('~') === 0 78 | ? resolve(process.cwd(), themeName) 79 | : styleLibraryPath; 80 | } 81 | 82 | if (libraryObjs[methodName]) { 83 | /* istanbul ingore next */ 84 | if (cache[libraryName] === 2) { 85 | throw Error('[babel-plugin-component] If you are using both' + 86 | 'on-demand and importing all, make sure to invoke the' + 87 | ' importing all first.'); 88 | } 89 | if (styleRoot) { 90 | path = `${cachePath[libraryName]}${styleRoot}${ext}`; 91 | } else { 92 | path = `${cachePath[libraryName]}${_root || '/index'}${ext}`; 93 | } 94 | cache[libraryName] = 1; 95 | } else { 96 | if (cache[libraryName] !== 1) { 97 | /* if set styleLibrary.path(format: [module]/module.css) */ 98 | const parsedMethodName = parseName(methodName, camel2Dash); 99 | if (modulePathTpl) { 100 | const modulePath = modulePathTpl.replace(/\[module]/ig, parsedMethodName); 101 | path = `${cachePath[libraryName]}/${modulePath}`; 102 | } else { 103 | path = `${cachePath[libraryName]}/${parsedMethodName}${ext}`; 104 | } 105 | if (mixin && !isExist(path)) { 106 | path = style === true ? `${_path}/style${ext}` : `${_path}/${style}`; 107 | } 108 | if (isBaseStyle) { 109 | addSideEffect(file.path, `${cachePath[libraryName]}/base${ext}`); 110 | } 111 | cache[libraryName] = 2; 112 | } 113 | } 114 | 115 | addDefault(file.path, path, { nameHint: methodName }); 116 | } else { 117 | if (style === true) { 118 | addSideEffect(file.path, `${path}/style${ext}`); 119 | } else if (style) { 120 | addSideEffect(file.path, `${path}/${style}`); 121 | } 122 | } 123 | } 124 | return selectedMethods[methodName]; 125 | } 126 | 127 | function buildExpressionHandler(node, props, path, state) { 128 | const file = (path && path.hub && path.hub.file) || (state && state.file); 129 | props.forEach(prop => { 130 | if (!types.isIdentifier(node[prop])) return; 131 | if (specified[node[prop].name]) { 132 | node[prop] = importMethod(node[prop].name, file, state.opts); // eslint-disable-line 133 | } 134 | }); 135 | } 136 | 137 | function buildDeclaratorHandler(node, prop, path, state) { 138 | const file = (path && path.hub && path.hub.file) || (state && state.file); 139 | if (!types.isIdentifier(node[prop])) return; 140 | if (specified[node[prop].name]) { 141 | node[prop] = importMethod(node[prop].name, file, state.opts); // eslint-disable-line 142 | } 143 | } 144 | 145 | return { 146 | visitor: { 147 | Program() { 148 | specified = Object.create(null); 149 | libraryObjs = Object.create(null); 150 | selectedMethods = Object.create(null); 151 | moduleArr = Object.create(null); 152 | }, 153 | 154 | ImportDeclaration(path, { opts }) { 155 | const { node } = path; 156 | const { value } = node.source; 157 | let result = {}; 158 | 159 | if (Array.isArray(opts)) { 160 | result = opts.find(option => option.libraryName === value) || {}; 161 | } 162 | const libraryName = result.libraryName || opts.libraryName || defaultLibraryName; 163 | 164 | if (value === libraryName) { 165 | node.specifiers.forEach(spec => { 166 | if (types.isImportSpecifier(spec)) { 167 | specified[spec.local.name] = spec.imported.name; 168 | moduleArr[spec.imported.name] = value; 169 | } else { 170 | libraryObjs[spec.local.name] = value; 171 | } 172 | }); 173 | 174 | if (!importAll[value]) { 175 | path.remove(); 176 | } 177 | } 178 | }, 179 | 180 | CallExpression(path, state) { 181 | const { node } = path; 182 | const file = (path && path.hub && path.hub.file) || (state && state.file); 183 | const { name } = node.callee; 184 | 185 | if (types.isIdentifier(node.callee)) { 186 | if (specified[name]) { 187 | node.callee = importMethod(specified[name], file, state.opts); 188 | } 189 | } else { 190 | node.arguments = node.arguments.map(arg => { 191 | const { name: argName } = arg; 192 | if (specified[argName]) { 193 | return importMethod(specified[argName], file, state.opts); 194 | } else if (libraryObjs[argName]) { 195 | return importMethod(argName, file, state.opts); 196 | } 197 | return arg; 198 | }); 199 | } 200 | }, 201 | 202 | MemberExpression(path, state) { 203 | const { node } = path; 204 | const file = (path && path.hub && path.hub.file) || (state && state.file); 205 | 206 | if (libraryObjs[node.object.name] || specified[node.object.name]) { 207 | node.object = importMethod(node.object.name, file, state.opts); 208 | } 209 | }, 210 | 211 | AssignmentExpression(path, { opts }) { 212 | if (!path.hub) { 213 | return; 214 | } 215 | const { node } = path; 216 | const { file } = path.hub; 217 | 218 | if (node.operator !== '=') return; 219 | if (libraryObjs[node.right.name] || specified[node.right.name]) { 220 | node.right = importMethod(node.right.name, file, opts); 221 | } 222 | }, 223 | 224 | ArrayExpression(path, { opts }) { 225 | if (!path.hub) { 226 | return; 227 | } 228 | const { elements } = path.node; 229 | const { file } = path.hub; 230 | 231 | elements.forEach((item, key) => { 232 | if (item && (libraryObjs[item.name] || specified[item.name])) { 233 | elements[key] = importMethod(item.name, file, opts); 234 | } 235 | }); 236 | }, 237 | 238 | Property(path, state) { 239 | const { node } = path; 240 | buildDeclaratorHandler(node, 'value', path, state); 241 | }, 242 | 243 | VariableDeclarator(path, state) { 244 | const { node } = path; 245 | buildDeclaratorHandler(node, 'init', path, state); 246 | }, 247 | 248 | LogicalExpression(path, state) { 249 | const { node } = path; 250 | buildExpressionHandler(node, ['left', 'right'], path, state); 251 | }, 252 | 253 | ConditionalExpression(path, state) { 254 | const { node } = path; 255 | buildExpressionHandler(node, ['test', 'consequent', 'alternate'], path, state); 256 | }, 257 | 258 | IfStatement(path, state) { 259 | const { node } = path; 260 | buildExpressionHandler(node, ['test'], path, state); 261 | buildExpressionHandler(node.test, ['left', 'right'], path, state); 262 | }, 263 | }, 264 | }; 265 | }; 266 | }; 267 | --------------------------------------------------------------------------------