diff --git a/packages/material-parser/CHANGELOG.md b/packages/material-parser/CHANGELOG.md
new file mode 100644
index 000000000..4bd5740bc
--- /dev/null
+++ b/packages/material-parser/CHANGELOG.md
@@ -0,0 +1,370 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+
+## [1.0.22](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.21...@ali/lowcode-material-parser@1.0.22) (2020-11-16)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.21](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.20...@ali/lowcode-material-parser@1.0.21) (2020-11-10)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.20](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.19...@ali/lowcode-material-parser@1.0.20) (2020-11-10)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.19](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.18...@ali/lowcode-material-parser@1.0.19) (2020-11-05)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.18](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.17...@ali/lowcode-material-parser@1.0.18) (2020-11-05)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.17](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.16...@ali/lowcode-material-parser@1.0.17) (2020-11-05)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.16](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.15...@ali/lowcode-material-parser@1.0.16) (2020-11-04)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.15](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.13...@ali/lowcode-material-parser@1.0.15) (2020-11-04)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.14](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.13...@ali/lowcode-material-parser@1.0.14) (2020-11-04)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.13](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.12...@ali/lowcode-material-parser@1.0.13) (2020-11-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.12](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.11...@ali/lowcode-material-parser@1.0.12) (2020-10-20)
+
+
+### Features
+
+* support params & returns of func propType ([0e46e49](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/0e46e49))
+* use parseJsDoc to parse propType docblock ([0b80be6](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/0b80be6))
+
+
+
+
+
+## [1.0.11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.10...@ali/lowcode-material-parser@1.0.11) (2020-10-19)
+
+
+### Bug Fixes
+
+* fix typescript related bugs, including the following: ([d4c45d2](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/d4c45d2))
+
+
+
+
+
+## [1.0.10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.9...@ali/lowcode-material-parser@1.0.10) (2020-09-29)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.9](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.8...@ali/lowcode-material-parser@1.0.9) (2020-09-28)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.8](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.8-0...@ali/lowcode-material-parser@1.0.8) (2020-09-28)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.8-0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.7-0...@ali/lowcode-material-parser@1.0.8-0) (2020-09-09)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.7-0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.6-0...@ali/lowcode-material-parser@1.0.7-0) (2020-09-02)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.6-0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.5-0...@ali/lowcode-material-parser@1.0.6-0) (2020-09-02)
+
+
+### Features
+
+* add root field to material parser options ([c6724e9](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/c6724e9))
+
+
+
+
+
+## [1.0.5-0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.4-0...@ali/lowcode-material-parser@1.0.5-0) (2020-08-20)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.4-0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.3-0...@ali/lowcode-material-parser@1.0.4-0) (2020-08-20)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.3-0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.2-0...@ali/lowcode-material-parser@1.0.3-0) (2020-08-20)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.2-0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.1-0...@ali/lowcode-material-parser@1.0.2-0) (2020-08-20)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [1.0.1-0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@1.0.0...@ali/lowcode-material-parser@1.0.1-0) (2020-08-20)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+# [1.0.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.15.0...@ali/lowcode-material-parser@1.0.0) (2020-08-17)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+# [0.15.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.14.0...@ali/lowcode-material-parser@0.15.0) (2020-08-17)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+# [0.14.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.12.0...@ali/lowcode-material-parser@0.14.0) (2020-08-17)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+# [0.13.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.12.0...@ali/lowcode-material-parser@0.13.0) (2020-08-17)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+# [0.12.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.11.0...@ali/lowcode-material-parser@0.12.0) (2020-08-16)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+# [0.11.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.10.0...@ali/lowcode-material-parser@0.11.0) (2020-08-14)
+
+
+### Features
+
+* support typescript & dynamic parsing in material parser ([6168ef5](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6168ef5))
+
+
+
+
+
+# [0.10.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.9.3...@ali/lowcode-material-parser@0.10.0) (2020-08-14)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [0.9.2](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.9.1...@ali/lowcode-material-parser@0.9.2) (2020-05-07)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+# [0.9.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.8.4...@ali/lowcode-material-parser@0.9.0) (2020-03-31)
+
+
+### Bug Fixes
+
+* [material-parser]fix bug of main field & remove useless debugger ([8fde0ec](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/8fde0ec))
+* fix bug of build errors ([770a1b6](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/770a1b6))
+* fix bug of missing types in material-parser ([9ce0a73](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/9ce0a73))
+
+
+### Features
+
+* 🎸 support parsing fusion source code ([5895cf1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/5895cf1))
+* support localizing ([e1faa84](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/e1faa84))
+
+
+
+
+
+## [0.8.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.8.3...@ali/lowcode-material-parser@0.8.4) (2020-03-30)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## [0.8.3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.8.2...@ali/lowcode-material-parser@0.8.3) (2020-03-30)
+
+
+
+
+**Note:** Version bump only for package @ali/lowcode-material-parser
+
+
+## 0.8.2 (2020-03-30)
+
+
+### Bug Fixes
+
+* 🐛 fix bug of transforming type ([ebbe58d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/ebbe58d))
+* 🐛 fix bug of validate schema ([3f97523](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3f97523))
+
+
+### Code Refactoring
+
+* 💡 refactor with react-docgen ([64c9daa](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/64c9daa))
+
+
+### Features
+
+* complete component protocol json schema & validate method ([3df360d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3df360d))
+* immigrate aimake materialin ([44ac85f](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/44ac85f))
+* import react-docgen to parse propTypes ([6e66168](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6e66168))
+* remove -p tslint.json for test ([6d013e1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6d013e1))
+* remove useless codes & modify generator ([dcd1b33](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/dcd1b33))
+* support multiple exported components ([db1b6de](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/db1b6de))
+
+
+### BREAKING CHANGES
+
+* 🧨 use react-docgen to replace parser
+
+
+
+
+
+## 0.8.1 (2020-03-30)
+
+
+### Bug Fixes
+
+* 🐛 fix bug of transforming type ([ebbe58d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/ebbe58d))
+* 🐛 fix bug of validate schema ([3f97523](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3f97523))
+* 🐛 fix bug of transforming type ([ebbe58d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/ebbe58df70f047f4b5fe367ac4b4a08de8a65e5d))
+* 🐛 fix bug of validate schema ([3f97523](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3f975232c7cd551bc9c74962095dcc9b127af489))
+
+
+### Code Refactoring
+
+* 💡 refactor with react-docgen ([64c9daa](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/64c9daa))
+* 💡 refactor with react-docgen ([64c9daa](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/64c9daa1f451fdfeab2777e4beefc5d5e1890ba1))
+
+
+### Features
+
+* complete component protocol json schema & validate method ([3df360d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3df360d))
+* immigrate aimake materialin ([44ac85f](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/44ac85f))
+* import react-docgen to parse propTypes ([6e66168](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6e66168))
+* remove -p tslint.json for test ([6d013e1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6d013e1))
+* remove useless codes & modify generator ([dcd1b33](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/dcd1b33))
+* support multiple exported components ([db1b6de](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/db1b6de))
+* complete component protocol json schema & validate method ([3df360d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3df360de85d425b2926ea50ff26a8df27ec36a78))
+* immigrate aimake materialin ([44ac85f](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/44ac85f8a6a35bcd50f2e2b74a022e3cebe3cdef))
+* import react-docgen to parse propTypes ([6e66168](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6e661686e4693e69279c496f3be1dd173703c55e))
+* remove -p tslint.json for test ([6d013e1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6d013e18f93bad5647cb9ea0a497336f64e1459a))
+* remove useless codes & modify generator ([dcd1b33](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/dcd1b33d3bf8bdf5577dcc980608d9eac8d99372))
+* support multiple exported components ([db1b6de](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/db1b6deaca256b0d107fe607de6cd0fc90517a9c))
+
+
+### BREAKING CHANGES
+
+* 🧨 use react-docgen to replace parser
diff --git a/packages/material-parser/README.md b/packages/material-parser/README.md
new file mode 100644
index 000000000..99786b2e4
--- /dev/null
+++ b/packages/material-parser/README.md
@@ -0,0 +1,16 @@
+# @ali/lowcode-material-parser
+
+> 入料模块
+
+本模块负责物料接入,能自动扫描、解析源码组件,并最终产出一份符合 **[《中后台搭建组件描述协议》](https://yuque.antfin-inc.com/rt656r/spec/pbeaqx)** 的 **JSON Schema**。
+
+详见[文档](https://yuque.antfin-inc.com/ali-lowcode/docs/tyktrt)。
+
+## demo
+
+```shell
+cd demo
+node index.js
+```
+
+## API
diff --git a/packages/material-parser/build.test.json b/packages/material-parser/build.test.json
new file mode 100644
index 000000000..2381f7d06
--- /dev/null
+++ b/packages/material-parser/build.test.json
@@ -0,0 +1,5 @@
+{
+ "plugins": [
+ "@ali/lowcode-test-mate/plugin/index.ts"
+ ]
+}
\ No newline at end of file
diff --git a/packages/material-parser/demo/component.jsx b/packages/material-parser/demo/component.jsx
new file mode 100644
index 000000000..0a6e805fb
--- /dev/null
+++ b/packages/material-parser/demo/component.jsx
@@ -0,0 +1,81 @@
+/* eslint-disable react/forbid-prop-types,react/no-unused-prop-types */
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import './main.scss';
+
+class Demo extends React.Component {
+ render() {
+ return
Test
;
+ }
+}
+
+Demo.propTypes = {
+ optionalArray: PropTypes.array,
+ optionalBool: PropTypes.bool,
+ optionalFunc: PropTypes.func,
+ optionalNumber: PropTypes.number,
+ optionalObject: PropTypes.object,
+ optionalString: PropTypes.string,
+ optionalSymbol: PropTypes.symbol,
+
+ // Anything that can be rendered: numbers, strings, elements or an array
+ // (or fragment) containing these types.
+ optionalNode: PropTypes.node,
+
+ // A React element (ie. ).
+ optionalElement: PropTypes.element,
+
+ // A React element type (ie. MyComponent).
+ optionalElementType: PropTypes.elementType,
+
+ // You can also declare that a prop is an instance of a class. This uses
+ // JS's instanceof operator.
+ optionalMessage: PropTypes.instanceOf(Demo),
+
+ // You can ensure that your prop is limited to specific values by treating
+ // it as an enum.
+ optionalEnum: PropTypes.oneOf(['News', 'Photos']),
+
+ // An object that could be one of many types
+ optionalUnion: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.instanceOf(Demo),
+ ]),
+
+ // An array of a certain type
+ optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
+
+ // An object with property values of a certain type
+ optionalObjectOf: PropTypes.objectOf(PropTypes.number),
+
+ // You can chain any of the above with `isRequired` to make sure a warning
+ // is shown if the prop isn't provided.
+
+ // An object taking on a particular shape
+ optionalObjectWithShape: PropTypes.shape({
+ optionalProperty: PropTypes.string,
+ requiredProperty: PropTypes.number.isRequired,
+ }),
+
+ optionalObjectWithShape2: PropTypes.shape({
+ optionalProperty: PropTypes.string,
+ requiredProperty: PropTypes.number.isRequired,
+ }).isRequired,
+
+ // An object with warnings on extra properties
+ optionalObjectWithStrictShape: PropTypes.exact({
+ optionalProperty: PropTypes.string,
+ requiredProperty: PropTypes.number.isRequired,
+ }),
+
+ requiredFunc: PropTypes.func.isRequired,
+
+ // A value of any data type
+ requiredAny: PropTypes.any.isRequired,
+};
+
+Demo.defaultProps = {};
+
+export default Demo;
diff --git a/packages/material-parser/demo/index.js b/packages/material-parser/demo/index.js
new file mode 100644
index 000000000..5c079efe3
--- /dev/null
+++ b/packages/material-parser/demo/index.js
@@ -0,0 +1,11 @@
+const parse = require('../lib').default;
+
+(async () => {
+ const options = {
+ entry: './component.jsx',
+ accesser: 'local',
+ };
+
+ const actual = await parse(options);
+ console.log(JSON.stringify(actual, null, 2));
+})();
diff --git a/packages/material-parser/jest.config.js b/packages/material-parser/jest.config.js
new file mode 100644
index 000000000..5686a4647
--- /dev/null
+++ b/packages/material-parser/jest.config.js
@@ -0,0 +1,20 @@
+
+module.exports = {
+ transform: {
+ '^.+\\.(ts|tsx|js|jsx)$': 'ts-jest',
+ },
+ testEnvironment: 'node',
+ // testMatch: ['(/tests?/.*(test))\\.[jt]s$'],
+ testTimeout: 1000000,
+ testPathIgnorePatterns: [
+ '/node_modules/',
+ 'test/fixtures',
+ ],
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
+ collectCoverage: true,
+ collectCoverageFrom: [
+ 'src/**/*.{ts,tsx}',
+ '!**/node_modules/**',
+ '!**/vendor/**',
+ ],
+};
\ No newline at end of file
diff --git a/packages/material-parser/package.json b/packages/material-parser/package.json
new file mode 100644
index 000000000..b760bdd72
--- /dev/null
+++ b/packages/material-parser/package.json
@@ -0,0 +1,65 @@
+{
+ "name": "@ali/lowcode-material-parser",
+ "version": "1.0.45",
+ "description": "material parser for Ali lowCode engine",
+ "main": "lib/index.js",
+ "module": "es/index.js",
+ "files": [
+ "lib",
+ "schemas"
+ ],
+ "devDependencies": {
+ "@babel/runtime": "^7.11.2",
+ "@types/debug": "^4.1.5",
+ "@types/fs-extra": "^8.0.1",
+ "@types/jest": "^26.0.18",
+ "@types/js-yaml": "^3.12.2",
+ "@types/lodash": "^4.14.149",
+ "@types/node": "^14.6.0",
+ "@types/prop-types": "^15.7.3",
+ "copy-webpack-plugin": "^9.1.0",
+ "copyfiles": "^2.4.1",
+ "jest": "^26.6.3",
+ "js-yaml": "^3.13.1",
+ "json-schema-to-typescript": "^8.2.0",
+ "ts-jest": "^26.0.0",
+ "ts-loader": "^9.2.6",
+ "ts-node": "^8.10.2",
+ "tslib": "^1.11.1",
+ "webpack": "^5.64.1",
+ "webpack-cli": "^4.9.1",
+ "webpack-node-externals": "^3.0.0"
+ },
+ "scripts": {
+ "build": "tsc",
+ "prebuild": "npm run schema && npm run bundle",
+ "postbuild": "copyfiles -u 1 \"src/**/*.json\" lib/",
+ "prepublishOnly": "npm run build",
+ "test": "jest --verbose",
+ "test:snapshot": "jest --updateSnapshot --verbose",
+ "schema": "node ./scripts/transform.js",
+ "bundle": "webpack"
+ },
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.0",
+ "ast-types": "^0.13.3",
+ "cross-spawn-promise": "^0.10.2",
+ "debug": "^4.1.1",
+ "find-config": "^1.0.0",
+ "fs-extra": "^8.1.0",
+ "lodash": "^4.17.15",
+ "parse-prop-types": "^0.3.0",
+ "prop-types": "^15.7.2",
+ "react-docgen": "5.3.0",
+ "react-docgen-typescript": "^1.16.5",
+ "safe-eval": "^0.4.1",
+ "short-uuid": "^3.1.1",
+ "ts-polyfill": "^3.8.1-rc",
+ "typescript": "3.9.4",
+ "vm2": "^3.9.2"
+ },
+ "publishConfig": {
+ "registry": "https://registry.npm.alibaba-inc.com"
+ }
+}
diff --git a/packages/material-parser/schemas/schema.json b/packages/material-parser/schemas/schema.json
new file mode 100644
index 000000000..7a5469a10
--- /dev/null
+++ b/packages/material-parser/schemas/schema.json
@@ -0,0 +1,537 @@
+{
+ "$id": "@ali/low-code-component-protocol-schema",
+ "description": "json schema for low code component protocol",
+ "allOf": [
+ {
+ "$ref": "#/definitions/BasicSection"
+ },
+ {
+ "$ref": "#/definitions/PropsSection"
+ },
+ {
+ "$ref": "#/definitions/ConfigureSection"
+ }
+ ],
+ "definitions": {
+ "BasicSection": {
+ "type": "object",
+ "properties": {
+ "componentName": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "docUrl": {
+ "type": "string"
+ },
+ "screenshot": {
+ "type": "string"
+ },
+ "icon": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "devMode": {
+ "enum": [
+ "proCode",
+ "lowCode"
+ ]
+ },
+ "npm": {
+ "$ref": "#/definitions/Npm"
+ }
+ },
+ "required": [
+ "componentName",
+ "title",
+ "npm",
+ "docUrl",
+ "screenshot"
+ ]
+ },
+ "PropsSection": {
+ "type": "object",
+ "properties": {
+ "props": {
+ "type": "array",
+ "items": {
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "propType": {
+ "$ref": "#/definitions/PropType"
+ },
+ "description": {
+ "type": "string"
+ },
+ "defaultValue": {}
+ },
+ "required": [
+ "name",
+ "propType"
+ ]
+ }
+ }
+ }
+ },
+ "ConfigureSection": {
+ "type": "object",
+ "properties": {
+ "configure": {
+ "type": "object",
+ "properties": {
+ "props": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/ConfigureProp"
+ }
+ },
+ "styles": {
+ "type": "object",
+ "properties": {}
+ },
+ "events": {
+ "type": "object",
+ "properties": {}
+ },
+ "component": {
+ "$ref": "#/definitions/ConfigureComponent"
+ }
+ }
+ }
+ }
+ },
+ "Npm": {
+ "type": "object",
+ "properties": {
+ "package": {
+ "type": "string"
+ },
+ "exportName": {
+ "type": "string"
+ },
+ "subName": {
+ "type": "string"
+ },
+ "main": {
+ "type": "string"
+ },
+ "destructuring": {
+ "type": "boolean"
+ },
+ "version": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "package",
+ "exportName",
+ "subName",
+ "main",
+ "destructuring",
+ "version"
+ ]
+ },
+ "PropType": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/BasicType"
+ },
+ {
+ "$ref": "#/definitions/RequiredType"
+ },
+ {
+ "$ref": "#/definitions/ComplexType"
+ }
+ ]
+ },
+ "BasicType": {
+ "type": "string",
+ "enum": [
+ "array",
+ "bool",
+ "func",
+ "number",
+ "object",
+ "string",
+ "node",
+ "element",
+ "any"
+ ]
+ },
+ "RequiredType": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/BasicType"
+ },
+ "isRequired": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "type"
+ ]
+ },
+ "ComplexType": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/OneOf"
+ },
+ {
+ "$ref": "#/definitions/OneOfType"
+ },
+ {
+ "$ref": "#/definitions/ArrayOf"
+ },
+ {
+ "$ref": "#/definitions/ObjectOf"
+ },
+ {
+ "$ref": "#/definitions/Shape"
+ },
+ {
+ "$ref": "#/definitions/Exact"
+ }
+ ]
+ },
+ "OneOf": {
+ "type": "object",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "oneOf"
+ ]
+ },
+ "value": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "isRequired": {
+ "type": "boolean"
+ }
+ }
+ },
+ "OneOfType": {
+ "type": "object",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "oneOfType"
+ ]
+ },
+ "value": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/PropType"
+ }
+ },
+ "isRequired": {
+ "type": "boolean"
+ }
+ }
+ },
+ "ArrayOf": {
+ "type": "object",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "arrayOf"
+ ]
+ },
+ "value": {
+ "$ref": "#/definitions/PropType"
+ },
+ "isRequired": {
+ "type": "boolean"
+ }
+ }
+ },
+ "ObjectOf": {
+ "type": "object",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "objectOf"
+ ]
+ },
+ "value": {
+ "$ref": "#/definitions/PropType"
+ },
+ "isRequired": {
+ "type": "boolean"
+ }
+ }
+ },
+ "Shape": {
+ "type": "object",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "shape"
+ ]
+ },
+ "value": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "propType": {
+ "$ref": "#/definitions/PropType"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "isRequired": {
+ "type": "boolean"
+ }
+ }
+ },
+ "ShapeItem": {
+ "type": "object",
+ "required": [
+ "name",
+ "propType"
+ ],
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "propType": {
+ "$ref": "#/definitions/PropType"
+ },
+ "isRequired": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ },
+ "Exact": {
+ "type": "object",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "exact"
+ ]
+ },
+ "value": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "propType": {
+ "$ref": "#/definitions/PropType"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "isRequired": {
+ "type": "boolean"
+ }
+ }
+ },
+ "ConfigureProp": {
+ "type": "object",
+ "allOf": [
+ {
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string"
+ },
+ "extraProps": {
+ "type": "object",
+ "properties": {}
+ }
+ }
+ },
+ {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/ConfigureFieldProp"
+ },
+ {
+ "$ref": "#/definitions/ConfigureGroupProp"
+ }
+ ]
+ }
+ ]
+ },
+ "ConfigureFieldProp": {
+ "type": "object",
+ "required": [
+ "type"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "field"
+ ]
+ },
+ "name": {
+ "type": "string"
+ },
+ "setter": {
+ "$ref": "#/definitions/ConfigureFieldSetter"
+ }
+ }
+ },
+ "ConfigureFieldSetter": {
+ "type": "object",
+ "required": [
+ "componentName"
+ ],
+ "properties": {
+ "componentName": {
+ "type": "string",
+ "enum": [
+ "List",
+ "Object",
+ "Function",
+ "Node",
+ "Mixin",
+ "Expression",
+ "Switch",
+ "Number",
+ "Input",
+ "TextArea",
+ "Date",
+ "DateYear",
+ "DateMonth",
+ "DateRange",
+ "ColorPicker",
+ "CodeEditor",
+ "Select",
+ "RadioGroup"
+ ]
+ },
+ "props": {
+ "type": "object",
+ "properties": {}
+ }
+ }
+ },
+ "ConfigureGroupProp": {
+ "type": "object",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "group"
+ ]
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/ConfigureProp"
+ }
+ }
+ }
+ },
+ "ConfigureComponent": {
+ "type": "object",
+ "properties": {
+ "isContainer": {
+ "type": "boolean"
+ },
+ "isModal": {
+ "type": "boolean"
+ },
+ "descriptor": {
+ "type": "string"
+ },
+ "nestingRule": {
+ "type": "object",
+ "properties": {
+ "childWhitelist": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "parentWhitelist": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "descendantBlacklist": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ancestorWhitelist": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "isNullNode": {
+ "type": "boolean"
+ },
+ "isLayout": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/material-parser/schemas/schema.yml b/packages/material-parser/schemas/schema.yml
new file mode 100644
index 000000000..71d2f8ec0
--- /dev/null
+++ b/packages/material-parser/schemas/schema.yml
@@ -0,0 +1,351 @@
+$id: "@ali/low-code-component-protocol-schema"
+description: json schema for low code component protocol
+allOf:
+ - $ref: "#/definitions/BasicSection"
+ - $ref: "#/definitions/PropsSection"
+ - $ref: "#/definitions/ConfigureSection"
+definitions:
+ BasicSection:
+ type: object
+ properties:
+ componentName:
+ type: string
+ title:
+ type: string
+ description:
+ type: string
+ docUrl:
+ type: string
+ screenshot:
+ type: string
+ icon:
+ type: string
+ tags:
+ type: array
+ items:
+ type: string
+ devMode:
+ enum:
+ - proCode
+ - lowCode
+ npm:
+ $ref: "#/definitions/Npm"
+ required:
+ - componentName
+ - title
+ - npm
+ PropsSection:
+ type: object
+ required:
+ - props
+ properties:
+ props:
+ type: array
+ items:
+ properties:
+ name:
+ type: string
+ propType:
+ $ref: "#/definitions/PropType"
+ description:
+ type: string
+ defaultValue: {}
+ required:
+ - name
+ - propType
+ ConfigureSection:
+ type: object
+ properties:
+ configure:
+ type: object
+ properties:
+ props:
+ type: array
+ items:
+ $ref: "#/definitions/ConfigureProp"
+ styles:
+ type: object
+ properties: {}
+ events:
+ type: object
+ properties: {}
+ component:
+ $ref: "#/definitions/ConfigureComponent"
+ Npm:
+ type: object
+ properties:
+ package:
+ type: string
+ exportName:
+ type: string
+ subName:
+ type: string
+ main:
+ type: string
+ destructuring:
+ type: boolean
+ version:
+ type: string
+ required:
+ - package
+ - exportName
+ - subName
+ - main
+ - destructuring
+ - version
+ PropType:
+ oneOf:
+ - $ref: "#/definitions/BasicType"
+ - $ref: "#/definitions/RequiredType"
+ - $ref: "#/definitions/ComplexType"
+ BasicType:
+ type: string
+ enum:
+ - array
+ - bool
+ - func
+ - number
+ - object
+ - string
+ - node
+ - element
+ - any
+ RequiredType:
+ type: object
+ properties:
+ type:
+ $ref: "#/definitions/BasicType"
+ isRequired:
+ type: boolean
+ additionalProperties: false
+ required:
+ - type
+ ComplexType:
+ oneOf:
+ - $ref: "#/definitions/OneOf"
+ - $ref: "#/definitions/OneOfType"
+ - $ref: "#/definitions/ArrayOf"
+ - $ref: "#/definitions/ObjectOf"
+ - $ref: "#/definitions/Shape"
+ - $ref: "#/definitions/Exact"
+ OneOf:
+ type: object
+ required:
+ - type
+ - value
+ properties:
+ type:
+ type: string
+ enum:
+ - oneOf
+ value:
+ type: array
+ items:
+ oneOf:
+ - type: string
+ - type: number
+ - type: boolean
+ isRequired:
+ type: boolean
+ OneOfType:
+ type: object
+ required:
+ - type
+ - value
+ properties:
+ type:
+ type: string
+ enum:
+ - oneOfType
+ value:
+ type: array
+ items:
+ $ref: "#/definitions/PropType"
+ isRequired:
+ type: boolean
+ ArrayOf:
+ type: object
+ required:
+ - type
+ - value
+ properties:
+ type:
+ type: string
+ enum:
+ - arrayOf
+ value:
+ $ref: "#/definitions/PropType"
+ isRequired:
+ type: boolean
+ ObjectOf:
+ type: object
+ required:
+ - type
+ - value
+ properties:
+ type:
+ type: string
+ enum:
+ - objectOf
+ value:
+ $ref: "#/definitions/PropType"
+ isRequired:
+ type: boolean
+ Shape:
+ type: object
+ required:
+ - type
+ - value
+ properties:
+ type:
+ type: string
+ enum:
+ - shape
+ value:
+ type: array
+ items:
+ type: object
+ properties:
+ name:
+ type: string
+ propType:
+ $ref: "#/definitions/PropType"
+ additionalProperties: false
+ isRequired:
+ type: boolean
+ ShapeItem:
+ type: object
+ required:
+ - name
+ - propType
+ properties:
+ name:
+ type: string
+ propType:
+ $ref: "#/definitions/PropType"
+ isRequired:
+ type: boolean
+ additionalProperties: false
+ Exact:
+ type: object
+ required:
+ - type
+ - value
+ properties:
+ type:
+ type: string
+ enum:
+ - exact
+ value:
+ type: array
+ items:
+ type: object
+ properties:
+ name:
+ type: string
+ propType:
+ $ref: "#/definitions/PropType"
+ additionalProperties: false
+ isRequired:
+ type: boolean
+ ConfigureProp:
+ type: object
+ allOf:
+ - type: object
+ properties:
+ title:
+ type: string
+ extraProps:
+ type: object
+ properties: {}
+ - oneOf:
+ - $ref: "#/definitions/ConfigureFieldProp"
+ - $ref: "#/definitions/ConfigureGroupProp"
+ ConfigureFieldProp:
+ type: object
+ required:
+ - type
+ properties:
+ type:
+ type: string
+ enum:
+ - field
+ name:
+ type: string
+ setter:
+ $ref: "#/definitions/ConfigureFieldSetter"
+ ConfigureFieldSetter:
+ type: object
+ required:
+ - componentName
+ properties:
+ componentName:
+ type: string
+ enum:
+ - List
+ - Object
+ - Function
+ - Node
+ - Mixin
+ - Expression
+ - Switch
+ - Number
+ - Input
+ - TextArea
+ - Date
+ - DateYear
+ - DateMonth
+ - DateRange
+ - ColorPicker
+ - CodeEditor
+ - Select
+ - RadioGroup
+ props:
+ type: object
+ properties: {} # 暂未校验每个控件的props,待控件入料后获取真实属性
+ ConfigureGroupProp:
+ type: object
+ required:
+ - type
+ - items
+ properties:
+ type:
+ type: string
+ enum:
+ - group
+ items:
+ type: array
+ items:
+ $ref: "#/definitions/ConfigureProp"
+ ConfigureComponent:
+ type: object
+ properties:
+ isContainer:
+ type: boolean
+ isModal:
+ type: boolean
+ descriptor:
+ type: string
+ nestingRule:
+ type: object
+ properties:
+ childWhitelist:
+ type: array
+ items:
+ type: string
+ parentWhitelist:
+ type: array
+ items:
+ type: string
+ descendantBlacklist:
+ type: array
+ items:
+ type: string
+ ancestorWhitelist:
+ type: array
+ items:
+ type: string
+ isNullNode:
+ type: boolean
+ isLayout:
+ type: boolean
diff --git a/packages/material-parser/scripts/transform.js b/packages/material-parser/scripts/transform.js
new file mode 100644
index 000000000..4e9c127f1
--- /dev/null
+++ b/packages/material-parser/scripts/transform.js
@@ -0,0 +1,27 @@
+const yaml = require('js-yaml');
+const fs = require('fs');
+const path = require('path');
+const Ajv = require('ajv');
+const { compile } = require('json-schema-to-typescript');
+
+const ajv = new Ajv();
+
+const YamlPath = path.resolve(__dirname, '../schemas/schema.yml');
+const JsonPath = path.resolve(__dirname, '../src/validate/schema.json');
+const tsPath = path.resolve(__dirname, '../src/core/schema/types.ts');
+// Get document, or throw exception on error
+
+(async function () {
+ try {
+ const schema = yaml.load(fs.readFileSync(YamlPath, 'utf8'));
+ ajv.compile(schema);
+ fs.writeFileSync(JsonPath, JSON.stringify(schema, null, 2), 'utf-8');
+ console.log('yaml file is successfully transformed into json');
+ const ts = await compile(schema, 'ComponentMeta');
+ fs.writeFileSync(tsPath, ts);
+ console.log('schema.d.ts is successfully generated');
+ } catch (e) {
+ console.log(e);
+ process.exit(1);
+ }
+})();
diff --git a/packages/material-parser/src/core/index.ts b/packages/material-parser/src/core/index.ts
new file mode 100644
index 000000000..2b46db64b
--- /dev/null
+++ b/packages/material-parser/src/core/index.ts
@@ -0,0 +1,10 @@
+import _debug from 'debug';
+
+export * from './schema/types';
+
+/**
+ * Dev helper
+ */
+export const debug = _debug('lowcode:mat');
+export const enableDebug = () => _debug.enable('lowcode:*');
+export const disableDebug = () => _debug.disable();
diff --git a/packages/material-parser/src/core/schema/types.ts b/packages/material-parser/src/core/schema/types.ts
new file mode 100644
index 000000000..196032d2c
--- /dev/null
+++ b/packages/material-parser/src/core/schema/types.ts
@@ -0,0 +1,163 @@
+/**
+ * This file was automatically generated by json-schema-to-typescript.
+ * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
+ * and run json-schema-to-typescript to regenerate this file.
+ */
+
+/**
+ * json schema for low code component protocol
+ */
+export type ComponentMeta = BasicSection & PropsSection & ConfigureSection;
+export type PropType = BasicType | RequiredType | ComplexType;
+export type BasicType = 'array' | 'bool' | 'func' | 'number' | 'object' | 'string' | 'node' | 'element' | 'any';
+export type ComplexType = OneOf | OneOfType | ArrayOf | ObjectOf | Shape | Exact;
+export type ConfigureProp = {
+ title?: string;
+ extraProps?: {
+ [k: string]: any;
+ };
+ [k: string]: any;
+} & (ConfigureFieldProp | ConfigureGroupProp);
+
+export interface BasicSection {
+ componentName: string;
+ title: string;
+ description?: string;
+ docUrl?: string;
+ screenshot?: string;
+ icon?: string;
+ tags?: string[];
+ devMode?: 'proCode' | 'lowCode';
+ npm: Npm;
+ [k: string]: any;
+}
+export interface Npm {
+ package: string;
+ exportName: string;
+ subName: string;
+ main: string;
+ destructuring: boolean;
+ version: string;
+ [k: string]: any;
+}
+export interface PropsSection {
+ props: {
+ name: string;
+ propType: PropType;
+ description?: string;
+ defaultValue?: any;
+ [k: string]: any;
+ }[];
+ [k: string]: any;
+}
+export interface RequiredType {
+ type: BasicType;
+ isRequired?: boolean;
+}
+export interface OneOf {
+ type: 'oneOf';
+ value: (string | number | boolean)[];
+ isRequired?: boolean;
+ [k: string]: any;
+}
+export interface OneOfType {
+ type: 'oneOfType';
+ value: PropType[];
+ isRequired?: boolean;
+ [k: string]: any;
+}
+export interface ArrayOf {
+ type: 'arrayOf';
+ value: PropType;
+ isRequired?: boolean;
+ [k: string]: any;
+}
+export interface ObjectOf {
+ type: 'objectOf';
+ value: PropType;
+ isRequired?: boolean;
+ [k: string]: any;
+}
+export interface Shape {
+ type: 'shape';
+ value: {
+ name?: string;
+ propType?: PropType;
+ }[];
+ isRequired?: boolean;
+ [k: string]: any;
+}
+export interface Exact {
+ type: 'exact';
+ value: {
+ name?: string;
+ propType?: PropType;
+ }[];
+ isRequired?: boolean;
+ [k: string]: any;
+}
+export interface ConfigureSection {
+ configure?: {
+ props?: ConfigureProp[];
+ styles?: {
+ [k: string]: any;
+ };
+ events?: {
+ [k: string]: any;
+ };
+ component?: ConfigureComponent;
+ [k: string]: any;
+ };
+ [k: string]: any;
+}
+export interface ConfigureFieldProp {
+ type: 'field';
+ name?: string;
+ setter?: ConfigureFieldSetter;
+ [k: string]: any;
+}
+export interface ConfigureFieldSetter {
+ componentName:
+ | 'List'
+ | 'Object'
+ | 'Function'
+ | 'Node'
+ | 'Mixin'
+ | 'Expression'
+ | 'Switch'
+ | 'Number'
+ | 'Input'
+ | 'TextArea'
+ | 'Date'
+ | 'DateYear'
+ | 'DateMonth'
+ | 'DateRange'
+ | 'ColorPicker'
+ | 'CodeEditor'
+ | 'Select'
+ | 'RadioGroup';
+ props?: {
+ [k: string]: any;
+ };
+ [k: string]: any;
+}
+export interface ConfigureGroupProp {
+ type: 'group';
+ items: ConfigureProp[];
+ [k: string]: any;
+}
+export interface ConfigureComponent {
+ isContainer?: boolean;
+ isModal?: boolean;
+ descriptor?: string;
+ nestingRule?: {
+ childWhitelist?: string[];
+ parentWhitelist?: string[];
+ descendantBlacklist?: string[];
+ ancestorWhitelist?: string[];
+ [k: string]: any;
+ };
+ isNullNode?: boolean;
+ isLayout?: boolean;
+ [k: string]: any;
+}
diff --git a/packages/material-parser/src/generate.ts b/packages/material-parser/src/generate.ts
new file mode 100644
index 000000000..ec057a8c6
--- /dev/null
+++ b/packages/material-parser/src/generate.ts
@@ -0,0 +1,65 @@
+import * as path from 'path';
+import { debug, ComponentMeta } from './core';
+import { IMaterialParsedModel, IMaterialScanModel, IInternalMaterializeOptions } from './types';
+
+const log = debug.extend('gen');
+
+export default async function (
+ matScanModel: IMaterialScanModel,
+ matParsedModels: IMaterialParsedModel[],
+ options: IInternalMaterializeOptions,
+): Promise {
+ const containerList = [];
+ for (const matParsedModel of matParsedModels) {
+ // 默认排除掉 defaultExportName 为空的组件
+ if (!matParsedModel.componentName) {
+ log('skip');
+ continue;
+ }
+ // 组装 manifest
+ const manifest: any = await genManifest(matScanModel, matParsedModel, options);
+
+ containerList.push(manifest);
+ }
+
+ return containerList;
+}
+
+/**
+ * 生成 manifest
+ *
+ * @param {IMaterialParsedModel} matParsedModel
+ * @returns {Promise<
+ * manifestObj: ComponentMeta, // 组件描述
+ * >}
+ * @memberof LocalGenerator
+ */
+export async function genManifest(
+ matScanModel: IMaterialScanModel,
+ matParsedModel: IMaterialParsedModel,
+ options: IInternalMaterializeOptions,
+): Promise {
+ const manifestObj: Partial = {
+ componentName: matParsedModel.componentName,
+ title: matScanModel.pkgName,
+ docUrl: '',
+ screenshot: '',
+ devMode: 'proCode', // 需要入料的组件都是源码模式,低代码组件在平台上即可直接生成描述
+ npm: {
+ package: matScanModel.pkgName,
+ version: matScanModel.pkgVersion,
+ exportName: matParsedModel.meta?.exportName || matParsedModel.componentName,
+ main:
+ options.root && path.isAbsolute(matScanModel.mainFilePath)
+ ? path.relative(options.root, matScanModel.mainFilePath)
+ : matScanModel.mainFilePath,
+ destructuring: matParsedModel.meta?.exportName !== 'default',
+ subName: matParsedModel.meta?.subName || '',
+ },
+ };
+
+ // 填充 props
+ manifestObj.props = matParsedModel.props;
+ // 执行扩展点
+ return manifestObj as ComponentMeta;
+}
diff --git a/packages/material-parser/src/index.ts b/packages/material-parser/src/index.ts
new file mode 100644
index 000000000..f5df4e1d0
--- /dev/null
+++ b/packages/material-parser/src/index.ts
@@ -0,0 +1,70 @@
+import 'ts-polyfill';
+import { remove, lstatSync } from 'fs-extra';
+import { join, isAbsolute } from 'path';
+import {
+ IMaterializeOptions,
+ IMaterializeLocalOptions,
+ IMaterializeOnlineOptions,
+ IInternalMaterializeOptions,
+} from './types';
+import { ComponentMeta } from './core';
+import scan from './scan';
+import generate from './generate';
+import parse from './parse';
+import localize from './localize';
+
+export { default as validate } from './validate';
+export { default as schema } from './validate/schema.json';
+
+export * from './types';
+
+export default async function (options: IMaterializeOptions): Promise {
+ const { accesser = 'local', dslType } = options;
+
+ let { entry = '' } = options;
+ const internalOptions: IInternalMaterializeOptions = {
+ ...options,
+ accesser,
+ entry: options.entry || '',
+ root: (options as IMaterializeLocalOptions)?.root || '',
+ } as IInternalMaterializeOptions;
+
+ if (accesser === 'local') {
+ const { root } = options as IMaterializeLocalOptions;
+ internalOptions.root = root;
+ if (!root) {
+ const stats = lstatSync(entry);
+ if (stats.isDirectory()) {
+ internalOptions.root = entry;
+ } else {
+ internalOptions.root = process.cwd();
+ }
+ } else if (!isAbsolute(entry)) {
+ internalOptions.entry = join(root, entry);
+ }
+ }
+
+ let workDir = internalOptions.root || '';
+ let moduleDir = '';
+ if (accesser === 'online') {
+ const result = await localize(internalOptions as IMaterializeOnlineOptions);
+ workDir = result.workDir;
+ moduleDir = result.moduleDir;
+ internalOptions.entry = result.entry ? join(moduleDir, result.entry) : moduleDir;
+ internalOptions.root = moduleDir;
+ }
+ const scanedModel = await scan(internalOptions);
+ const parsedModel = await parse({
+ ...scanedModel,
+ dslType,
+ accesser,
+ npmClient: internalOptions.npmClient,
+ workDir,
+ moduleDir,
+ });
+ const result = await generate(scanedModel, parsedModel, internalOptions);
+ if (workDir && accesser === 'online') {
+ await remove(workDir);
+ }
+ return result;
+}
diff --git a/packages/material-parser/src/localize.ts b/packages/material-parser/src/localize.ts
new file mode 100644
index 000000000..a152fc0de
--- /dev/null
+++ b/packages/material-parser/src/localize.ts
@@ -0,0 +1,126 @@
+import spawn from 'cross-spawn-promise';
+import { ensureDir, ensureFile, writeFile } from 'fs-extra';
+import { join, resolve } from 'path';
+import uuid from 'short-uuid';
+import { debug } from './core';
+import { IMaterializeOnlineOptions, IMaterializeOnlinePackageAndVersionOptions } from './types';
+
+const log = debug.extend('localize');
+
+/**
+ * 创建组件包
+ *
+ * @private
+ * @param {{
+ * pkgName: string;
+ * pkgVersion: string;
+ * }} params
+ * @returns {Promise}
+ * @memberof OnlineAccesser
+ */
+export async function createFakePackage(params: {
+ workDir: string;
+ pkgName: string;
+ pkgVersion: string;
+ npmClient?: string;
+}): Promise {
+ // 创建临时组件包
+ const { workDir } = params;
+ const pkgJsonFilePath = join(workDir, 'package.json');
+ await ensureFile(pkgJsonFilePath);
+ await writeFile(
+ pkgJsonFilePath,
+ JSON.stringify(
+ {
+ name: params.pkgName,
+ version: params.pkgVersion || '0.0.0',
+ dependencies: {
+ [params.pkgName]: params.pkgVersion || 'latest',
+ react: 'latest',
+ 'react-dom': 'latest',
+ 'parse-prop-types': '^0.3.0',
+ typesync: 'latest',
+ },
+ },
+ null,
+ 2,
+ ),
+ );
+
+ // 安装依赖
+ const npmClient = params.npmClient || 'tnpm';
+ await spawn(npmClient, ['i'], { stdio: 'inherit', cwd: workDir } as any);
+}
+
+/**
+ * 创建临时目录
+ *
+ * @private
+ * @returns {Promise} 返回临时文件夹路径
+ * @memberof LocalGenerator
+ */
+export async function createworkDir(tempDir?: string): Promise {
+ const workDirName = uuid.generate();
+ const workDir = resolve(tempDir || '../../node_modules/.temp/', workDirName);
+ await ensureDir(workDir);
+ log('create temp dir successfully', workDir);
+ return workDir;
+}
+
+/**
+ * 分离物料组件名称和版本号
+ *
+ * @private
+ * @param {string} pkgNameWithVersion
+ * @returns {{ [key: string]: any }}
+ * @memberof OnlineAccesser
+ */
+export function getPkgNameAndVersion(pkgNameWithVersion: string): { [key: string]: any } {
+ const matches = pkgNameWithVersion.match(/(@[^/]+)$/);
+ if (!matches) {
+ return {
+ name: pkgNameWithVersion,
+ };
+ }
+ const name = pkgNameWithVersion.replace(matches[0], '');
+ return {
+ version: matches[0].slice(1),
+ name,
+ };
+}
+
+// 将问题转化为本地物料化场景
+export default async function localize(options: IMaterializeOnlineOptions): Promise<{
+ workDir: string;
+ moduleDir: string;
+ entry?: string;
+}> {
+ // 创建临时目录
+ const workDir = await createworkDir(options.tempDir);
+ await ensureDir(workDir);
+ let { name, version = 'latest' } = options as IMaterializeOnlinePackageAndVersionOptions;
+ if (!name) {
+ const pkgNameAndVersion = getPkgNameAndVersion(options.entry);
+ name = pkgNameAndVersion.name;
+ version = pkgNameAndVersion.version;
+ }
+ // 创建组件包
+ await createFakePackage({
+ pkgName: name,
+ pkgVersion: version,
+ workDir,
+ npmClient: options.npmClient,
+ });
+
+ const result = {
+ workDir,
+ moduleDir: join(workDir, 'node_modules', name),
+ entry: undefined,
+ };
+
+ if ((options as IMaterializeOnlinePackageAndVersionOptions)?.name) {
+ result.entry = options.entry;
+ }
+
+ return result;
+}
diff --git a/packages/material-parser/src/parse/dynamic/index.ts b/packages/material-parser/src/parse/dynamic/index.ts
new file mode 100644
index 000000000..0a7e968f9
--- /dev/null
+++ b/packages/material-parser/src/parse/dynamic/index.ts
@@ -0,0 +1,121 @@
+import { isEmpty } from 'lodash';
+// import * as path from 'path';
+// @ts-ignore
+import parsePropTypes from 'parse-prop-types';
+import PropTypes from 'prop-types';
+import { transformItem } from '../transform';
+import requireInSandbox from './requireInSandbox';
+
+export interface IComponentInfo {
+ component: any;
+ meta: {
+ exportName: string;
+ subName?: string;
+ };
+}
+
+const reservedKeys = [
+ 'propTypes',
+ 'defaultProps',
+ 'name',
+ 'arguments',
+ 'caller',
+ 'length',
+ 'contextTypes',
+ 'displayName',
+ '__esModule',
+ 'version',
+];
+
+function getKeys(com: any) {
+ const keys = Object.keys(com).filter(x => {
+ return !reservedKeys.includes(x) && !x.startsWith('_');
+ });
+
+ return keys;
+}
+
+function isComponent(obj: any) {
+ return (
+ typeof obj === 'function' &&
+ (Object.prototype.hasOwnProperty.call(obj, 'propTypes') ||
+ Object.prototype.hasOwnProperty.call(obj, 'defaultProps'))
+ );
+}
+
+export default function (filePath: string) {
+ // const { filePath } = arg;
+ // const modulePath = path.resolve(workDir, 'node_modules', 'parse-prop-types');
+ // const parsePropTypes = require(modulePath).default;
+ if (!filePath) return [];
+ const Com = requireInSandbox(filePath, PropTypes);
+ const components: IComponentInfo[] = [];
+ let index = 0;
+
+ if (Com.__esModule) {
+ const keys = getKeys(Com);
+ keys.forEach(k => {
+ if (isComponent(Com[k])) {
+ components.push({
+ component: Com[k],
+ meta: {
+ exportName: k,
+ },
+ });
+ }
+ });
+ } else if (isComponent(Com)) {
+ components.push({
+ component: Com,
+ meta: {
+ exportName: 'default',
+ },
+ });
+ }
+
+ // dps
+ while (index < components.length) {
+ const item = components[index++];
+
+ const keys = getKeys(item.component);
+ const subs = keys
+ .filter(k => isComponent(item.component[k]))
+ .map(k => ({
+ component: item.component[k],
+ meta: {
+ ...item.meta,
+ subName: k,
+ },
+ }));
+ if (subs.length) {
+ components.splice(index, 0, ...subs);
+ }
+ }
+
+ const result = components.reduce((acc: any, { meta, component }) => {
+ const componentInfo = parsePropTypes(component);
+ if (!isEmpty(componentInfo)) {
+ const props = Object.keys(componentInfo).reduce((acc2: any[], name) => {
+ try {
+ const item: any = transformItem(name, componentInfo[name]);
+ acc2.push(item);
+ } catch (e) {
+ // TODO
+ }
+ return acc2;
+ }, []);
+
+ return [
+ ...acc,
+ {
+ meta,
+ props,
+ componentName: meta.subName || meta.exportName || component.displayName,
+ },
+ ];
+ }
+ return acc;
+ }, []);
+
+ return result;
+}
diff --git a/packages/material-parser/src/parse/dynamic/requireInSandbox.ts b/packages/material-parser/src/parse/dynamic/requireInSandbox.ts
new file mode 100644
index 000000000..511b30038
--- /dev/null
+++ b/packages/material-parser/src/parse/dynamic/requireInSandbox.ts
@@ -0,0 +1,37 @@
+import { readFileSync } from 'fs-extra';
+import { NodeVM } from 'vm2';
+// import PropTypes from 'prop-types';
+
+const cssPattern = /\.(css|scss|sass|less)$/;
+function requireInSandbox(filePath: string, PropTypes: any) {
+ const vm = new NodeVM({
+ sandbox: {},
+ sourceExtensions: ['js', 'css', 'scss', 'sass', 'less'],
+ compiler: (code, filename) => {
+ if (filename.match(cssPattern)) {
+ return `
+ const handler = {
+ get() {
+ return new Proxy({}, handler);
+ },
+ };
+ const proxiedObject = new Proxy({}, handler);
+ module.exports = proxiedObject;
+ `;
+ } else {
+ return code;
+ }
+ },
+ require: {
+ external: true,
+ context: 'sandbox',
+ mock: {
+ 'prop-types': PropTypes,
+ },
+ },
+ });
+ const fileContent = readFileSync(filePath, { encoding: 'utf8' });
+ return vm.run(fileContent, filePath);
+}
+
+export default requireInSandbox;
diff --git a/packages/material-parser/src/parse/index.ts b/packages/material-parser/src/parse/index.ts
new file mode 100644
index 000000000..f38fab199
--- /dev/null
+++ b/packages/material-parser/src/parse/index.ts
@@ -0,0 +1,80 @@
+import parseDynamic from './dynamic';
+import parseJS from './js';
+import parseTS from './ts';
+import { install, installPeerAndDevDeps, syncTypeModules, installTypeDTS } from '../utils';
+import { IMaterialScanModel, DSLType } from '../types';
+import { debug } from '../core';
+
+const log = debug.extend('parse');
+
+export interface IParseArgs extends IMaterialScanModel {
+ accesser?: 'online' | 'local';
+ dslType?: DSLType;
+ npmClient?: string;
+ workDir: string;
+ moduleDir: string;
+ typingsFileAbsolutePath?: string;
+ mainFileAbsolutePath: string;
+ moduleFileAbsolutePath?: string;
+}
+
+export function isTSLike(str) {
+ return str.endsWith('ts') || str.endsWith('tsx');
+}
+
+export default async (args: IParseArgs) => {
+ const {
+ typingsFileAbsolutePath,
+ mainFileAbsolutePath,
+ moduleFileAbsolutePath = mainFileAbsolutePath,
+ useEntry = false,
+ } = args;
+ if (args.accesser === 'local') {
+ if (isTSLike(mainFileAbsolutePath)) {
+ await install(args);
+ // in case the developer forgets to install types
+ await installTypeDTS(args);
+ return parseTS(mainFileAbsolutePath, args);
+ } else if (typingsFileAbsolutePath) {
+ await installTypeDTS(args);
+ return parseTS(typingsFileAbsolutePath, args);
+ } else {
+ try {
+ return parseJS(moduleFileAbsolutePath || mainFileAbsolutePath);
+ } catch (e) {
+ log(e);
+ await install(args);
+ const info = parseDynamic(mainFileAbsolutePath);
+ if (!info || !info.length) {
+ throw Error();
+ }
+ return info;
+ }
+ }
+ } else if (args.accesser === 'online') {
+ // ts
+ const entryPath = useEntry ? mainFileAbsolutePath : typingsFileAbsolutePath;
+ if (entryPath && isTSLike(entryPath)) {
+ await syncTypeModules(args);
+ await install(args);
+ await installTypeDTS(args);
+ await installPeerAndDevDeps(args);
+ return parseTS(entryPath, args);
+ }
+ // js
+ try {
+ // try dynamic parsing first
+ await installPeerAndDevDeps(args);
+ const info = parseDynamic(mainFileAbsolutePath);
+ if (!info || !info.length) {
+ throw Error();
+ }
+ return info;
+ } catch (e) {
+ log(e);
+ // if error, use static js parsing instead
+ return parseJS(moduleFileAbsolutePath || mainFileAbsolutePath);
+ }
+ }
+ return parseJS(moduleFileAbsolutePath || mainFileAbsolutePath);
+};
diff --git a/packages/material-parser/src/parse/js/handlers/defaultPropsHandler.ts b/packages/material-parser/src/parse/js/handlers/defaultPropsHandler.ts
new file mode 100644
index 000000000..078db5f18
--- /dev/null
+++ b/packages/material-parser/src/parse/js/handlers/defaultPropsHandler.ts
@@ -0,0 +1,138 @@
+import getComposedPath from '../utils/getComposedPath';
+import evaluate from '../utils/evaluate';
+
+const { namedTypes: t, NodePath, visit } = require('ast-types');
+type NodePathType = typeof NodePath;
+const {
+ getPropertyName,
+ isReactComponentClass,
+ getMemberValuePath,
+ isReactForwardRefCall,
+ printValue,
+ resolveToValue,
+} = require('react-docgen').utils;
+const resolveFunctionDefinitionToReturnValue = require('react-docgen/dist/utils/resolveFunctionDefinitionToReturnValue');
+
+function getDefaultValue(path: NodePathType) {
+ let { node } = path;
+ let defaultValue;
+ if (t.Literal.check(node)) {
+ defaultValue = node.raw;
+ } else {
+ if (t.AssignmentPattern.check(path.node)) {
+ path = resolveToValue(path.get('right'));
+ } else {
+ path = resolveToValue(path);
+ }
+ if (t.ImportDeclaration.check(path.node)) {
+ defaultValue = node.name;
+ } else {
+ node = path.node;
+ try {
+ const result = evaluate(path);
+ if (result.confident) {
+ defaultValue = result.value;
+ }
+ } catch (e) {
+ // log(e);
+ // TODO
+ }
+ }
+ }
+ if (typeof defaultValue !== 'undefined') {
+ return {
+ value: defaultValue,
+ computed:
+ t.CallExpression.check(node) || t.MemberExpression.check(node) || t.Identifier.check(node),
+ };
+ }
+
+ return null;
+}
+
+function getStatelessPropsPath(componentDefinition: any) {
+ const value = resolveToValue(componentDefinition);
+ if (isReactForwardRefCall(value)) {
+ const inner = resolveToValue(value.get('arguments', 0));
+ return inner.get('params', 0);
+ }
+ return value.get('params', 0);
+}
+
+function getDefaultPropsPath(componentDefinition: any) {
+ let defaultPropsPath = getMemberValuePath(componentDefinition, 'defaultProps');
+ if (!defaultPropsPath) {
+ return null;
+ }
+
+ defaultPropsPath = resolveToValue(defaultPropsPath);
+ if (!defaultPropsPath) {
+ return null;
+ }
+
+ if (t.FunctionExpression.check(defaultPropsPath.node)) {
+ // Find the value that is returned from the function and process it if it is
+ // an object literal.
+ const returnValue = resolveFunctionDefinitionToReturnValue(defaultPropsPath);
+ if (returnValue && t.ObjectExpression.check(returnValue.node)) {
+ defaultPropsPath = returnValue;
+ }
+ }
+ return defaultPropsPath;
+}
+
+function getDefaultValuesFromProps(properties: any[], documentation: any, isStateless: boolean) {
+ properties
+ // Don't evaluate property if component is functional and the node is not an AssignmentPattern
+ .filter(
+ (propertyPath) => !isStateless || t.AssignmentPattern.check(propertyPath.get('value').node),
+ )
+ .forEach((propertyPath) => {
+ if (t.Property.check(propertyPath.node)) {
+ const propName = getPropertyName(propertyPath);
+ if (!propName) return;
+
+ const propDescriptor = documentation.getPropDescriptor(propName);
+ const defaultValue = getDefaultValue(
+ isStateless ? propertyPath.get('value', 'right') : propertyPath.get('value'),
+ );
+ if (defaultValue) {
+ propDescriptor.defaultValue = defaultValue;
+ }
+ } else if (t.SpreadElement.check(propertyPath.node)) {
+ const resolvedValuePath = resolveToValue(propertyPath.get('argument'));
+ if (t.ObjectExpression.check(resolvedValuePath.node)) {
+ getDefaultValuesFromProps(
+ resolvedValuePath.get('properties'),
+ documentation,
+ isStateless,
+ );
+ }
+ }
+ });
+}
+
+export default function defaultPropsHandler(documentation: any, componentDefinition: any) {
+ let statelessProps = null;
+ let defaultPropsPath = getDefaultPropsPath(componentDefinition);
+ /**
+ * function, lazy, memo, forwardRef etc components can resolve default props as well
+ */
+ if (!isReactComponentClass(componentDefinition)) {
+ statelessProps = getStatelessPropsPath(componentDefinition);
+ }
+
+ // Do both statelessProps and defaultProps if both are available so defaultProps can override
+ if (statelessProps && t.ObjectPattern.check(statelessProps.node)) {
+ getDefaultValuesFromProps(statelessProps.get('properties'), documentation, true);
+ }
+ if (defaultPropsPath && !t.ObjectExpression.check(defaultPropsPath.node)) {
+ const composedPath = getComposedPath(documentation, 'defaultProps', defaultPropsPath);
+ if (composedPath) {
+ defaultPropsPath = composedPath;
+ }
+ }
+ if (defaultPropsPath && t.ObjectExpression.check(defaultPropsPath.node)) {
+ getDefaultValuesFromProps(defaultPropsPath.get('properties'), documentation, false);
+ }
+}
diff --git a/packages/material-parser/src/parse/js/handlers/index.ts b/packages/material-parser/src/parse/js/handlers/index.ts
new file mode 100644
index 000000000..46f6abd4e
--- /dev/null
+++ b/packages/material-parser/src/parse/js/handlers/index.ts
@@ -0,0 +1,22 @@
+import { propTypeHandler, contextTypeHandler, childContextTypeHandler } from './propTypeHandler';
+import defaultPropsHandler from './defaultPropsHandler';
+import preProcessHandler from './preProcessHandler';
+import propTypeJsDocHandler from './propTypeJsDocHandler';
+
+const { handlers } = require('react-docgen');
+
+const defaultHandlers = [
+ preProcessHandler,
+ handlers.propTypeCompositionHandler,
+ propTypeHandler,
+ contextTypeHandler,
+ childContextTypeHandler,
+ handlers.propDocBlockHandler,
+ propTypeJsDocHandler,
+ defaultPropsHandler,
+ handlers.componentDocblockHandler,
+ handlers.displayNameHandler,
+ handlers.componentMethodsJsDocHandler,
+];
+
+export default defaultHandlers;
diff --git a/packages/material-parser/src/parse/js/handlers/preProcessHandler.ts b/packages/material-parser/src/parse/js/handlers/preProcessHandler.ts
new file mode 100644
index 000000000..48541c55b
--- /dev/null
+++ b/packages/material-parser/src/parse/js/handlers/preProcessHandler.ts
@@ -0,0 +1,3 @@
+export default function preProcessHandler(documentation: any, path: any) {
+ documentation.set('meta', path.__meta);
+}
diff --git a/packages/material-parser/src/parse/js/handlers/propTypeHandler.ts b/packages/material-parser/src/parse/js/handlers/propTypeHandler.ts
new file mode 100644
index 000000000..85930ee10
--- /dev/null
+++ b/packages/material-parser/src/parse/js/handlers/propTypeHandler.ts
@@ -0,0 +1,139 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow
+ */
+
+import { namedTypes as t, visit } from 'ast-types';
+import fs from 'fs';
+import path from 'path';
+import getRoot from '../utils/getRoot';
+import findJSFilePath from '../utils/findJSFilePath';
+import getComposedPath from '../utils/getComposedPath';
+const buildParser = require('react-docgen/dist/babelParser').default;
+
+const {
+ resolveToValue,
+ isExportsOrModuleAssignment,
+ getPropType,
+ getPropertyName,
+ getMemberValuePath,
+ isReactModuleName,
+ printValue,
+ resolveToModule,
+} = require('react-docgen').utils;
+
+const expressionTo = require('react-docgen/dist/utils/expressionTo');
+const isRequiredPropType = require('react-docgen/dist/utils/isRequiredPropType')
+ .default;
+
+function isPropTypesExpression(path: any) {
+ const moduleName = resolveToModule(path);
+ if (moduleName) {
+ return isReactModuleName(moduleName) || moduleName === 'ReactPropTypes';
+ }
+ return false;
+}
+
+function amendPropTypes(getDescriptor: any, path: any, documentation, propName: string) {
+ if (!t.ObjectExpression.check(path.node)) {
+ const propTypesPath = getComposedPath(documentation, propName, path);
+ if (!propTypesPath) {
+ return;
+ } else {
+ path.replace(propTypesPath.node);
+ }
+ }
+
+ path.get('properties').each((propertyPath: any) => {
+ switch (propertyPath.node.type) {
+ // @ts-ignore
+ case t.Property.name: {
+ const propName = getPropertyName(propertyPath);
+ if (!propName) return;
+
+ const propDescriptor = getDescriptor(propName);
+ const valuePath = propertyPath.get('value');
+ const type = getPropType(valuePath);
+
+ if (type) {
+ propDescriptor.type = type;
+ propDescriptor.required =
+ type.name !== 'custom' && isRequiredPropType(valuePath);
+ }
+ break;
+ }
+ // @ts-ignore
+ case t.SpreadElement.name: {
+ const resolvedValuePath = resolveToValue(propertyPath.get('argument'));
+ switch (resolvedValuePath.node.type) {
+ // @ts-ignore
+ case t.ObjectExpression.name: // normal object literal
+ amendPropTypes(getDescriptor, resolvedValuePath, documentation, propName);
+ break;
+ }
+ break;
+ }
+ }
+ });
+}
+
+function getDefinePropertyValuePath(nodePath: any, propName: string) {
+ const program = getRoot(nodePath);
+ let resultPath = nodePath;
+ if (!nodePath.node.id) return;
+ const componentName = nodePath.node.id.name;
+
+ visit(program, {
+ visitCallExpression(path) {
+ const args = path.get('arguments');
+ const argsNodeList = args.value;
+ if (
+ argsNodeList.length === 3 &&
+ t.Identifier.check(argsNodeList[0]) &&
+ argsNodeList[0].name === componentName &&
+ t.Literal.check(argsNodeList[1]) &&
+ argsNodeList[1].value === propName
+ ) {
+ resultPath = args.get(2);
+ }
+ return false;
+ },
+ });
+ return resultPath;
+}
+
+function getPropTypeHandler(propName: string) {
+ return function (documentation: any, path: any) {
+ let propTypesPath = getMemberValuePath(path, propName);
+ if (!propTypesPath) {
+ propTypesPath = getDefinePropertyValuePath(path, propName);
+ if (!propTypesPath) {
+ return;
+ }
+ }
+ propTypesPath = resolveToValue(propTypesPath);
+ if (!propTypesPath) {
+ return;
+ }
+ let getDescriptor;
+ switch (propName) {
+ case 'childContextTypes':
+ getDescriptor = documentation.getChildContextDescriptor;
+ break;
+ case 'contextTypes':
+ getDescriptor = documentation.getContextDescriptor;
+ break;
+ default:
+ getDescriptor = documentation.getPropDescriptor;
+ }
+ amendPropTypes(getDescriptor.bind(documentation), propTypesPath, documentation, propName);
+ };
+}
+
+export const propTypeHandler = getPropTypeHandler('propTypes');
+export const contextTypeHandler = getPropTypeHandler('contextTypes');
+export const childContextTypeHandler = getPropTypeHandler('childContextTypes');
diff --git a/packages/material-parser/src/parse/js/handlers/propTypeJsDocHandler.ts b/packages/material-parser/src/parse/js/handlers/propTypeJsDocHandler.ts
new file mode 100644
index 000000000..7fd160c8b
--- /dev/null
+++ b/packages/material-parser/src/parse/js/handlers/propTypeJsDocHandler.ts
@@ -0,0 +1,64 @@
+/* eslint-disable no-param-reassign */
+import { set, get } from 'lodash';
+import { debug } from '../../../core';
+
+const log = debug.extend('parse:js');
+
+const parseJsDoc = require('react-docgen/dist/utils/parseJsDoc').default;
+const { getMemberValuePath, resolveToValue } = require('react-docgen').utils;
+
+function getType(type = 'void') {
+ const typeOfType = typeof type;
+ if (typeOfType === 'string') {
+ return typeOfType;
+ } else if (typeOfType === 'object') {
+ return get(type, 'name', 'void');
+ }
+ return 'void';
+}
+
+function generateRaw(params = [], returns = { type: 'void' }): string {
+ const raw = `(${params.filter(x => !!x).map(x => `${x.name}: ${getType(x.type)}`).join(', ')}) => ${returns ? getType(returns.type) : 'void'}`;
+ return raw;
+}
+
+function resolveDocumentation(documentation) {
+ documentation._props.forEach(propDescriptor => {
+ const { description } = propDescriptor;
+ if (description.includes('@') && propDescriptor?.type?.name === 'func') {
+ const jsDoc = parseJsDoc(description);
+ propDescriptor.description = jsDoc.description;
+ if (jsDoc.params) {
+ set(propDescriptor, ['type', 'params'], jsDoc.params);
+ }
+ if (jsDoc.returns) {
+ set(propDescriptor, ['type', 'returns'], jsDoc.returns);
+ }
+ try {
+ const raw = generateRaw(jsDoc.params, jsDoc.returns);
+ if (raw) {
+ set(propDescriptor, ['type', 'raw'], raw);
+ }
+ } catch (e) {
+ log(e);
+ }
+ }
+ });
+}
+
+/**
+ * Extract info from the propType jsdoc blocks. Must be run after
+ * propDocBlockHandler.
+ */
+export default function propTypeJsDocHandler(documentation, path) {
+ let propTypesPath = getMemberValuePath(path, 'propTypes');
+ if (!propTypesPath) {
+ return;
+ }
+ propTypesPath = resolveToValue(propTypesPath);
+ if (!propTypesPath) {
+ return;
+ }
+
+ resolveDocumentation(documentation);
+}
diff --git a/packages/material-parser/src/parse/js/index.ts b/packages/material-parser/src/parse/js/index.ts
new file mode 100644
index 000000000..283b6bf98
--- /dev/null
+++ b/packages/material-parser/src/parse/js/index.ts
@@ -0,0 +1,42 @@
+import { transformItem } from '../transform';
+import { IMaterialParsedModel } from '../../types';
+import { loadFile } from '../../utils';
+import resolver from './resolver';
+import handlers from './handlers';
+
+const reactDocs = require('react-docgen');
+
+export default function parse(filePath: string): IMaterialParsedModel[] {
+ if (!filePath) return [];
+ const fileContent = loadFile(filePath);
+ const result = reactDocs.parse(
+ fileContent,
+ (ast: any) => {
+ ast.__path = filePath;
+ return resolver(ast);
+ },
+ handlers,
+ {
+ filename: filePath,
+ },
+ );
+ const coms = result.reduce((res: any[], info: any) => {
+ if (!info || !info.props) return res;
+ const props = Object.keys(info.props).reduce((acc: any[], name) => {
+ try {
+ const item: any = transformItem(name, info.props[name]);
+ acc.push(item);
+ } catch (e) {
+ // TODO
+ }
+ return acc;
+ }, []);
+ res.push({
+ componentName: info.displayName,
+ props,
+ meta: info.meta || {},
+ });
+ return res;
+ }, []);
+ return coms;
+}
diff --git a/packages/material-parser/src/parse/js/resolver/checkIsIIFE.ts b/packages/material-parser/src/parse/js/resolver/checkIsIIFE.ts
new file mode 100644
index 000000000..4e56be891
--- /dev/null
+++ b/packages/material-parser/src/parse/js/resolver/checkIsIIFE.ts
@@ -0,0 +1,8 @@
+export default function checkIsIIFE(path: any) {
+ return (
+ path.value &&
+ path.value.callee &&
+ path.value.callee.type === 'FunctionExpression' &&
+ path.node.type === 'CallExpression'
+ );
+}
diff --git a/packages/material-parser/src/parse/js/resolver/findAssignedMethods.ts b/packages/material-parser/src/parse/js/resolver/findAssignedMethods.ts
new file mode 100644
index 000000000..e14a40ac1
--- /dev/null
+++ b/packages/material-parser/src/parse/js/resolver/findAssignedMethods.ts
@@ -0,0 +1,37 @@
+import { namedTypes as t } from 'ast-types';
+import isReactComponentStaticMember from './isReactComponentStaticMember';
+
+const { match } = require('react-docgen').utils;
+const { traverseShallow } = require('react-docgen/dist/utils/traverse');
+
+function findAssignedMethods(scope: any, idPath: any) {
+ const results: any[] = [];
+
+ if (!t.Identifier.check(idPath.node)) {
+ return results;
+ }
+
+ const { name } = idPath.node;
+ // const idScope = idPath.scope.lookup(idPath.node.name);
+
+ traverseShallow(scope.path, {
+ visitAssignmentExpression(path: any) {
+ const { node } = path;
+ if (
+ match(node.left, {
+ type: 'MemberExpression',
+ object: { type: 'Identifier', name },
+ })
+ // && path.scope.lookup(name) === idScope
+ ) {
+ results.push(path);
+ return false;
+ }
+ return this.traverse(path);
+ },
+ });
+
+ return results.filter((x) => !isReactComponentStaticMember(x.get('left')));
+}
+
+export default findAssignedMethods;
diff --git a/packages/material-parser/src/parse/js/resolver/index.ts b/packages/material-parser/src/parse/js/resolver/index.ts
new file mode 100644
index 000000000..ba9175715
--- /dev/null
+++ b/packages/material-parser/src/parse/js/resolver/index.ts
@@ -0,0 +1,393 @@
+import { namedTypes as t, visit } from 'ast-types';
+import { uniqBy } from 'lodash';
+import checkIsIIFE from './checkIsIIFE';
+import resolveHOC from './resolveHOC';
+import resolveIIFE from './resolveIIFE';
+import resolveImport from './resolveImport';
+import resolveTranspiledClass from './resolveTranspiledClass';
+import isStaticMethod from './isStaticMethod';
+import findAssignedMethods from './findAssignedMethods';
+import resolveExportDeclaration from './resolveExportDeclaration';
+import makeProxy from '../utils/makeProxy';
+import { get, set, has, ICache } from '../utils/cache';
+import getName from '../utils/getName';
+import getRoot from '../utils/getRoot';
+
+const expressionTo = require('react-docgen/dist/utils/expressionTo');
+
+const {
+ isExportsOrModuleAssignment,
+ isReactComponentClass,
+ isReactCreateClassCall,
+ isReactForwardRefCall,
+ isStatelessComponent,
+ normalizeClassDefinition,
+ resolveToValue,
+ getMemberValuePath,
+} = require('react-docgen').utils;
+
+function ignore() {
+ return false;
+}
+
+function isComponentDefinition(path: any) {
+ return (
+ isReactCreateClassCall(path) ||
+ isReactComponentClass(path) ||
+ isStatelessComponent(path) ||
+ isReactForwardRefCall(path)
+ );
+}
+
+function resolveDefinition(definition: any) {
+ if (isReactCreateClassCall(definition)) {
+ // return argument
+ const resolvedPath = resolveToValue(definition.get('arguments', 0));
+ if (t.ObjectExpression.check(resolvedPath.node)) {
+ return resolvedPath;
+ }
+ } else if (isReactComponentClass(definition)) {
+ normalizeClassDefinition(definition);
+ return definition;
+ } else if (isStatelessComponent(definition) || isReactForwardRefCall(definition)) {
+ return definition;
+ }
+ return null;
+}
+
+function getDefinition(definition: any, cache: ICache = {}): any {
+ const { __meta: exportMeta = {} } = definition;
+ if (checkIsIIFE(definition)) {
+ definition = resolveToValue(resolveIIFE(definition));
+ if (!isComponentDefinition(definition)) {
+ definition = resolveTranspiledClass(definition);
+ }
+ } else {
+ definition = resolveToValue(resolveHOC(definition));
+ if (isComponentDefinition(definition)) {
+ definition = makeProxy(definition, {
+ __meta: exportMeta,
+ });
+ return definition;
+ }
+ if (checkIsIIFE(definition)) {
+ definition = resolveToValue(resolveIIFE(definition));
+ if (!isComponentDefinition(definition)) {
+ definition = resolveTranspiledClass(definition);
+ }
+ } else if (t.SequenceExpression.check(definition.node)) {
+ const classNameNode = definition.parent.get('id').node;
+ const localNames: string[] = [];
+ let { node } = definition.get('expressions', 0);
+ while (t.AssignmentExpression.check(node)) {
+ // @ts-ignore
+ const { name } = node.left;
+ if (name) {
+ localNames.push(name);
+ }
+ node = node.right;
+ }
+ definition.get('expressions').each((x: any) => {
+ if (!x.name) return;
+ if (t.AssignmentExpression.check(x.node) && t.MemberExpression.check(x.node.left)) {
+ const objectName = x.node.left.object.name;
+ if (localNames.includes(objectName)) {
+ x.get('left', 'object').replace(classNameNode);
+ }
+ }
+ });
+ definition = getDefinition(resolveToValue(definition.get('expressions').get(0)), cache);
+ } else {
+ return resolveImport(definition, (ast: any, sourcePath: string, importMeta, mode) => {
+ let result;
+ if (has('ast-export', ast.__path)) {
+ result = get('ast-export', ast.__path);
+ } else {
+ result = findAllExportedComponentDefinition(ast);
+ set('ast-export', ast.__path, result);
+ }
+
+ const exportList: any[] = [];
+ const importList: any[] = [];
+ result.forEach((def: any) => {
+ const { __meta: meta = {} } = def;
+ let { exportName } = meta;
+ for (const item of importMeta) {
+ if (exportName === item.importedName) {
+ exportName = item.localName;
+ break;
+ }
+ }
+
+ if (exportName) {
+ importList.push(makeProxy(def, { __meta: { exportName } }));
+ }
+
+ const nextMeta: any = {
+ exportName,
+ };
+
+ if (exportName === exportMeta.localName) {
+ nextMeta.exportName = exportMeta.exportName;
+ } else if (mode === 'import') {
+ // } else {
+ return;
+ }
+
+ if (exportMeta.subName) {
+ nextMeta.subName = exportMeta.subName;
+ } else if (meta.subName) {
+ nextMeta.subName = meta.subName;
+ }
+ exportList.push(makeProxy(def, { __meta: nextMeta }));
+ });
+ cache[sourcePath] = importList;
+
+ // result = result.filter((x) => !x.__shouldDelete);
+ return exportList;
+ });
+ }
+ }
+ if (definition && (!definition.__meta || Object.keys(definition.__meta).length === 0)) {
+ definition.__meta = exportMeta;
+ }
+ return definition;
+}
+
+export interface IMethodsPath {
+ subName: string;
+ localName: string;
+ value: any;
+}
+
+/**
+ * Extract all flow types for the methods of a react component. Doesn't
+ * return any react specific lifecycle methods.
+ */
+function getSubComponents(path: any, scope: any, cache: ICache) {
+ // Extract all methods from the class or object.
+ let methodPaths = [];
+ if (isReactComponentClass(path)) {
+ methodPaths = path.get('body', 'body').filter(isStaticMethod);
+ methodPaths = [...methodPaths, ...findAssignedMethods(scope || path.scope, path.get('id'))];
+ } else if (t.ObjectExpression.check(path.node)) {
+ methodPaths = path.get('properties').filter(isStaticMethod);
+ methodPaths = [...methodPaths, ...findAssignedMethods(scope || path.scope, path.get('id'))];
+ // Add the statics object properties.
+ const statics = getMemberValuePath(path, 'statics');
+ if (statics) {
+ statics.get('properties').each((p: any) => {
+ if (isStaticMethod(p)) {
+ p.node.static = true;
+ methodPaths.push(p);
+ }
+ });
+ }
+ } else if (
+ t.VariableDeclarator.check(path.parent.node) &&
+ path.parent.node.init === path.node &&
+ t.Identifier.check(path.parent.node.id)
+ ) {
+ methodPaths = findAssignedMethods(scope || path.parent.scope, path.parent.get('id'));
+ } else if (
+ t.AssignmentExpression.check(path.parent.node) &&
+ path.parent.node.right === path.node &&
+ t.Identifier.check(path.parent.node.left)
+ ) {
+ methodPaths = findAssignedMethods(scope || path.parent.scope, path.parent.get('left'));
+ } else if (t.FunctionDeclaration.check(path.node)) {
+ methodPaths = findAssignedMethods(scope || path.parent.scope, path.get('id'));
+ } else if (t.ArrowFunctionExpression.check(path.node)) {
+ methodPaths = findAssignedMethods(scope || path.parent.scope, path.parent.get('id'));
+ }
+
+ return (
+ methodPaths
+ .map((x: any) => {
+ if (t.ClassProperty.check(x.node)) {
+ return {
+ value: x.get('value'),
+ subName: x.node.key.name,
+ localName: getName(x.get('value')),
+ };
+ }
+ return {
+ value: x,
+ subName: x.node.left.property.name,
+ localName: getName(x.get('right')),
+ };
+ })
+ .map(({ subName, localName, value }: IMethodsPath) => ({
+ subName,
+ localName,
+ value: resolveToValue(value),
+ }))
+ .map(({ subName, localName, value }: IMethodsPath) => {
+ let def = getDefinition(
+ makeProxy(value, {
+ __meta: {
+ localName,
+ subName,
+ exportName: path.__meta && path.__meta.exportName,
+ },
+ }),
+ cache,
+ );
+ if (!Array.isArray(def)) {
+ def = [def];
+ }
+ return {
+ subName,
+ localName,
+ value: def.flatMap((x: any) => x).filter((x: any) => isComponentDefinition(x)),
+ };
+ })
+ .map(({ subName, localName, value }: IMethodsPath) => {
+ return value.map((x: any) => ({
+ subName,
+ localName,
+ value: x,
+ }));
+ })
+ // @ts-ignore
+ .flatMap((x: any) => x)
+ .map(({ subName, value }: IMethodsPath) => {
+ const __meta = {
+ subName,
+ exportName: path.__meta && path.__meta.exportName,
+ };
+ return makeProxy(value, { __meta });
+ })
+ );
+}
+
+/**
+ * Given an AST, this function tries to find the exported component definition.
+ *
+ * The component definition is either the ObjectExpression passed to
+ * `React.createClass` or a `class` definition extending `React.Component` or
+ * having a `render()` method.
+ *
+ * If a definition is part of the following statements, it is considered to be
+ * exported:
+ *
+ * modules.exports = Definition;
+ * exports.foo = Definition;
+ * export default Definition;
+ * export var Definition = ...;
+ */
+export default function findAllExportedComponentDefinition(ast: any) {
+ const components: any[] = [];
+ const cache: ICache = {};
+ let programScope: any;
+
+ function exportDeclaration(path: any) {
+ const definitions = resolveExportDeclaration(path)
+ .reduce((acc: any[], definition: any) => {
+ if (isComponentDefinition(definition)) {
+ acc.push(definition);
+ } else {
+ definition = getDefinition(definition, cache);
+ if (!Array.isArray(definition)) {
+ definition = [definition];
+ }
+ definition.forEach((def: any) => {
+ if (isComponentDefinition(def)) {
+ acc.push(def);
+ }
+ });
+ }
+ return acc;
+ }, [])
+ .map((definition: any) => {
+ const { __meta: meta } = definition;
+ const def = resolveDefinition(definition);
+ return makeProxy(def, { __meta: meta });
+ });
+
+ if (definitions.length === 0) {
+ return false;
+ }
+ definitions.forEach((definition: any) => {
+ if (definition && components.indexOf(definition) === -1) {
+ components.push(definition);
+ }
+ });
+ return false;
+ }
+
+ visit(ast, {
+ visitProgram(path) {
+ programScope = path.scope;
+ return this.traverse(path);
+ },
+ visitFunctionDeclaration: ignore,
+ visitFunctionExpression: ignore,
+ visitClassDeclaration: ignore,
+ visitClassExpression: ignore,
+ visitIfStatement: ignore,
+ visitWithStatement: ignore,
+ visitSwitchStatement: ignore,
+ visitWhileStatement: ignore,
+ visitDoWhileStatement: ignore,
+ visitForStatement: ignore,
+ visitForInStatement: ignore,
+ visitForOfStatement: ignore,
+ visitImportDeclaration: ignore,
+
+ visitExportNamedDeclaration: exportDeclaration,
+ visitExportDefaultDeclaration: exportDeclaration,
+ visitExportAllDeclaration(path) {
+ components.push(...resolveImport(path, findAllExportedComponentDefinition));
+ return false;
+ },
+
+ visitAssignmentExpression(path: any) {
+ // Ignore anything that is not `exports.X = ...;` or
+ // `module.exports = ...;`
+ if (!isExportsOrModuleAssignment(path)) {
+ return false;
+ }
+ const arr = expressionTo.Array(path.get('left'));
+ const meta: any = {
+ exportName: arr[1] === 'exports' ? 'default' : arr[1],
+ };
+ // Resolve the value of the right hand side. It should resolve to a call
+ // expression, something like React.createClass
+ path = resolveToValue(path.get('right'));
+ if (!isComponentDefinition(path)) {
+ path = getDefinition(path, cache);
+ }
+
+ if (!Array.isArray(path)) {
+ path = [path];
+ }
+
+ const definitions = path.map(resolveDefinition);
+
+ definitions.forEach((definition: any) => {
+ if (definition && components.indexOf(definition) === -1) {
+ // if (definition.__meta) {
+ definition = makeProxy(definition, {
+ __meta: meta,
+ });
+ // }
+ components.push(definition);
+ }
+ });
+ return false;
+ },
+ });
+
+ const result = components.reduce((acc, item) => {
+ let subModuleDefinitions = [];
+ subModuleDefinitions = getSubComponents(item, programScope, cache);
+ return [...acc, item, ...subModuleDefinitions];
+ }, []);
+
+ const res = uniqBy(result, (x: any) => {
+ return `${getRoot(x)?.node?.__path}/${x.__meta.exportName}/${x.__meta.subName}`;
+ });
+
+ return res;
+}
diff --git a/packages/material-parser/src/parse/js/resolver/isReactComponentStaticMember.ts b/packages/material-parser/src/parse/js/resolver/isReactComponentStaticMember.ts
new file mode 100644
index 000000000..8249dfac3
--- /dev/null
+++ b/packages/material-parser/src/parse/js/resolver/isReactComponentStaticMember.ts
@@ -0,0 +1,14 @@
+import { namedTypes as t } from 'ast-types';
+
+const { getPropertyName } = require('react-docgen').utils;
+
+const reactStaticMembers = ['propTypes', 'defaultProps', 'contextTypes'];
+export default function isReactComponentStaticMember(methodPath: any) {
+ let name;
+ if (t.MemberExpression.check(methodPath.node)) {
+ name = methodPath.node.property.name;
+ } else {
+ name = getPropertyName(methodPath);
+ }
+ return !!name && reactStaticMembers.indexOf(name) !== -1;
+}
diff --git a/packages/material-parser/src/parse/js/resolver/isStaticMethod.ts b/packages/material-parser/src/parse/js/resolver/isStaticMethod.ts
new file mode 100644
index 000000000..f8168fa8e
--- /dev/null
+++ b/packages/material-parser/src/parse/js/resolver/isStaticMethod.ts
@@ -0,0 +1,15 @@
+import { namedTypes as t } from 'ast-types';
+import isReactComponentStaticMember from './isReactComponentStaticMember';
+
+const { isReactComponentMethod } = require('react-docgen').utils;
+
+/**
+ * judge if static method
+ */
+function isStaticMethod(path: any) {
+ const isProbablyStaticMethod = t.ClassProperty.check(path.node) && path.node.static === true;
+
+ return isProbablyStaticMethod && !isReactComponentStaticMember(path) && !isReactComponentMethod(path);
+}
+
+export default isStaticMethod;
diff --git a/packages/material-parser/src/parse/js/resolver/resolveExportDeclaration.ts b/packages/material-parser/src/parse/js/resolver/resolveExportDeclaration.ts
new file mode 100644
index 000000000..5e8875975
--- /dev/null
+++ b/packages/material-parser/src/parse/js/resolver/resolveExportDeclaration.ts
@@ -0,0 +1,53 @@
+import { namedTypes as t } from 'ast-types';
+import makeProxy from '../utils/makeProxy';
+import getName from '../utils/getName';
+
+export default function resolveExportDeclaration(path: any) {
+ const definitions = [];
+ if (path.node.default || t.ExportDefaultDeclaration.check(path.node)) {
+ const def = path.get('declaration');
+ const meta: { [name: string]: string } = {
+ exportName: 'default',
+ localName: getName(def),
+ };
+
+ definitions.push(makeProxy(def, { __meta: meta }));
+ } else if (path.node.declaration) {
+ if (t.VariableDeclaration.check(path.node.declaration)) {
+ path.get('declaration', 'declarations').each((declarator: any) => {
+ definitions.push(
+ makeProxy(declarator, {
+ __meta: {
+ exportName: declarator.get('id').node.name,
+ },
+ }),
+ );
+ });
+ } else {
+ const def = path.get('declaration');
+ definitions.push(
+ makeProxy(def, {
+ __meta: {
+ exportName: 'default',
+ },
+ }),
+ );
+ }
+ } else if (path.node.specifiers) {
+ path.get('specifiers').each((specifier: any) => {
+ const def = specifier.node.id ? specifier.get('id') : specifier.get('local');
+ const exportName = specifier.get('exported').node.name;
+ const localName = def.get('local').node.name;
+
+ definitions.push(
+ makeProxy(def, {
+ __meta: {
+ exportName,
+ localName,
+ },
+ }),
+ );
+ });
+ }
+ return definitions;
+}
diff --git a/packages/material-parser/src/parse/js/resolver/resolveHOC.ts b/packages/material-parser/src/parse/js/resolver/resolveHOC.ts
new file mode 100644
index 000000000..ab62f895f
--- /dev/null
+++ b/packages/material-parser/src/parse/js/resolver/resolveHOC.ts
@@ -0,0 +1,42 @@
+import { namedTypes as t } from 'ast-types';
+
+const { isReactCreateClassCall, isReactForwardRefCall } = require('react-docgen').utils;
+
+/**
+ * If the path is a call expression, it recursively resolves to the
+ * rightmost argument, stopping if it finds a React.createClass call expression
+ *
+ * Else the path itself is returned.
+ */
+export default function resolveHOC(path: any): any {
+ const { node } = path;
+ if (
+ t.CallExpression.check(node) &&
+ !isReactCreateClassCall(path) &&
+ !isReactForwardRefCall(path)
+ ) {
+ if (node.arguments.length) {
+ const inner = path.get('arguments', 0);
+
+ // If the first argument is one of these types then the component might be the last argument
+ // If there are all identifiers then we cannot figure out exactly and have to assume it is the first
+ if (
+ node.arguments.length > 1 &&
+ (t.Literal.check(inner.node) ||
+ t.ObjectExpression.check(inner.node) ||
+ t.ArrayExpression.check(inner.node) ||
+ t.SpreadElement.check(inner.node))
+ ) {
+ return resolveHOC(
+ // resolveToValue(path.get('arguments', node.arguments.length - 1)),
+ path.get('arguments', node.arguments.length - 1),
+ );
+ }
+
+ // return resolveHOC(resolveToValue(inner));
+ return resolveHOC(inner);
+ }
+ }
+
+ return path;
+}
diff --git a/packages/material-parser/src/parse/js/resolver/resolveIIFE.ts b/packages/material-parser/src/parse/js/resolver/resolveIIFE.ts
new file mode 100644
index 000000000..371cde5fb
--- /dev/null
+++ b/packages/material-parser/src/parse/js/resolver/resolveIIFE.ts
@@ -0,0 +1,20 @@
+import checkIsIIFE from './checkIsIIFE';
+
+const resolveFunctionDefinitionToReturnValue = require('react-docgen/dist/utils/resolveFunctionDefinitionToReturnValue')
+ .default;
+/**
+ * If the path is a call expression, it recursively resolves to the
+ * rightmost argument, stopping if it finds a React.createClass call expression
+ *
+ * Else the path itself is returned.
+ */
+export default function resolveIIFE(path: any) {
+ if (!checkIsIIFE(path)) {
+ return path;
+ }
+ const returnValue = resolveFunctionDefinitionToReturnValue(
+ path.get('callee'),
+ );
+
+ return returnValue;
+}
diff --git a/packages/material-parser/src/parse/js/resolver/resolveImport.ts b/packages/material-parser/src/parse/js/resolver/resolveImport.ts
new file mode 100644
index 000000000..2acefff6f
--- /dev/null
+++ b/packages/material-parser/src/parse/js/resolver/resolveImport.ts
@@ -0,0 +1,178 @@
+import { namedTypes as t } from 'ast-types';
+import fs from 'fs';
+import p from 'path';
+import getRoot from '../utils/getRoot';
+
+const { resolveToModule, resolveToValue, match } = require('react-docgen').utils;
+
+export function isImportLike(path) {
+ const { node } = path;
+ return (
+ t.ImportDeclaration.check(node) ||
+ t.ExportAllDeclaration.check(node) ||
+ t.ExportNamedDeclaration.check(node)
+ );
+}
+
+export function isRequireLike(path: any) {
+ if (
+ t.CallExpression.check(path.node) &&
+ t.Identifier.check(path.get('callee').node) &&
+ path.get('callee').node.name === 'require' &&
+ t.Literal.check(path.get('arguments', 0)?.node)
+ ) {
+ return true;
+ }
+
+ return false;
+}
+
+export function resolveToImport(initialPath) {
+ const pathBuffer = [initialPath];
+
+ while (pathBuffer.length) {
+ let path = pathBuffer.shift();
+ const node = path.node;
+ switch (node.type) {
+ case 'VariableDeclarator':
+ if (node.init) {
+ pathBuffer.unshift(path.get('init'));
+ }
+ break;
+ case 'CallExpression': {
+ if (match(node.callee, { type: 'Identifier', name: 'require' })) {
+ return path;
+ }
+ const paths = [path.get('callee')];
+ const argumentsPath = path.get('arguments');
+ for (let index = 0; index < argumentsPath.value.length; index++) {
+ paths.push(argumentsPath.get(index));
+ }
+ pathBuffer.unshift(...paths);
+ }
+ case 'Identifier':
+ case 'JSXIdentifier': {
+ const valuePath = resolveToValue(path);
+ if (valuePath !== path) {
+ pathBuffer.unshift(valuePath);
+ }
+ break;
+ }
+ case 'ImportDeclaration':
+ return path;
+ case 'MemberExpression':
+ while (path && t.MemberExpression.check(path.node)) {
+ path = path.get('object');
+ }
+ if (path) {
+ pathBuffer.unshift(path);
+ }
+ }
+ }
+
+ return null;
+}
+
+function getPath(path: any, name: any) {
+ const root = getRoot(path).node;
+ if (!root) return;
+ let { __path } = root;
+ __path = p.dirname(__path);
+ // is directory
+ if (fs.existsSync(p.resolve(__path, name))) {
+ name += '/index';
+ }
+ const suffix = suffixes.find((suf) => {
+ return fs.existsSync(p.resolve(__path, name + suf));
+ });
+ if (!suffix) return;
+ return p.resolve(__path, name + suffix);
+}
+
+const buildParser = require('react-docgen/dist/babelParser').default;
+
+const suffixes = ['.js', '.jsx', '.ts', '.tsx'];
+
+const cache: {
+ [name: string]: any;
+} = {};
+
+export default function resolveImport(path: any, callback: any) {
+ let name;
+ let mode: 'import' | 'require' = 'import';
+
+ let importPath;
+ if (path.name === 'local') {
+ name = path.parentPath.parentPath.parentPath.node.source.value;
+ importPath = path;
+ } else {
+ importPath = resolveToImport(path);
+ if (!importPath) {
+ return path;
+ }
+ if (isImportLike(importPath)) {
+ name = importPath.node.source.value;
+ } else if (isRequireLike(importPath)) {
+ const moduleName = resolveToModule(importPath);
+ if (typeof moduleName === 'string') {
+ mode = 'require';
+ name = moduleName;
+ }
+ } else {
+ return path;
+ }
+ }
+
+ if (name) {
+ const __path = getPath(path, name);
+ if (!__path) return path;
+ let ast;
+ if (!cache[__path]) {
+ const fileContent = fs.readFileSync(__path, 'utf8');
+ const parser = buildParser({ filename: __path });
+ ast = parser.parse(fileContent);
+ ast.__src = fileContent;
+ ast.__path = __path;
+ cache[__path] = ast;
+ } else {
+ ast = cache[__path];
+ }
+
+ const importMeta: any[] = [];
+ if (mode === 'import') {
+ if (t.ImportDeclaration.check(importPath.node)) {
+ // @ts-ignore
+ const specifiers = importPath.get('specifiers');
+ specifiers.each((spec: any) => {
+ const { node } = spec;
+ importMeta.push({
+ localName: node.local.name,
+ importedName: node.imported ? node.imported.name : 'default',
+ });
+ });
+ }
+ } else {
+ const idPath = importPath.parentPath.get('id');
+ if (t.Identifier.check(idPath.node)) {
+ importMeta.push({
+ localName: 'default',
+ importedName: idPath.node.name,
+ });
+ } else if (t.ObjectPattern.check(path.node)) {
+ path.get('properties').each((propertyPath) => {
+ const keyPath = propertyPath.get('key');
+ const valuePath = propertyPath.get('value');
+ if (t.Identifier.check(keyPath.node) && t.Identifier.check(valuePath.node)) {
+ importMeta.push({
+ localName: keyPath.node.name,
+ importedName: valuePath.node.name,
+ });
+ }
+ });
+ }
+ }
+
+ return callback(ast, __path, importMeta, mode);
+ }
+ return path;
+}
diff --git a/packages/material-parser/src/parse/js/resolver/resolveTranspiledClass.ts b/packages/material-parser/src/parse/js/resolver/resolveTranspiledClass.ts
new file mode 100644
index 000000000..992d0321b
--- /dev/null
+++ b/packages/material-parser/src/parse/js/resolver/resolveTranspiledClass.ts
@@ -0,0 +1,31 @@
+import { builders, NodePath, visit } from 'ast-types';
+/**
+ * If the path is a call expression, it recursively resolves to the
+ * rightmost argument, stopping if it finds a React.createClass call expression
+ *
+ * Else the path itself is returned.
+ */
+export default function resolveTranspiledClass(path: any) {
+ let classPath = path;
+ visit(path, {
+ visitFunctionDeclaration(arg) {
+ classPath = new NodePath(
+ builders.functionDeclaration(
+ // @ts-ignore
+ arg.node.id || 'Default',
+ [],
+ builders.blockStatement([
+ builders.returnStatement(
+ builders.jsxElement(
+ builders.jsxOpeningElement(builders.jsxIdentifier('div'), [], true),
+ ),
+ ),
+ ]),
+ ),
+ path.parent,
+ );
+ return false;
+ },
+ });
+ return classPath;
+}
diff --git a/packages/material-parser/src/parse/js/utils/cache.ts b/packages/material-parser/src/parse/js/utils/cache.ts
new file mode 100644
index 000000000..c8bcabb8d
--- /dev/null
+++ b/packages/material-parser/src/parse/js/utils/cache.ts
@@ -0,0 +1,18 @@
+export interface ICache {
+ [name: string]: any;
+}
+
+const cache: ICache = {};
+
+export function set(scope: string, name: string, value: any) {
+ cache[scope] = cache[scope] || {};
+ cache[scope][name] = value;
+}
+
+export function get(scope: string, name: string) {
+ return (cache[scope] || {})[name];
+}
+
+export function has(scope: string, name: string) {
+ return cache[scope] && Object.prototype.hasOwnProperty.call(cache[scope], name);
+}
diff --git a/packages/material-parser/src/parse/js/utils/evaluate.ts b/packages/material-parser/src/parse/js/utils/evaluate.ts
new file mode 100644
index 000000000..91388d2ba
--- /dev/null
+++ b/packages/material-parser/src/parse/js/utils/evaluate.ts
@@ -0,0 +1,103 @@
+const { namedTypes: t } = require('ast-types');
+
+const { resolveToValue } = require('react-docgen').utils;
+
+function isInfinity(path) {
+ return t.Identifier.check(path.node) && path.node.name === 'Infinity';
+}
+
+function wrapValue(value, confident = true) {
+ return {
+ value,
+ confident,
+ };
+}
+
+export default function evaluate(path: any) {
+ if (t.UnaryExpression.check(path.node)) {
+ if (path.node.operator === 'void') {
+ return wrapValue(undefined);
+ }
+
+ const argument = path.get('argument');
+
+ const result = evaluate(argument);
+ if (!result.confident) {
+ return wrapValue(undefined, false);
+ }
+
+ const arg = result.value;
+ if (arg === undefined) {
+ return wrapValue(undefined);
+ }
+
+ switch (path.node.operator) {
+ case '!':
+ return wrapValue(!arg);
+ case '+':
+ return wrapValue(+arg);
+ case '-':
+ return wrapValue(-arg);
+ case '~':
+ return wrapValue(~arg);
+ case 'typeof':
+ return wrapValue(typeof arg);
+ }
+ }
+
+ if (t.Identifier.check(path.node)) {
+ const valuePath = resolveToValue(path);
+ if (isInfinity(valuePath)) {
+ return wrapValue(undefined);
+ }
+ return evaluate(valuePath);
+ }
+
+ if (t.Literal.check(path.node)) {
+ return wrapValue(path.node.value);
+ }
+
+ if (t.ObjectExpression.check(path.node)) {
+ const returnValue = {};
+ path.get('properties').each((propertyPath) => {
+ const { confident, value } = evaluate(propertyPath.get('value'));
+ if (!confident) {
+ return;
+ }
+ const keyPath = propertyPath.get('key');
+ let key;
+ if (keyPath.node.computed) {
+ const result = evaluate(keyPath);
+ if (!result.confident) {
+ return;
+ }
+ key = result.value;
+ } else {
+ key = keyPath.node.name;
+ }
+ returnValue[key] = value;
+ });
+
+ return wrapValue(returnValue);
+ }
+
+ if (t.ArrayExpression.check(path.node)) {
+ const value = [];
+ let isValid = true;
+ path.get('elements').each((x) => {
+ if (!isValid) return;
+ const result = evaluate(x);
+ if (!result.confident) {
+ isValid = false;
+ } else {
+ value.push(result.value);
+ }
+ });
+
+ if (isValid) {
+ return wrapValue(value);
+ }
+ }
+
+ return wrapValue(undefined, false);
+}
diff --git a/packages/material-parser/src/parse/js/utils/findJSFilePath.ts b/packages/material-parser/src/parse/js/utils/findJSFilePath.ts
new file mode 100644
index 000000000..d5ec20518
--- /dev/null
+++ b/packages/material-parser/src/parse/js/utils/findJSFilePath.ts
@@ -0,0 +1,15 @@
+import fs from 'fs';
+
+const suffixes = ['js', 'jsx'];
+export default function findJSFilePath(fileBasePath: string): string {
+ let filePath;
+ for (const suffix of suffixes) {
+ const fp = `${fileBasePath}.${suffix}`;
+ if (fs.existsSync(fp)) {
+ filePath = fp;
+ break;
+ }
+ }
+
+ return filePath;
+}
\ No newline at end of file
diff --git a/packages/material-parser/src/parse/js/utils/getComposedPath.ts b/packages/material-parser/src/parse/js/utils/getComposedPath.ts
new file mode 100644
index 000000000..471af46a4
--- /dev/null
+++ b/packages/material-parser/src/parse/js/utils/getComposedPath.ts
@@ -0,0 +1,51 @@
+import { namedTypes as t, visit } from 'ast-types';
+import fs from 'fs';
+import path from 'path';
+import getRoot from './getRoot';
+import findJSFilePath from './findJSFilePath';
+
+const buildParser = require('react-docgen/dist/babelParser').default;
+const expressionTo = require('react-docgen/dist/utils/expressionTo');
+
+const {
+ resolveToValue,
+ isExportsOrModuleAssignment,
+} = require('react-docgen').utils;
+
+export default function getComposedPropTypesPath(documentation, propName, p) {
+ const composes: string[] = Array.from(documentation._composes);
+ let _path = null;
+ const root = getRoot(p).node;
+ for (const compose of composes) {
+ const composePath = findJSFilePath(path.resolve(path.dirname(root.__path), compose));
+ if (!composePath) continue;
+
+ const fileContent = fs.readFileSync(composePath, 'utf8');
+ const parser = buildParser({ filename: composePath });
+ const ast = parser.parse(fileContent);
+
+ visit(ast, {
+ visitAssignmentExpression(path: any) {
+ // Ignore anything that is not `exports.X = ...;` or
+ // `module.exports = ...;`
+ if (!isExportsOrModuleAssignment(path)) {
+ return false;
+ }
+ const arr = expressionTo.Array(path.get('left'));
+ if (!(arr[0] === 'exports' && arr[1] === propName)) return false;
+
+ // Resolve the value of the right hand side. It should resolve to a call
+ // expression, something like React.createClass
+ path = resolveToValue(path.get('right'));
+ _path = path;
+ return false;
+ },
+ });
+
+ if (_path) {
+ break;
+ }
+ }
+
+ return _path;
+}
\ No newline at end of file
diff --git a/packages/material-parser/src/parse/js/utils/getName.ts b/packages/material-parser/src/parse/js/utils/getName.ts
new file mode 100644
index 000000000..81f48cc71
--- /dev/null
+++ b/packages/material-parser/src/parse/js/utils/getName.ts
@@ -0,0 +1,13 @@
+import { namedTypes as t } from 'ast-types';
+
+export default function (def: any) {
+ let name = '';
+ if (def.node.name) {
+ name = def.node.name;
+ // hoc
+ } else if (t.CallExpression.check(def.node)) {
+ if (def.node.arguments && def.node.arguments.length && t.Identifier.check(def.get('arguments', 0).node)) name = def.get('arguments', 0).node.name;
+ }
+
+ return name;
+}
diff --git a/packages/material-parser/src/parse/js/utils/getRoot.ts b/packages/material-parser/src/parse/js/utils/getRoot.ts
new file mode 100644
index 000000000..3a20579d3
--- /dev/null
+++ b/packages/material-parser/src/parse/js/utils/getRoot.ts
@@ -0,0 +1,7 @@
+export default function getRoot(path: any) {
+ let root = path.parent;
+ while (root.parent) {
+ root = root.parent;
+ }
+ return root;
+}
diff --git a/packages/material-parser/src/parse/js/utils/makeProxy.ts b/packages/material-parser/src/parse/js/utils/makeProxy.ts
new file mode 100644
index 000000000..4f6c7ace1
--- /dev/null
+++ b/packages/material-parser/src/parse/js/utils/makeProxy.ts
@@ -0,0 +1,23 @@
+function makeProxy(target: { [name: string]: any }, meta: any = {}): any {
+ if (target.__isProxy) {
+ const value = target.__getRaw();
+ const rawMeta = target.__getMeta();
+ return makeProxy(value, Object.assign({}, rawMeta, meta));
+ }
+ return new Proxy(target, {
+ get: (obj, prop: string | number) => {
+ if (prop === '__isProxy') return true;
+ if (prop === '__getRaw') return () => target;
+ if (prop === '__getMeta') return () => meta;
+ return Object.prototype.hasOwnProperty.call(meta, prop) ? meta[prop] : obj[prop];
+ },
+ has: (obj, prop) => {
+ return (
+ Object.prototype.hasOwnProperty.call(obj, prop) ||
+ Object.prototype.hasOwnProperty.call(meta, prop)
+ );
+ },
+ });
+}
+
+export default makeProxy;
diff --git a/packages/material-parser/src/parse/transform.ts b/packages/material-parser/src/parse/transform.ts
new file mode 100644
index 000000000..6325be8b4
--- /dev/null
+++ b/packages/material-parser/src/parse/transform.ts
@@ -0,0 +1,306 @@
+import { omit, pick, isNil, uniq } from 'lodash';
+import { safeEval, isEvaluable } from '../utils';
+import { debug } from '../core';
+
+const log = debug.extend('parse:transform');
+
+export function transformType(itemType: any) {
+ if (typeof itemType === 'string') return itemType;
+ const {
+ name,
+ elements,
+ value = elements,
+ computed,
+ required,
+ type,
+ raw,
+ params,
+ returns,
+ } = itemType;
+ if (computed !== undefined && value) {
+ return safeEval(value);
+ }
+ const result: any = {
+ type: name,
+ };
+ if (required) {
+ result.isRequired = required;
+ }
+ switch (name) {
+ case 'number':
+ case 'string':
+ case 'bool':
+ case 'any':
+ case 'symbol':
+ case 'object':
+ case 'null':
+ case 'array':
+ case 'element':
+ case 'node':
+ case 'void':
+ break;
+ case 'func':
+ if (params) {
+ result.params = params.map((x) => {
+ const res: any = {
+ name: x.name,
+ propType: transformType(x.type || x.propType),
+ };
+ if (x.description) {
+ res.description = x.description;
+ }
+ return res;
+ });
+ }
+ if (returns) {
+ result.returns = {
+ propType: transformType(returns.type || returns.propType),
+ };
+ }
+ if (raw) {
+ result.raw = raw;
+ }
+ break;
+ case 'literal': {
+ result.type = 'oneOf';
+ try {
+ const literalValue = safeEval(value);
+ result.value = [literalValue];
+ } catch (e) {
+ result.value = [raw];
+ }
+ break;
+ }
+ case 'enum':
+ case 'oneOf':
+ result.type = 'oneOf';
+ result.value = value.map(transformType);
+ break;
+ case 'tuple':
+ result.type = 'tuple';
+ result.value = value.map(transformType);
+ break;
+ case 'union': {
+ if (itemType.raw) {
+ if (itemType.raw.match(/ReactNode$/)) {
+ result.type = 'node';
+ break;
+ } else if (itemType.raw.match(/Element$/)) {
+ result.type = 'element';
+ break;
+ }
+ }
+ }
+ // eslint-disable-next-line no-fallthrough
+ case 'oneOfType':
+ result.type = 'oneOfType';
+ result.value = value.map(transformType);
+ break;
+ case 'boolean':
+ result.type = 'bool';
+ break;
+ case 'Function':
+ result.type = 'func';
+ break;
+ case 'unknown':
+ result.type = 'any';
+ break;
+ case 'Array':
+ case 'arrayOf': {
+ result.type = 'arrayOf';
+ let _itemType = transformType(value[0]);
+ if (typeof _itemType === 'object') {
+ _itemType = omit(_itemType, ['isRequired']);
+ }
+
+ result.value = _itemType;
+ break;
+ }
+ case 'signature': {
+ if (typeof type === 'string') {
+ result.type = type;
+ break;
+ }
+ result.type = 'shape';
+ const properties = type?.signature?.properties || itemType?.signature?.properties || [];
+ if (properties.length === 0) {
+ if (raw?.includes('=>')) {
+ result.type = 'func';
+ result.raw = raw;
+ } else {
+ result.type = 'object';
+ }
+ } else if (properties.length === 1 && typeof properties[0].key === 'object') {
+ const v = transformType(properties[0].value);
+ if (v === 'any') {
+ result.type = 'object';
+ } else if (typeof v === 'string') {
+ result.value = v;
+ result.type = 'objectOf';
+ } else if (typeof v?.type === 'string') {
+ result.value = v.type;
+ result.type = 'objectOf';
+ } else {
+ result.type = 'object';
+ }
+ } else if (properties.length === 1 && properties[0].key === '__call') {
+ result.type = 'func';
+ } else {
+ result.value = properties
+ .filter((item: any) => typeof item.key !== 'object')
+ .map((prop: any) => {
+ const { key } = prop;
+ const typeItem = {
+ ...omit(prop.value, 'name'),
+ type: prop.value.type || {},
+ };
+ typeItem.type = {
+ ...typeItem.type,
+ ...pick(prop.value, ['name', 'value']),
+ };
+ return transformItem(key, typeItem);
+ });
+ }
+ break;
+ }
+ case 'objectOf':
+ case 'instanceOf':
+ result.value = transformType(value);
+ break;
+ case 'exact':
+ case 'shape':
+ result.value = Object.keys(value).map((n) => {
+ const { name: _name, ...others } = value[n];
+ return transformItem(n, {
+ ...others,
+ type: {
+ name: _name,
+ },
+ });
+ });
+ break;
+ case (name.match(/ReactNode$/) || {}).input:
+ result.type = 'node';
+ break;
+ case (name.match(/JSX\.Element$/) || {}).input:
+ result.type = 'element';
+ break;
+ default:
+ result.type = 'object';
+ break;
+ }
+ if (Object.keys(result).length === 1) {
+ return result.type;
+ }
+ if (result?.type === 'oneOfType') {
+ return combineOneOfValues(result);
+ }
+ return result;
+}
+
+function combineOneOfValues(propType) {
+ if (propType.type !== 'oneOfType') {
+ return propType;
+ }
+ const newValue = [];
+ let oneOfItem = null;
+ let firstBooleanIndex = -1;
+ propType.value.forEach((item) => {
+ if (item?.type === 'oneOf') {
+ if (!oneOfItem) {
+ oneOfItem = {
+ type: 'oneOf',
+ value: [],
+ };
+ }
+ if (item.value.includes(true) || item.value.includes(false)) {
+ if (firstBooleanIndex !== -1) {
+ oneOfItem.value.splice(firstBooleanIndex, 1);
+ newValue.push('bool');
+ } else {
+ firstBooleanIndex = oneOfItem.value.length;
+ oneOfItem.value = oneOfItem.value.concat(item.value);
+ }
+ } else {
+ oneOfItem.value = oneOfItem.value.concat(item.value);
+ }
+ } else {
+ newValue.push(item);
+ }
+ });
+ let result = propType;
+ const oneOfItemLength = oneOfItem?.value?.length;
+ if (oneOfItemLength) {
+ newValue.push(oneOfItem);
+ }
+ if (firstBooleanIndex !== -1 || oneOfItemLength) {
+ result = {
+ ...propType,
+ value: newValue,
+ };
+ }
+ if (result.value.length === 1 && result.value[0]?.type === 'oneOf') {
+ result = {
+ ...result,
+ type: 'oneOf',
+ value: result.value[0].value,
+ };
+ }
+ result.value = uniq(result.value);
+ return result;
+}
+
+export function transformItem(name: string, item: any) {
+ const {
+ description,
+ flowType,
+ tsType,
+ type = tsType || flowType,
+ optional,
+ required = optional,
+ defaultValue,
+ ...others
+ } = item;
+ const result: any = {
+ name,
+ };
+
+ if (type) {
+ result.propType = transformType({
+ ...type,
+ ...omit(others, ['name']),
+ required: !!required,
+ });
+ }
+ if (description) {
+ if (description.includes('\n')) {
+ result.description = description.split('\n')[0];
+ } else {
+ result.description = description;
+ }
+ }
+ if (!isNil(defaultValue) && typeof defaultValue === 'object' && isEvaluable(defaultValue)) {
+ if (defaultValue === null) {
+ result.defaultValue = defaultValue;
+ } else {
+ // if ('computed' in defaultValue) {
+ // val = val.value;
+ try {
+ const value = safeEval(defaultValue.value);
+ if (isEvaluable(value)) {
+ result.defaultValue = value;
+ }
+ } catch (e) {
+ log(e);
+ }
+ }
+ // else {
+ // result.defaultValue = defaultValue.value;
+ // }
+ }
+ if (result.propType === undefined) {
+ delete result.propType;
+ }
+
+ return result;
+}
diff --git a/packages/material-parser/src/parse/ts/generateDTS.ts b/packages/material-parser/src/parse/ts/generateDTS.ts
new file mode 100644
index 000000000..79ccf853c
--- /dev/null
+++ b/packages/material-parser/src/parse/ts/generateDTS.ts
@@ -0,0 +1,56 @@
+import * as path from 'path';
+import { writeFileSync, pathExistsSync, ensureDirSync, copySync } from 'fs-extra';
+import { loadFile } from '../../utils';
+
+import { debug } from '../../core';
+
+const log = debug.extend('parse:ts:generate_dts');
+
+/**
+ * Generate alias dts file by removing some needless interfaces.
+ * Replace original file at present, which will cause type pollution, looking for better solution
+ * @param {string} workDir - the dir containing the module to be parsed
+ * @returns {string} - the path of generated xxx.d.ts
+ */
+export default function generateDTS({
+ workDir,
+ dslType = 'react',
+}: {
+ workDir: string;
+ dslType?: string;
+}): {
+ originalTypePath: string;
+ newTypePath: string;
+} {
+ const typeDir = path.join(workDir, 'node_modules', `@types/${dslType}`);
+ const typePath = path.join(typeDir, 'index.d.ts');
+ const fileContent = loadFile(typePath);
+ // const materialParserTypeDir = path.join(workDir, `node_modules/material-parser-types/${type}`);
+ // ensureDirSync(materialParserTypeDir);
+ const materialParserTypeDir = typeDir;
+ const newTypePath = path.join(materialParserTypeDir, 'index.d.ts');
+ // if (!pathExistsSync(newTypePath)) {
+ // copySync(
+ // path.join(typeDir, 'global.d.ts'),
+ // path.join(materialParserTypeDir, 'global.d.ts'),
+ // );
+ let newContent = fileContent.replace(
+ /(?<=interface HTMLAttributes[^e]+)(extends[^}]+)/,
+ `{
+ style?: CSSProperties;
+ className?: string;
+ `,
+ );
+ newContent = newContent.replace(/(?<=interface IntrinsicElements {)([^}]+)/, '');
+ newContent = newContent.replace(/type LibraryManagedAttributes[^;]+;/, '');
+ writeFileSync(newTypePath, newContent);
+ log('generate dts', newTypePath);
+ // } else {
+ // log('found dts', newTypePath);
+ // }
+
+ return {
+ originalTypePath: typePath,
+ newTypePath,
+ };
+}
diff --git a/packages/material-parser/src/parse/ts/index.ts b/packages/material-parser/src/parse/ts/index.ts
new file mode 100644
index 000000000..059d9fb90
--- /dev/null
+++ b/packages/material-parser/src/parse/ts/index.ts
@@ -0,0 +1,611 @@
+import * as path from 'path';
+import { Parser, ComponentDoc } from 'react-docgen-typescript';
+import ts, { SymbolFlags, TypeFlags, SyntaxKind } from 'typescript';
+import { isEmpty, isEqual } from 'lodash';
+import { existsSync, readFileSync } from 'fs-extra';
+import findConfig from 'find-config';
+import { debug } from '../../core';
+import { Json } from '../../types';
+import { transformItem } from '../transform';
+import generateDTS from './generateDTS';
+import { IParseArgs } from '../index';
+
+const log = debug.extend('parse:ts');
+
+type ExtendedType = ts.Type & {
+ id: string;
+ typeArguments: any[];
+};
+
+function getNextParentIds(parentIds: number[], type: ts.Type) {
+ // @ts-ignore
+ const id = type?.symbol?.id;
+ if (id) {
+ return [...parentIds, id];
+ }
+ return parentIds;
+}
+
+function getSymbolName(symbol: ts.Symbol) {
+ // @ts-ignore
+ const prefix: string = symbol?.parent && getSymbolName(symbol.parent);
+ const name = symbol.getName();
+ if (prefix && prefix.length <= 20) {
+ return `${prefix}.${name}`;
+ }
+ return name;
+}
+
+function getFunctionParams(parameters: any[] = [], checker, parentIds, type) {
+ return parameters.map((node) => {
+ const typeObject = checker.getTypeOfSymbolAtLocation(node.symbol, node.symbol.valueDeclaration);
+ const v = getDocgenTypeHelper(checker, typeObject, false, getNextParentIds(parentIds, type));
+ const name = node.symbol.escapedName;
+ return {
+ name,
+ propType: v,
+ };
+ });
+}
+
+function getFunctionReturns(node: any, checker, parentIds, type) {
+ if (!node) return {};
+ const propType = getDocgenTypeHelper(
+ checker,
+ node.type,
+ false,
+ getNextParentIds(parentIds, type),
+ );
+ return {
+ propType,
+ };
+}
+
+const blacklistNames = [
+ 'prototype',
+ 'getDerivedStateFromProps',
+ 'propTypes',
+ 'defaultProps',
+ 'contextTypes',
+ 'displayName',
+ 'contextType',
+ 'Provider',
+ 'Consumer',
+];
+
+const blacklistPatterns = [
+ /^HTML/,
+ /^React\./,
+ /^Object$/,
+ /^Date$/,
+ /^Promise$/,
+ /^XML/,
+ /^Function$/,
+];
+
+// function hasTooManyTypes(type) {
+// return type?.types?.length >= 20;
+// }
+
+function isComplexType(type) {
+ let isAliasSymbol = false;
+ let symbol = type?.symbol;
+ if (!symbol) {
+ symbol = type?.aliasSymbol;
+ isAliasSymbol = true;
+ }
+ if (!symbol) return false;
+ if (isAliasSymbol) {
+ return false;
+ }
+ const name = getSymbolName(symbol);
+ if (blacklistPatterns.some((patt) => patt.test(name))) {
+ return true;
+ }
+ return false;
+}
+
+function getDocgenTypeHelper(
+ checker: ts.TypeChecker,
+ type: ts.Type,
+ skipRequired = false,
+ parentIds: number[] = [],
+ isRequired = false,
+): any {
+ function isTuple(_type: ts.Type) {
+ // @ts-ignore use internal methods
+ return checker.isArrayLikeType(_type) && !checker.isArrayType(_type);
+ }
+ let required: boolean;
+ if (isRequired !== undefined) {
+ required = isRequired;
+ } else {
+ required = !(type.flags & SymbolFlags.Optional) || isRequired;
+ }
+
+ function makeResult(typeInfo: Json) {
+ if (skipRequired) {
+ return {
+ raw: checker.typeToString(type),
+ ...typeInfo,
+ };
+ } else {
+ return {
+ required,
+ raw: checker.typeToString(type),
+ ...typeInfo,
+ };
+ }
+ }
+
+ function getShapeFromArray(symbolArr: ts.Symbol[], _type: ts.Type) {
+ const shape: Array<{
+ key:
+ | {
+ name: string;
+ }
+ | string;
+ value: any;
+ }> = symbolArr.map((prop) => {
+ const propType = checker.getTypeOfSymbolAtLocation(
+ prop,
+ // @ts-ignore
+ prop.valueDeclaration || (prop.declarations && prop.declarations[0]) || {},
+ );
+ return {
+ key: prop.getName(),
+
+ value: getDocgenTypeHelper(
+ checker,
+ propType,
+ false,
+ // @ts-ignore
+ getNextParentIds(parentIds, _type),
+ // @ts-ignore
+ !prop?.valueDeclaration?.questionToken,
+ ),
+ };
+ });
+ // @ts-ignore use internal methods
+ if (checker.isArrayLikeType(_type)) {
+ return shape;
+ }
+ if (_type.getStringIndexType()) {
+ // @ts-ignore use internal methods
+ if (!_type.stringIndexInfo) {
+ return shape;
+ }
+ shape.push({
+ key: {
+ name: 'string',
+ },
+ value: getDocgenTypeHelper(
+ checker,
+ // @ts-ignore use internal methods
+ _type.stringIndexInfo.type,
+ false,
+ getNextParentIds(parentIds, _type),
+ ),
+ });
+ } else if (_type.getNumberIndexType()) {
+ // @ts-ignore use internal methods
+ if (!_type.numberIndexInfo) {
+ return shape;
+ }
+ shape.push({
+ key: {
+ name: 'number',
+ },
+
+ value: getDocgenTypeHelper(
+ checker,
+ // @ts-ignore use internal methods
+ _type.numberIndexInfo.type,
+ false,
+ getNextParentIds(parentIds, _type),
+ ),
+ });
+ }
+ return shape;
+ }
+
+ function getShape(_type: ts.Type) {
+ const { symbol } = _type;
+ if (symbol && symbol.members) {
+ // @ts-ignore
+ const props: ts.Symbol[] = Array.from(symbol.members.values());
+ // if (props.length >= 20) {
+ // throw new Error('too many props');
+ // }
+ return getShapeFromArray(
+ props.filter((prop) => prop.getName() !== '__index'),
+ _type,
+ );
+ } else {
+ // @ts-ignore
+ const args = _type.resolvedTypeArguments || [];
+ const props = checker.getPropertiesOfType(_type);
+ // if (props.length >= 20) {
+ // throw new Error('too many props');
+ // }
+ const shape = getShapeFromArray(props.slice(0, args.length), _type);
+ return shape;
+ }
+ }
+
+ // @ts-ignore
+ if (type?.kind === SyntaxKind.VoidExpression) {
+ return makeResult({
+ name: 'void',
+ raw: 'void',
+ });
+ }
+
+ const pattern = /^__global\.(.+)$/;
+ // @ts-ignore
+ if (parentIds.includes(type?.symbol?.id)) {
+ return makeResult({
+ name: 'object', // checker.typeToString(type),
+ });
+ }
+ if (type.symbol) {
+ const symbolName = getSymbolName(type.symbol);
+ if (symbolName) {
+ const matches = pattern.exec(symbolName);
+ if (matches) {
+ return makeResult({
+ name: matches[1],
+ });
+ }
+ }
+ }
+
+ if (type.flags & TypeFlags.Number) {
+ return makeResult({
+ name: 'number',
+ });
+ } else if (type.flags & TypeFlags.String) {
+ return makeResult({
+ name: 'string',
+ });
+ } else if (type.flags & TypeFlags.NumberLiteral) {
+ return makeResult({
+ name: 'literal',
+ // @ts-ignore
+ value: type.value,
+ });
+ } else if (type.flags & TypeFlags.Literal) {
+ return makeResult({
+ name: 'literal',
+ value: checker.typeToString(type),
+ });
+ } else if (type.symbol?.flags & SymbolFlags.Enum) {
+ return makeResult({
+ name: 'union',
+ // @ts-ignore
+ value: type.types.map((t) => t.value),
+ });
+ // @ts-ignore
+ } else if (type.flags & TypeFlags.DisjointDomains) {
+ return makeResult({
+ name: checker.typeToString(type),
+ });
+ } else if (type.flags & TypeFlags.Any) {
+ return makeResult({
+ name: 'any',
+ });
+ } else if (type.flags & TypeFlags.Union && !isComplexType(type)) {
+ return makeResult({
+ name: 'union',
+ // @ts-ignore
+ value: type.types.map((t) =>
+ getDocgenTypeHelper(checker, t, true, getNextParentIds(parentIds, type)),
+ ),
+ });
+ } else if (isComplexType(type)) {
+ return makeResult({
+ name: getSymbolName(type?.symbol || type?.aliasSymbol),
+ });
+ } else if (type.flags & (TypeFlags.Object | TypeFlags.Intersection)) {
+ if (isTuple(type)) {
+ try {
+ const props = getShape(type);
+ return makeResult({
+ name: 'tuple',
+ value: props.map((p) => p.value),
+ });
+ } catch (e) {
+ return makeResult({
+ name: 'object',
+ });
+ }
+
+ // @ts-ignore
+ } else if (checker.isArrayType(type)) {
+ return makeResult({
+ name: 'Array',
+ // @ts-ignore
+ elements: [
+ getDocgenTypeHelper(
+ checker,
+ (type as ExtendedType).typeArguments[0],
+ false,
+ getNextParentIds(parentIds, type),
+ ),
+ ],
+ });
+ // @ts-ignore
+ } else if (type?.symbol?.valueDeclaration?.parameters?.length) {
+ return makeResult({
+ name: 'func',
+ params: getFunctionParams(
+ // @ts-ignore
+ type?.symbol?.valueDeclaration?.parameters,
+ checker,
+ parentIds,
+ type,
+ ),
+ returns: getFunctionReturns(
+ checker.typeToTypeNode(type, type?.symbol?.valueDeclaration),
+ checker,
+ parentIds,
+ type,
+ ),
+ });
+ } else if (
+ // @ts-ignore
+ type?.members?.get('__call')?.declarations[0]?.symbol?.declarations[0]?.parameters?.length
+ ) {
+ return makeResult({
+ name: 'func',
+ params: getFunctionParams(
+ // @ts-ignore
+ type?.members?.get('__call')?.declarations[0]?.symbol?.declarations[0]?.parameters,
+ checker,
+ parentIds,
+ type,
+ ),
+ });
+ } else {
+ try {
+ const props = getShape(type);
+ return makeResult({
+ name: 'signature',
+ type: {
+ signature: {
+ properties: props,
+ },
+ },
+ });
+ } catch (e) {
+ return makeResult({
+ name: 'object',
+ });
+ }
+ }
+ } else {
+ return makeResult({
+ name: 'object',
+ });
+ }
+}
+class MyParser extends Parser {
+ getDocgenType(propType: ts.Type): any {
+ const parentIds = [];
+ // @ts-ignore
+ const parentId = propType?.symbol?.parent?.id;
+ if (parentId) {
+ parentIds.push(parentId);
+ }
+ // @ts-ignore
+ const result = getDocgenTypeHelper(this.checker, propType, true, parentIds);
+ return result;
+ }
+
+ // override the builtin method, to avoid the false positive
+ public extractPropsFromTypeIfStatelessComponent(type: ts.Type): ts.Symbol | null {
+ const callSignatures = type.getCallSignatures();
+
+ if (callSignatures.length) {
+ // Could be a stateless component. Is a function, so the props object we're interested
+ // in is the (only) parameter.
+
+ for (const sig of callSignatures) {
+ const params = sig.getParameters();
+ if (params.length === 0) {
+ continue;
+ }
+
+ // @ts-ignore
+ const returnSymbol = this.checker.getReturnTypeOfSignature(sig);
+ if (!returnSymbol) continue;
+ const symbol = returnSymbol?.symbol;
+ if (!symbol) continue;
+ // @ts-ignore
+ const typeString = this.checker.symbolToString(symbol);
+ if (
+ typeString.startsWith('ReactElement') ||
+ typeString.startsWith('Element') ||
+ typeString.startsWith('RaxElement')
+ ) {
+ const propsParam = params[0];
+ if (propsParam) {
+ return propsParam;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+}
+
+const getCompilerOptions = (reactTypePath, originalReactTypePath) => {
+ const options: any = {
+ jsx: ts.JsxEmit.React,
+ module: ts.ModuleKind.CommonJS,
+ target: ts.ScriptTarget.Latest,
+ allowSyntheticDefaultImports: true,
+ };
+ // if (reactTypePath) {
+ // options.paths = {
+ // react: [reactTypePath],
+ // };
+ // options.exclude = [path.dirname(originalReactTypePath)];
+ // options.types = [];
+ // options.skipLibCheck = true;
+ // }
+ return options;
+};
+
+interface SymbolWithMeta extends ts.Symbol {
+ meta?: {
+ exportName: string;
+ subName?: string;
+ };
+}
+
+function getComponentName(exportName, displayName) {
+ if (displayName) {
+ const firstCharCode = displayName.charCodeAt(0);
+ if (firstCharCode >= 65 && firstCharCode <= 90) {
+ return displayName || exportName;
+ }
+ }
+ return exportName;
+}
+
+const defaultTsConfigPath = path.resolve(__dirname, './tsconfig.json');
+
+export default function parseTS(filePath: string, args: IParseArgs): ComponentDoc[] {
+ if (!filePath) return [];
+
+ let basePath = args.moduleDir || args.workDir || path.dirname(filePath);
+ let tsConfigPath = findConfig('tsconfig.json', { cwd: basePath }); // path.resolve(basePath, 'tsconfig.json')
+ if (
+ !tsConfigPath ||
+ !existsSync(tsConfigPath) ||
+ (args.accesser === 'online' && tsConfigPath === 'tsconfig.json')
+ ) {
+ tsConfigPath = defaultTsConfigPath;
+ } else {
+ basePath = path.dirname(tsConfigPath);
+ }
+
+ log('ts config path is', tsConfigPath);
+ const { config, error } = ts.readConfigFile(tsConfigPath, (filename) =>
+ readFileSync(filename, 'utf8'),
+ );
+
+ if (error !== undefined) {
+ const errorText = `Cannot load custom tsconfig.json from provided path: ${tsConfigPath}, with error code: ${error.code}, message: ${error.messageText}`;
+ throw new Error(errorText);
+ }
+
+ const { options, errors } = ts.parseJsonConfigFileContent(
+ config,
+ ts.sys,
+ basePath,
+ {},
+ tsConfigPath,
+ );
+
+ if (errors && errors.length) {
+ throw errors[0];
+ }
+ log('ts config is', options);
+ // const filePaths = Array.isArray(filePathOrPaths) ? filePathOrPaths : [filePathOrPaths];
+ generateDTS(args);
+ const program = ts.createProgram([filePath], options);
+
+ const parser = new MyParser(program, {});
+
+ const checker = program.getTypeChecker();
+
+ const result = [filePath]
+ .map((fPath) => program.getSourceFile(fPath))
+ .filter((sourceFile) => typeof sourceFile !== 'undefined')
+ .reduce((docs: any[], sourceFile) => {
+ const moduleSymbol = checker.getSymbolAtLocation(sourceFile as ts.Node);
+
+ if (!moduleSymbol) {
+ return docs;
+ }
+
+ const exportSymbols = checker.getExportsOfModule(moduleSymbol);
+
+ for (let index = 0; index < exportSymbols.length; index++) {
+ const sym: SymbolWithMeta = exportSymbols[index];
+ const name = sym.getName();
+ if (blacklistNames.includes(name)) {
+ continue;
+ }
+
+ // polyfill valueDeclaration
+ sym.valueDeclaration =
+ sym.valueDeclaration || (Array.isArray(sym.declarations) && sym.declarations[0]);
+
+ if (!sym.valueDeclaration) {
+ continue;
+ }
+ const info = parser.getComponentInfo(sym, sourceFile);
+ if (info === null) {
+ continue;
+ }
+ const exportName = sym.meta && sym.meta.exportName;
+ const meta = {
+ subName: exportName ? name : '',
+ exportName: exportName || name,
+ };
+ if (docs.find((x) => isEqual(x.meta, meta))) {
+ continue;
+ }
+ docs.push({
+ ...info,
+ meta,
+ });
+ // find sub components
+ if (!!sym.declarations && sym.declarations.length === 0) {
+ continue;
+ }
+
+ const type = checker.getTypeOfSymbolAtLocation(
+ sym,
+ sym.valueDeclaration || sym.declarations[0],
+ );
+ Array.prototype.push.apply(
+ exportSymbols,
+ type.getProperties().map((x: SymbolWithMeta) => {
+ x.meta = { exportName: name };
+ return x;
+ }),
+ );
+ }
+
+ return docs;
+ }, []);
+ const coms = result.reduce((res: any[], info: any) => {
+ if (!info || !info.props || isEmpty(info.props)) return res;
+ const props = Object.keys(info.props).reduce((acc: any[], name) => {
+ // omit aria related properties temporarily
+ if (name.startsWith('aria-')) {
+ return acc;
+ }
+ try {
+ const item: any = transformItem(name, info.props[name]);
+ acc.push(item);
+ } catch (e) {
+ log(e);
+ }
+ return acc;
+ }, []);
+ const exportName = info?.meta?.exportName;
+ res.push({
+ componentName: getComponentName(exportName, info.displayName),
+ props,
+ meta: info.meta || {},
+ });
+ return res;
+ }, []);
+ return coms;
+}
diff --git a/packages/material-parser/src/parse/ts/tsconfig.json b/packages/material-parser/src/parse/ts/tsconfig.json
new file mode 100644
index 000000000..533839dce
--- /dev/null
+++ b/packages/material-parser/src/parse/ts/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "jsx": "react",
+ "target": "es6",
+ "module": "commonjs",
+ "allowSyntheticDefaultImports": true,
+ "allowJs": true
+ },
+ "include": ["**/*"],
+ "exclude": [""]
+}
diff --git a/packages/material-parser/src/scan.ts b/packages/material-parser/src/scan.ts
new file mode 100644
index 000000000..f6bb09e76
--- /dev/null
+++ b/packages/material-parser/src/scan.ts
@@ -0,0 +1,78 @@
+import {
+ IInternalMaterializeOptions,
+ IMaterializeOnlinePackageAndVersionOptions,
+ IMaterialScanModel,
+} from './types';
+import { pathExists, lstatSync } from 'fs-extra';
+import { join, isAbsolute, resolve } from 'path';
+import { debug } from './core';
+import { resolvePkgJson } from './utils';
+
+const log = debug.extend('mat');
+
+export default async function scan(
+ options: IInternalMaterializeOptions,
+): Promise {
+ const model: IMaterialScanModel = {
+ pkgName: '',
+ pkgVersion: '',
+ mainFileAbsolutePath: '',
+ mainFilePath: '',
+ };
+ log('options', options);
+ // 入口文件路径
+ const entryFilePath = options.entry;
+ const stats = lstatSync(entryFilePath);
+ if (
+ (options.accesser === 'local' ||
+ (options.accesser === 'online' &&
+ (options as IMaterializeOnlinePackageAndVersionOptions).name &&
+ options.entry)) &&
+ stats.isFile()
+ ) {
+ if (options.accesser === 'online') {
+ model.useEntry = true;
+ }
+ if (isAbsolute(entryFilePath)) {
+ model.mainFilePath = entryFilePath;
+ model.mainFileAbsolutePath = entryFilePath;
+ } else {
+ model.mainFilePath = entryFilePath;
+ model.mainFileAbsolutePath = resolve(entryFilePath);
+ }
+ }
+ const pkgJsonPath = join(options.root, 'package.json');
+ if (await pathExists(pkgJsonPath)) {
+ const pkgJson = await resolvePkgJson(pkgJsonPath);
+ model.pkgName = pkgJson.name;
+ model.pkgVersion = pkgJson.version;
+ if (pkgJson.module) {
+ const moduleFileAbsolutePath = join(options.root, pkgJson.module);
+ if (await pathExists(moduleFileAbsolutePath)) {
+ model.moduleFilePath = pkgJson.module;
+ model.moduleFileAbsolutePath = moduleFileAbsolutePath;
+ }
+ }
+ model.mainFilePath = model.mainFilePath || pkgJson.main || './index.js';
+ model.mainFileAbsolutePath = model.mainFileAbsolutePath || join(entryFilePath, pkgJson.main);
+ const typingsPathCandidates = [
+ pkgJson.typings,
+ pkgJson.types,
+ './index.d.ts',
+ './lib/index.d.ts',
+ ];
+ for (let i = 0; i < typingsPathCandidates.length; i++) {
+ const typingsFilePath = typingsPathCandidates[i];
+ if (!typingsFilePath) continue;
+ const typingsFileAbsolutePath = join(options.root, typingsFilePath);
+ if (await pathExists(typingsFileAbsolutePath)) {
+ model.typingsFileAbsolutePath = typingsFileAbsolutePath;
+ model.typingsFilePath = typingsFilePath;
+ break;
+ }
+ }
+ }
+
+ log('model', model);
+ return model;
+}
diff --git a/packages/material-parser/src/types/Basic.ts b/packages/material-parser/src/types/Basic.ts
new file mode 100644
index 000000000..18752003b
--- /dev/null
+++ b/packages/material-parser/src/types/Basic.ts
@@ -0,0 +1,5 @@
+export interface Json {
+ [x: string]: string | number | boolean | Date | Json | JsonArray;
+}
+export type JsonArray = Array;
+export type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never;
diff --git a/packages/material-parser/src/types/ChannelType.ts b/packages/material-parser/src/types/ChannelType.ts
new file mode 100644
index 000000000..1f9953480
--- /dev/null
+++ b/packages/material-parser/src/types/ChannelType.ts
@@ -0,0 +1,9 @@
+/**
+ * 物料接入渠道
+ */
+export enum ChannelType {
+ /** 本地 */
+ LOCAL = 'local',
+ /** 在线 */
+ ONLINE = 'online',
+}
diff --git a/packages/material-parser/src/types/DSLType.ts b/packages/material-parser/src/types/DSLType.ts
new file mode 100644
index 000000000..dc9133554
--- /dev/null
+++ b/packages/material-parser/src/types/DSLType.ts
@@ -0,0 +1,4 @@
+/**
+ * DSL类型
+ */
+export type DSLType = 'react' | 'rax';
diff --git a/packages/material-parser/src/types/IAccesser.ts b/packages/material-parser/src/types/IAccesser.ts
new file mode 100644
index 000000000..3495817d7
--- /dev/null
+++ b/packages/material-parser/src/types/IAccesser.ts
@@ -0,0 +1,14 @@
+import { ComponentMeta } from '../core';
+
+/**
+ * 接入器接口(用于定义物料化组件的接入渠道)
+ * @interface IAccesser
+ */
+export interface IAccesser {
+ /**
+ * 接入
+ * @returns {Promise}
+ * @memberof IAccesser
+ */
+ access(): Promise;
+}
diff --git a/packages/material-parser/src/types/IExtensionConfigManifest.ts b/packages/material-parser/src/types/IExtensionConfigManifest.ts
new file mode 100644
index 000000000..a1f711033
--- /dev/null
+++ b/packages/material-parser/src/types/IExtensionConfigManifest.ts
@@ -0,0 +1,13 @@
+import { ComponentMeta } from '../core';
+/**
+ * 扩展点:配置 manifest
+ * (物料化场景)
+ */
+export type IExtensionConfigManifest = (params: {
+ manifestObj: ComponentMeta; // manifest 配置对象
+ manifestFilePath: string; // manifest 文件默认路径
+}) => Promise<{
+ manifestJSON: string; // manifest 文件内容
+ manifestFilePath: string; // manifest 文件路径
+ manifestObj: ComponentMeta; // manifest 文件对象
+}>;
diff --git a/packages/material-parser/src/types/IMaterialParsedModel.ts b/packages/material-parser/src/types/IMaterialParsedModel.ts
new file mode 100644
index 000000000..c263d4651
--- /dev/null
+++ b/packages/material-parser/src/types/IMaterialParsedModel.ts
@@ -0,0 +1,22 @@
+import { PropsSection } from '../core';
+/**
+ * 对应解析器分析出的一些关键信息
+ */
+export interface IPropType {
+ name: string;
+ type: string;
+ value?: IPropTypes;
+ required: boolean;
+}
+
+export type IPropTypes = IPropType[];
+
+export interface IMaterialParsedModel {
+ // filePath: string;
+ componentName: string;
+ props?: PropsSection['props'];
+ meta?: {
+ exportName?: string;
+ subName?: string;
+ };
+}
diff --git a/packages/material-parser/src/types/IMaterialScanModel.ts b/packages/material-parser/src/types/IMaterialScanModel.ts
new file mode 100644
index 000000000..f2da73b35
--- /dev/null
+++ b/packages/material-parser/src/types/IMaterialScanModel.ts
@@ -0,0 +1,23 @@
+/**
+ * 对应扫描阶段的产物
+ */
+export interface IMaterialScanModel {
+ /** 当前包名 */
+ pkgName: string;
+ /** 当前包版本 */
+ pkgVersion: string;
+ /** 在ts场景下,使用entry */
+ useEntry?: boolean;
+ /** main文件相对路径 */
+ mainFilePath: string;
+ /** module文件相对路径 */
+ moduleFilePath?: string;
+ /** typings文件相对路径 */
+ typingsFilePath?: string;
+ /** main文件绝对路径 */
+ mainFileAbsolutePath: string;
+ /** module文件绝对路径 */
+ moduleFileAbsolutePath?: string;
+ /** typings文件绝对路径 */
+ typingsFileAbsolutePath?: string;
+}
diff --git a/packages/material-parser/src/types/IMaterializeOptions.ts b/packages/material-parser/src/types/IMaterializeOptions.ts
new file mode 100644
index 000000000..72e37689e
--- /dev/null
+++ b/packages/material-parser/src/types/IMaterializeOptions.ts
@@ -0,0 +1,117 @@
+import { Expand } from './Basic';
+import { DSLType } from './DSLType';
+/**
+ * 通用入料配置项
+ * @interface IMaterializeCommonOptions
+ */
+export interface IMaterializeCommonOptions {
+ /**
+ * 当 accesser=online 时,配置要使用的 npm client,如:tnpm、cnpm、yarn、npm
+ */
+ npmClient?: string;
+ /**
+ * 当前dsl类型,可选值包括'react' | 'rax'
+ */
+ dslType?: DSLType;
+}
+
+/**
+ * 本地入料配置项
+ * @interface IMaterializeOnlineOptions
+ */
+export interface IMaterializeLocalOptions extends IMaterializeCommonOptions {
+ /**
+ * 接入渠道
+ * (local:表示本地物料工作台方式接入,online:表示在线 npm 包接入)
+ * @type {('local' | 'online')}
+ * @memberof IMaterializeOptions
+ */
+ accesser: 'local';
+
+ /**
+ * 组件文件(夹)路径或包名
+ * 形如:
+ * 本地路径:/usr/project/src/container/DemoMaterial
+ * 包名:@ali/demo-material@0.0.1
+ */
+ entry: string;
+
+ /**
+ * 组件根目录,当entry为文件路径的时候,可以用root来指定根目录,当entry为文件夹时,root默认为entry
+ * 形如:
+ * 相对路径:./
+ * 绝对路径:/usr/project/src/container/DemoMaterial
+ */
+ root?: string;
+}
+
+/**
+ * 在线入料配置项
+ * @interface IMaterializeOnlineOptions
+ */
+export interface IMaterializeOnlineCommonOptions {
+ /**
+ * 接入渠道
+ * (local:表示本地物料工作台方式接入,online:表示在线 npm 包接入)
+ * @type {('local' | 'online')}
+ * @memberof IMaterializeOptions
+ */
+ accesser: 'online';
+ /**
+ * 临时工作目录,用来存放下载的npm包,可为绝对路径或相对路径
+ */
+ tempDir?: string;
+}
+
+/**
+ * 只通过entry指定包名&版本号,无需内部路径
+ */
+export interface IMaterializeOnlineEntryOptions {
+ /**
+ * npm包名&版本号,此时无需指定内部路径,会从package.json自动解析
+ * 形如:
+ * 包名&版本号:@ali/demo-material@0.0.1
+ */
+ entry: string;
+}
+
+export interface IMaterializeOnlinePackageAndVersionOptions {
+ /**
+ * npm包内部相对路径
+ * 形如:
+ * 相对路径:lib/index.js
+ */
+ entry?: string;
+
+ /**
+ * npm包名
+ * 形如:
+ * react-color
+ */
+ name: string;
+
+ /**
+ * npm包版本号
+ * 形如:
+ * latest/1.0.0/1.x.0
+ * @default latest
+ */
+ version?: string;
+}
+
+export type IMaterializeOnlineOptions = Expand<
+ IMaterializeCommonOptions &
+ IMaterializeOnlineCommonOptions &
+ (IMaterializeOnlineEntryOptions | IMaterializeOnlinePackageAndVersionOptions)
+>;
+/**
+ * 入料配置项
+ * @interface IMaterializeOptions
+ */
+export type IMaterializeOptions = Expand;
+
+export type IInternalMaterializeOptions = Expand<
+ IMaterializeOptions & {
+ root: string;
+ }
+>;
diff --git a/packages/material-parser/src/types/Meta.ts b/packages/material-parser/src/types/Meta.ts
new file mode 100644
index 000000000..2cf810ce4
--- /dev/null
+++ b/packages/material-parser/src/types/Meta.ts
@@ -0,0 +1,14 @@
+import { Path } from 'ast-types';
+
+export interface IFileMeta {
+ src: string;
+ path: string;
+ exports: IDefinitionMeta[];
+}
+
+export interface IDefinitionMeta {
+ subDefinitions: IDefinitionMeta[];
+ nodePath: typeof Path;
+ exportName: string;
+ id: string;
+}
diff --git a/packages/material-parser/src/types/index.ts b/packages/material-parser/src/types/index.ts
new file mode 100644
index 000000000..be700f7b6
--- /dev/null
+++ b/packages/material-parser/src/types/index.ts
@@ -0,0 +1,8 @@
+export * from './ChannelType';
+export * from './DSLType';
+export * from './IAccesser';
+export * from './IExtensionConfigManifest';
+export * from './IMaterializeOptions';
+export * from './IMaterialScanModel';
+export * from './IMaterialParsedModel';
+export * from './Basic';
diff --git a/packages/material-parser/src/utils.ts b/packages/material-parser/src/utils.ts
new file mode 100644
index 000000000..dfd36d880
--- /dev/null
+++ b/packages/material-parser/src/utils.ts
@@ -0,0 +1,129 @@
+import { pathExists, readFileSync, writeFile } from 'fs-extra';
+import { isPlainObject } from 'lodash';
+import originalSafeEval from 'safe-eval';
+import * as path from 'path';
+import spawn from 'cross-spawn-promise';
+import { DSLType } from './types';
+
+export async function isNPMInstalled(args: {
+ workDir: string;
+ moduleDir: string;
+ npmClient?: string;
+}) {
+ return pathExists(path.join(args.workDir, 'node_modules'));
+}
+
+export async function install(args: { workDir: string; moduleDir: string; npmClient?: string }) {
+ if (await isNPMInstalled(args)) return;
+ const { workDir, npmClient = 'tnpm' } = args;
+ try {
+ await spawn(npmClient, ['i'], { stdio: 'inherit', cwd: workDir } as any);
+ } catch (e) {
+ // TODO
+ }
+}
+
+export async function installModule(
+ args: { workDir: string; moduleDir: string; npmClient?: string },
+ name: string,
+) {
+ const { workDir, npmClient = 'tnpm' } = args;
+ try {
+ await spawn(npmClient, ['i', name], { stdio: 'inherit', cwd: workDir } as any);
+ } catch (e) {
+ // TODO
+ }
+}
+
+export function installTypeDTS(args: {
+ workDir: string;
+ moduleDir: string;
+ npmClient?: string;
+ dslType?: DSLType;
+}) {
+ return installModule(args, `@types/${args.dslType || 'react'}`);
+}
+
+export async function installTypeScript(args: {
+ workDir: string;
+ moduleDir: string;
+ npmClient?: string;
+}) {
+ if (await pathExists(path.join(args.workDir, 'node_modules', '.bin', 'tsc'))) return;
+ const { workDir, npmClient = 'tnpm' } = args;
+ await spawn(npmClient, ['i', 'typescript'], { stdio: 'inherit', cwd: workDir } as any);
+}
+
+export async function installPeerAndDevDeps(args: {
+ workDir: string;
+ moduleDir: string;
+ npmClient?: string;
+}) {
+ const { workDir, moduleDir, npmClient = 'tnpm' } = args;
+ const modulePkgJsonPath = path.resolve(moduleDir, 'package.json');
+ if (!(await pathExists(modulePkgJsonPath))) {
+ return;
+ }
+ const pkgJsonPath = path.resolve(workDir, 'package.json');
+ if (!(await pathExists(pkgJsonPath))) {
+ return;
+ }
+ const modulePkgJson = await resolvePkgJson(modulePkgJsonPath);
+ const pkgJson = await resolvePkgJson(pkgJsonPath);
+ const { peerDependencies = {}, devDependencies = {} } = modulePkgJson;
+ pkgJson.dependencies = pkgJson.dependencies || {};
+ pkgJson.dependencies = {
+ ...pkgJson.dependencies,
+ ...peerDependencies,
+ ...devDependencies,
+ };
+ await writeFile(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
+ await spawn(npmClient, ['i'], { stdio: 'inherit', cwd: workDir } as any);
+}
+
+export async function syncTypeModules(args: {
+ workDir: string;
+ moduleDir: string;
+ npmClient?: string;
+}) {
+ const { workDir, moduleDir, npmClient = 'tnpm' } = args;
+ const pkgJsonPath = path.resolve(moduleDir, 'package.json');
+ if (!(await pathExists(pkgJsonPath))) {
+ return;
+ }
+ await installModule(args, 'typesync');
+ await spawn(npmClient.replace('m', 'x'), ['typesync'], { stdio: 'inherit', cwd: workDir } as any);
+}
+
+export async function resolvePkgJson(pkgJsonPath: string): Promise<{ [k: string]: any }> {
+ const content = await loadFile(pkgJsonPath);
+ const json = JSON.parse(content);
+ return json;
+}
+
+export function loadFile(filePath: string): string {
+ const content: string | Buffer = readFileSync(filePath);
+ if (typeof content === 'string') {
+ return content;
+ }
+ return content.toString();
+}
+
+export function isPrimitive(val) {
+ return !['object', 'function'].includes(typeof val) || val === null;
+}
+
+export function isEvaluable(value) {
+ if (isPrimitive(value)) return true;
+ if (Array.isArray(value)) {
+ return value.every(isEvaluable);
+ } else if (isPlainObject(value)) {
+ return Object.keys(value).every((key) => isEvaluable(value[key]));
+ }
+ return false;
+}
+
+export function safeEval(value: any) {
+ if (typeof value === 'string') return originalSafeEval(value);
+ return value;
+}
diff --git a/packages/material-parser/src/validate/index.ts b/packages/material-parser/src/validate/index.ts
new file mode 100644
index 000000000..3028b85c5
--- /dev/null
+++ b/packages/material-parser/src/validate/index.ts
@@ -0,0 +1,14 @@
+import Ajv from 'ajv';
+import { Json } from '../types/Basic';
+import schema from './schema.json';
+
+const ajv = new Ajv({ jsonPointers: true });
+const validate = ajv.compile(schema);
+
+export default function validateSchema(json: Json) {
+ if (validate(json) === false) {
+ throw new Error(JSON.stringify(validate.errors, null, 2));
+ }
+
+ return true;
+}
diff --git a/packages/material-parser/src/validate/schema.json b/packages/material-parser/src/validate/schema.json
new file mode 100644
index 000000000..5a0364f76
--- /dev/null
+++ b/packages/material-parser/src/validate/schema.json
@@ -0,0 +1,548 @@
+{
+ "$id": "@ali/low-code-component-protocol-schema",
+ "description": "json schema for low code component protocol",
+ "allOf": [
+ {
+ "$ref": "#/definitions/BasicSection"
+ },
+ {
+ "$ref": "#/definitions/PropsSection"
+ },
+ {
+ "$ref": "#/definitions/ConfigureSection"
+ }
+ ],
+ "definitions": {
+ "BasicSection": {
+ "type": "object",
+ "properties": {
+ "componentName": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "docUrl": {
+ "type": "string"
+ },
+ "screenshot": {
+ "type": "string"
+ },
+ "icon": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "devMode": {
+ "enum": [
+ "proCode",
+ "lowCode"
+ ]
+ },
+ "npm": {
+ "$ref": "#/definitions/Npm"
+ }
+ },
+ "required": [
+ "componentName",
+ "title",
+ "npm"
+ ]
+ },
+ "PropsSection": {
+ "type": "object",
+ "required": [
+ "props"
+ ],
+ "properties": {
+ "props": {
+ "type": "array",
+ "items": {
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "propType": {
+ "$ref": "#/definitions/PropType"
+ },
+ "description": {
+ "type": "string"
+ },
+ "defaultValue": {}
+ },
+ "required": [
+ "name",
+ "propType"
+ ]
+ }
+ }
+ }
+ },
+ "ConfigureSection": {
+ "type": "object",
+ "properties": {
+ "configure": {
+ "type": "object",
+ "properties": {
+ "props": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/ConfigureProp"
+ }
+ },
+ "styles": {
+ "type": "object",
+ "properties": {}
+ },
+ "events": {
+ "type": "object",
+ "properties": {}
+ },
+ "component": {
+ "$ref": "#/definitions/ConfigureComponent"
+ }
+ }
+ }
+ }
+ },
+ "Npm": {
+ "type": "object",
+ "properties": {
+ "package": {
+ "type": "string"
+ },
+ "exportName": {
+ "type": "string"
+ },
+ "subName": {
+ "type": "string"
+ },
+ "main": {
+ "type": "string"
+ },
+ "destructuring": {
+ "type": "boolean"
+ },
+ "version": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "package",
+ "exportName",
+ "subName",
+ "main",
+ "destructuring",
+ "version"
+ ]
+ },
+ "PropType": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/BasicType"
+ },
+ {
+ "$ref": "#/definitions/RequiredType"
+ },
+ {
+ "$ref": "#/definitions/ComplexType"
+ }
+ ]
+ },
+ "BasicType": {
+ "type": "string",
+ "enum": [
+ "array",
+ "bool",
+ "func",
+ "number",
+ "object",
+ "string",
+ "node",
+ "element",
+ "any"
+ ]
+ },
+ "RequiredType": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/BasicType"
+ },
+ "isRequired": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "type"
+ ]
+ },
+ "ComplexType": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/OneOf"
+ },
+ {
+ "$ref": "#/definitions/OneOfType"
+ },
+ {
+ "$ref": "#/definitions/ArrayOf"
+ },
+ {
+ "$ref": "#/definitions/ObjectOf"
+ },
+ {
+ "$ref": "#/definitions/Shape"
+ },
+ {
+ "$ref": "#/definitions/Exact"
+ }
+ ]
+ },
+ "OneOf": {
+ "type": "object",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "oneOf"
+ ]
+ },
+ "value": {
+ "type": "array",
+ "items": {
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "number"
+ },
+ {
+ "type": "boolean"
+ }
+ ]
+ }
+ },
+ "isRequired": {
+ "type": "boolean"
+ }
+ }
+ },
+ "OneOfType": {
+ "type": "object",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "oneOfType"
+ ]
+ },
+ "value": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/PropType"
+ }
+ },
+ "isRequired": {
+ "type": "boolean"
+ }
+ }
+ },
+ "ArrayOf": {
+ "type": "object",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "arrayOf"
+ ]
+ },
+ "value": {
+ "$ref": "#/definitions/PropType"
+ },
+ "isRequired": {
+ "type": "boolean"
+ }
+ }
+ },
+ "ObjectOf": {
+ "type": "object",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "objectOf"
+ ]
+ },
+ "value": {
+ "$ref": "#/definitions/PropType"
+ },
+ "isRequired": {
+ "type": "boolean"
+ }
+ }
+ },
+ "Shape": {
+ "type": "object",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "shape"
+ ]
+ },
+ "value": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "propType": {
+ "$ref": "#/definitions/PropType"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "isRequired": {
+ "type": "boolean"
+ }
+ }
+ },
+ "ShapeItem": {
+ "type": "object",
+ "required": [
+ "name",
+ "propType"
+ ],
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "propType": {
+ "$ref": "#/definitions/PropType"
+ },
+ "isRequired": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ },
+ "Exact": {
+ "type": "object",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "exact"
+ ]
+ },
+ "value": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "propType": {
+ "$ref": "#/definitions/PropType"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "isRequired": {
+ "type": "boolean"
+ }
+ }
+ },
+ "ConfigureProp": {
+ "type": "object",
+ "allOf": [
+ {
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string"
+ },
+ "extraProps": {
+ "type": "object",
+ "properties": {}
+ }
+ }
+ },
+ {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/ConfigureFieldProp"
+ },
+ {
+ "$ref": "#/definitions/ConfigureGroupProp"
+ }
+ ]
+ }
+ ]
+ },
+ "ConfigureFieldProp": {
+ "type": "object",
+ "required": [
+ "type"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "field"
+ ]
+ },
+ "name": {
+ "type": "string"
+ },
+ "setter": {
+ "$ref": "#/definitions/ConfigureFieldSetter"
+ }
+ }
+ },
+ "ConfigureFieldSetter": {
+ "type": "object",
+ "required": [
+ "componentName"
+ ],
+ "properties": {
+ "componentName": {
+ "type": "string",
+ "enum": [
+ "List",
+ "Object",
+ "Function",
+ "Node",
+ "Mixin",
+ "Expression",
+ "Switch",
+ "Number",
+ "Input",
+ "TextArea",
+ "Date",
+ "DateYear",
+ "DateMonth",
+ "DateRange",
+ "ColorPicker",
+ "CodeEditor",
+ "Select",
+ "RadioGroup"
+ ]
+ },
+ "props": {
+ "type": "object",
+ "properties": {}
+ }
+ }
+ },
+ "ConfigureGroupProp": {
+ "type": "object",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "group"
+ ]
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/ConfigureProp"
+ }
+ }
+ }
+ },
+ "ConfigureComponent": {
+ "type": "object",
+ "properties": {
+ "isContainer": {
+ "type": "boolean"
+ },
+ "isModal": {
+ "type": "boolean"
+ },
+ "descriptor": {
+ "type": "string"
+ },
+ "nestingRule": {
+ "type": "object",
+ "properties": {
+ "childWhitelist": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "parentWhitelist": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "descendantBlacklist": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ancestorWhitelist": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "isNullNode": {
+ "type": "boolean"
+ },
+ "isLayout": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/material-parser/test/__snapshots__/dynamic.test.ts.snap b/packages/material-parser/test/__snapshots__/dynamic.test.ts.snap
new file mode 100644
index 000000000..86aa94aed
--- /dev/null
+++ b/packages/material-parser/test/__snapshots__/dynamic.test.ts.snap
@@ -0,0 +1,27 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`materialize dynamic component by online 1`] = `
+Array [
+ Object {
+ "componentName": "BizAnchor",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": false,
+ "exportName": "default",
+ "main": "lib/index.js",
+ "package": "@alifd/biz-anchor",
+ "subName": "",
+ "version": "1.1.7",
+ },
+ "props": Array [
+ Object {
+ "defaultValue": false,
+ "name": "noHash",
+ },
+ ],
+ "screenshot": "",
+ "title": "@alifd/biz-anchor",
+ },
+]
+`;
diff --git a/packages/material-parser/test/__snapshots__/index.test.ts.snap b/packages/material-parser/test/__snapshots__/index.test.ts.snap
new file mode 100644
index 000000000..561efc7f8
--- /dev/null
+++ b/packages/material-parser/test/__snapshots__/index.test.ts.snap
@@ -0,0 +1,1753 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`d.ts component by local 1`] = `
+Array [
+ Object {
+ "componentName": "default",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": false,
+ "exportName": "default",
+ "main": "src/index.jsx",
+ "package": "dts-component",
+ "subName": "",
+ "version": "1.2.3",
+ },
+ "props": Array [
+ Object {
+ "description": "是否是财鲸主站,该字段由后端 vm 中吐出在 window.appConfig 中",
+ "name": "isMainSite",
+ "propType": "bool",
+ },
+ Object {
+ "description": "财鲸主站的 app 名称,该字段由后端 vm 中吐出在 window.appConfig 中",
+ "name": "mainSiteAppName",
+ "propType": "string",
+ },
+ Object {
+ "description": "主站中文名,该字段由后端 vm 中吐出在 window.appConfig 中",
+ "name": "mainSiteName",
+ "propType": "string",
+ },
+ Object {
+ "description": "主站英文名,该字段由后端 vm 中吐出在 window.appConfig 中",
+ "name": "mainSiteNameEn",
+ "propType": "string",
+ },
+ Object {
+ "description": "主站链接,该字段由后端 vm 中吐出在 window.appConfig 中",
+ "name": "mainSiteLink",
+ "propType": "string",
+ },
+ Object {
+ "description": "子站点的应用名,该字段由后端 vm 中吐出在 window.appConfig 中",
+ "name": "subSiteAppName",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "description": "子站点的名称,该字段由后端 vm 中吐出在 window.appConfig 中",
+ "name": "subSiteName",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "description": "子站点的英文名称,该字段由后端 vm 中吐出在 window.appConfig 中",
+ "name": "subSiteNameEn",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "description": "子站点的链接,该字段由后端 vm 中吐出在 window.appConfig 中",
+ "name": "subSiteLink",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "description": "子站访问相关接口时,属于buc 跨域请求,需要把 ssoTicket 带上,该字段由后端 vm 中吐出在 window.appConfig 中",
+ "name": "ssoTicket",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "description": "是否使用 ak/sk 方案(用于登录)",
+ "name": "aksk",
+ "propType": "bool",
+ },
+ Object {
+ "description": "是否显示左侧导航",
+ "name": "sidebarVisible",
+ "propType": "bool",
+ },
+ Object {
+ "description": "是否显示顶部菜单栏",
+ "name": "topbarVisible",
+ "propType": "bool",
+ },
+ Object {
+ "description": "是否开启全屏",
+ "name": "isFullScreen",
+ "propType": "bool",
+ },
+ Object {
+ "description": "当前选中的导航 key",
+ "name": "navSelectedKeys",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ Object {
+ "type": "arrayOf",
+ "value": "string",
+ },
+ ],
+ },
+ },
+ Object {
+ "description": "history 对象",
+ "name": "history",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "object",
+ ],
+ },
+ },
+ Object {
+ "description": "左侧子导航数组",
+ "name": "nav",
+ "propType": Object {
+ "type": "arrayOf",
+ "value": "object",
+ },
+ },
+ Object {
+ "description": "Next Nav 组件本身的配置",
+ "name": "nextNavConfig",
+ "propType": "object",
+ },
+ Object {
+ "description": "切换语言的 Url",
+ "name": "setLanguageUrl",
+ "propType": "string",
+ },
+ Object {
+ "description": "顶部控件的扩展区渲染内容",
+ "name": "extra",
+ "propType": "node",
+ },
+ Object {
+ "description": "顶部导航站点名称后面的快速入口区域自定义渲染",
+ "name": "quickEntry",
+ "propType": "node",
+ },
+ Object {
+ "description": "水印配置项",
+ "name": "waterMarkOptions",
+ "propType": "object",
+ },
+ Object {
+ "description": "是否需要默认的登出行为",
+ "name": "needDefaultLogout",
+ "propType": "bool",
+ },
+ Object {
+ "description": "点击登出按钮后的回调函数",
+ "name": "onLogoutClick",
+ "propType": "func",
+ },
+ Object {
+ "description": "侧边栏收起展开回调函数",
+ "name": "onToggleMenu",
+ "propType": "func",
+ },
+ Object {
+ "description": "logo 的 style 覆盖",
+ "name": "logoStyle",
+ "propType": "object",
+ },
+ Object {
+ "description": "logo 点击事件,传入覆盖",
+ "name": "onLogoClick",
+ "propType": "func",
+ },
+ Object {
+ "description": "切换语言自定义事件",
+ "name": "onToggleLang",
+ "propType": Object {
+ "params": Array [
+ Object {
+ "name": "nextConfig",
+ "propType": "object",
+ },
+ Object {
+ "name": "appName",
+ "propType": "any",
+ },
+ ],
+ "raw": "(nextConfig: Record, appName: any) => void",
+ "type": "func",
+ },
+ },
+ Object {
+ "description": "语言切换器显示切换",
+ "name": "langVisible",
+ "propType": "bool",
+ },
+ Object {
+ "description": "打开启用浏览器缩放警告",
+ "name": "scaleWarning",
+ "propType": "bool",
+ },
+ Object {
+ "description": "This event is fired whenever the application navigates to a new page.",
+ "name": "test",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ ],
+ "screenshot": "",
+ "title": "dts-component",
+ },
+]
+`;
+
+exports[`materialize multiple exported component by local 1`] = `
+Array [
+ Object {
+ "componentName": "AIMakeBlank",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "AIMakeBlank",
+ "main": "es/index.js",
+ "package": "multiple-exported-component",
+ "subName": "",
+ "version": "1.0.0",
+ },
+ "props": Array [
+ Object {
+ "name": "styleBoxModel",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "styleLayout",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "styleBackground",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "styleFlexLayout",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "style",
+ "propType": "object",
+ },
+ Object {
+ "name": "id",
+ "propType": "string",
+ },
+ ],
+ "screenshot": "",
+ "title": "multiple-exported-component",
+ },
+ Object {
+ "componentName": "AIMakeIcon",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "AIMakeIcon",
+ "main": "es/index.js",
+ "package": "multiple-exported-component",
+ "subName": "",
+ "version": "1.0.0",
+ },
+ "props": Array [
+ Object {
+ "name": "className",
+ "propType": "string",
+ },
+ Object {
+ "name": "iconClassName",
+ "propType": "string",
+ },
+ Object {
+ "name": "styleBoxModel",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "styleText",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "styleBackground",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "style",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "multiple-exported-component",
+ },
+ Object {
+ "componentName": "AIMakeImage",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "AIMakeImage",
+ "main": "es/index.js",
+ "package": "multiple-exported-component",
+ "subName": "",
+ "version": "1.0.0",
+ },
+ "props": Array [
+ Object {
+ "name": "styleBoxModel",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "style",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "multiple-exported-component",
+ },
+ Object {
+ "componentName": "AIMakeLink",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "AIMakeLink",
+ "main": "es/index.js",
+ "package": "multiple-exported-component",
+ "subName": "",
+ "version": "1.0.0",
+ },
+ "props": Array [
+ Object {
+ "name": "styleBoxModel",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "styleText",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "styleLayout",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "styleBackground",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "style",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "multiple-exported-component",
+ },
+ Object {
+ "componentName": "AIMakePlaceholder",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "AIMakePlaceholder",
+ "main": "es/index.js",
+ "package": "multiple-exported-component",
+ "subName": "",
+ "version": "1.0.0",
+ },
+ "props": Array [
+ Object {
+ "name": "styleBoxModel",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "styleLayout",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "style",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "multiple-exported-component",
+ },
+ Object {
+ "componentName": "AIMakeText",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "AIMakeText",
+ "main": "es/index.js",
+ "package": "multiple-exported-component",
+ "subName": "",
+ "version": "1.0.0",
+ },
+ "props": Array [
+ Object {
+ "name": "type",
+ "propType": "string",
+ },
+ Object {
+ "name": "styleBoxModel",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "styleText",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "styleLayout",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "styleBackground",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "style",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "multiple-exported-component",
+ },
+ Object {
+ "componentName": "Root",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "Root",
+ "main": "es/index.js",
+ "package": "multiple-exported-component",
+ "subName": "",
+ "version": "1.0.0",
+ },
+ "props": Array [
+ Object {
+ "name": "style",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "multiple-exported-component",
+ },
+]
+`;
+
+exports[`materialize single exported component by local 1`] = `
+Array [
+ Object {
+ "componentName": "Demo",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": false,
+ "exportName": "default",
+ "main": "src/index.js",
+ "package": "single-exported-component",
+ "subName": "",
+ "version": "1.0.0",
+ },
+ "props": Array [
+ Object {
+ "name": "optionalArray",
+ "propType": "array",
+ },
+ Object {
+ "name": "optionalBool",
+ "propType": "bool",
+ },
+ Object {
+ "description": "desc",
+ "name": "optionalFunc",
+ "propType": Object {
+ "params": Array [
+ Object {
+ "description": "The title of the book.",
+ "name": "title",
+ "propType": "string",
+ },
+ Object {
+ "description": "The author of the book.",
+ "name": "author",
+ "propType": "string",
+ },
+ ],
+ "raw": "(title: string, author: string) => any",
+ "returns": Object {
+ "propType": "any",
+ },
+ "type": "func",
+ },
+ },
+ Object {
+ "defaultValue": 123,
+ "name": "optionalNumber",
+ "propType": "number",
+ },
+ Object {
+ "name": "optionalObject",
+ "propType": "object",
+ },
+ Object {
+ "name": "optionalString",
+ "propType": "string",
+ },
+ Object {
+ "name": "optionalSymbol",
+ "propType": "symbol",
+ },
+ Object {
+ "name": "optionalNode",
+ "propType": "node",
+ },
+ Object {
+ "name": "optionalElement",
+ "propType": "element",
+ },
+ Object {
+ "name": "optionalElementType",
+ "propType": "object",
+ },
+ Object {
+ "name": "optionalMessage",
+ "propType": Object {
+ "type": "instanceOf",
+ "value": "Demo",
+ },
+ },
+ Object {
+ "name": "optionalEnum",
+ "propType": Object {
+ "type": "oneOf",
+ "value": Array [
+ "News",
+ "Photos",
+ ],
+ },
+ },
+ Object {
+ "name": "optionalUnion",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "number",
+ Object {
+ "type": "instanceOf",
+ "value": "Demo",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "optionalObjectOf",
+ "propType": Object {
+ "type": "objectOf",
+ "value": "number",
+ },
+ },
+ Object {
+ "name": "optionalObjectWithShape",
+ "propType": Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "optionalProperty",
+ "propType": "string",
+ },
+ Object {
+ "name": "requiredProperty",
+ "propType": Object {
+ "isRequired": true,
+ "type": "number",
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "optionalObjectWithShape2",
+ "propType": Object {
+ "isRequired": true,
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "optionalProperty",
+ "propType": "string",
+ },
+ Object {
+ "name": "requiredProperty",
+ "propType": Object {
+ "isRequired": true,
+ "type": "number",
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "optionalObjectWithStrictShape",
+ "propType": Object {
+ "type": "exact",
+ "value": Array [
+ Object {
+ "name": "optionalProperty",
+ "propType": "string",
+ },
+ Object {
+ "name": "requiredProperty",
+ "propType": Object {
+ "isRequired": true,
+ "type": "number",
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "requiredFunc",
+ "propType": Object {
+ "isRequired": true,
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "requiredAny",
+ "propType": Object {
+ "isRequired": true,
+ "type": "any",
+ },
+ },
+ ],
+ "screenshot": "",
+ "title": "single-exported-component",
+ },
+]
+`;
+
+exports[`rax component by local 1`] = `
+Array [
+ Object {
+ "componentName": "default",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": false,
+ "exportName": "default",
+ "main": "src/index.tsx",
+ "package": "@ali/chaoshi-meta-example",
+ "subName": "",
+ "version": "1.0.0",
+ },
+ "props": Array [
+ Object {
+ "name": "a",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "ref",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ Object {
+ "params": Array [
+ Object {
+ "name": "instance",
+ "propType": "object",
+ },
+ ],
+ "raw": "(instance: unknown) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "T",
+ "propType": Object {
+ "isRequired": true,
+ "type": "any",
+ },
+ },
+ Object {
+ "name": "current",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "key",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "number",
+ ],
+ },
+ },
+ ],
+ "screenshot": "",
+ "title": "@ali/chaoshi-meta-example",
+ },
+ Object {
+ "componentName": "Price",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "Price",
+ "main": "src/index.tsx",
+ "package": "@ali/chaoshi-meta-example",
+ "subName": "",
+ "version": "1.0.0",
+ },
+ "props": Array [
+ Object {
+ "name": "color",
+ "propType": "string",
+ },
+ Object {
+ "name": "fontSize",
+ "propType": "number",
+ },
+ Object {
+ "name": "symbolSize",
+ "propType": "number",
+ },
+ Object {
+ "name": "decimalSize",
+ "propType": "number",
+ },
+ Object {
+ "name": "value",
+ "propType": "string",
+ },
+ Object {
+ "name": "autoScale",
+ "propType": "bool",
+ },
+ Object {
+ "name": "className",
+ "propType": "string",
+ },
+ Object {
+ "name": "style",
+ "propType": "object",
+ },
+ Object {
+ "name": "rest",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "@ali/chaoshi-meta-example",
+ },
+ Object {
+ "componentName": "Title",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "Title",
+ "main": "src/index.tsx",
+ "package": "@ali/chaoshi-meta-example",
+ "subName": "",
+ "version": "1.0.0",
+ },
+ "props": Array [
+ Object {
+ "name": "type",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "small",
+ "medium",
+ "large",
+ ],
+ },
+ },
+ Object {
+ "name": "doubleLine",
+ "propType": "bool",
+ },
+ Object {
+ "name": "className",
+ "propType": "string",
+ },
+ Object {
+ "name": "style",
+ "propType": "object",
+ },
+ Object {
+ "name": "rest",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "@ali/chaoshi-meta-example",
+ },
+]
+`;
+
+exports[`transpiled component by local 1`] = `
+Array [
+ Object {
+ "componentName": "MyComponent",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "\\"default\\"",
+ "main": "lib/index.js",
+ "package": "transpiled-component",
+ "subName": "",
+ "version": "1.0.0",
+ },
+ "props": Array [
+ Object {
+ "description": "Description of prop \\"foo\\".",
+ "name": "foo",
+ "propType": Object {
+ "isRequired": true,
+ "type": "number",
+ },
+ },
+ Object {
+ "defaultValue": 21,
+ "description": "Description of prop \\"bar\\" (a custom validation function).",
+ "name": "bar",
+ "propType": "object",
+ },
+ Object {
+ "name": "baz",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "number",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "optionalObjectWithShape2",
+ "propType": Object {
+ "isRequired": true,
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "optionalProperty",
+ "propType": "string",
+ },
+ Object {
+ "name": "requiredProperty",
+ "propType": Object {
+ "isRequired": true,
+ "type": "number",
+ },
+ },
+ ],
+ },
+ },
+ ],
+ "screenshot": "",
+ "title": "transpiled-component",
+ },
+]
+`;
+
+exports[`ts component 2 by local 1`] = `
+Array [
+ Object {
+ "componentName": "default",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": false,
+ "exportName": "default",
+ "main": "src/index.tsx",
+ "package": "@alife/empty",
+ "subName": "",
+ "version": "1.0.1",
+ },
+ "props": Array [
+ Object {
+ "name": "className",
+ "propType": "string",
+ },
+ Object {
+ "name": "style",
+ "propType": "object",
+ },
+ Object {
+ "name": "imageStyle",
+ "propType": "object",
+ },
+ Object {
+ "name": "image",
+ "propType": "node",
+ },
+ Object {
+ "name": "description",
+ "propType": "node",
+ },
+ Object {
+ "name": "type",
+ "propType": Object {
+ "type": "oneOf",
+ "value": Array [
+ "default",
+ "custom",
+ ],
+ },
+ },
+ ],
+ "screenshot": "",
+ "title": "@alife/empty",
+ },
+]
+`;
+
+exports[`ts component by local 1`] = `
+Array [
+ Object {
+ "componentName": "default",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": false,
+ "exportName": "default",
+ "main": "src/index.tsx",
+ "package": "ts-component",
+ "subName": "",
+ "version": "1.0.0",
+ },
+ "props": Array [
+ Object {
+ "name": "error",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "a",
+ "propType": "string",
+ },
+ ],
+ "raw": "(a: string) => number",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "void",
+ "propType": Object {
+ "isRequired": true,
+ "type": "void",
+ },
+ },
+ Object {
+ "name": "object",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "trigger",
+ "propType": Object {
+ "type": "arrayOf",
+ "value": Object {
+ "type": "oneOf",
+ "value": Array [
+ "click",
+ "hover",
+ "contextMenu",
+ ],
+ },
+ },
+ },
+ Object {
+ "name": "str",
+ "propType": "string",
+ },
+ Object {
+ "name": "num",
+ "propType": Object {
+ "isRequired": true,
+ "type": "number",
+ },
+ },
+ Object {
+ "name": "any",
+ "propType": Object {
+ "isRequired": true,
+ "type": "any",
+ },
+ },
+ Object {
+ "name": "bool",
+ "propType": Object {
+ "isRequired": true,
+ "type": "bool",
+ },
+ },
+ Object {
+ "name": "tuple",
+ "propType": Object {
+ "isRequired": true,
+ "type": "tuple",
+ "value": Array [
+ Object {
+ "isRequired": true,
+ "type": "number",
+ },
+ Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ Object {
+ "isRequired": true,
+ "type": "oneOf",
+ "value": Array [
+ true,
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "enum",
+ "propType": Object {
+ "isRequired": true,
+ "type": "oneOf",
+ "value": Array [
+ "red",
+ "yellow",
+ "green",
+ ],
+ },
+ },
+ Object {
+ "name": "arr",
+ "propType": Object {
+ "isRequired": true,
+ "type": "arrayOf",
+ "value": "number",
+ },
+ },
+ Object {
+ "name": "halfEmptyObj",
+ "propType": Object {
+ "isRequired": true,
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "fun",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "a",
+ "propType": Object {
+ "type": "arrayOf",
+ "value": "string",
+ },
+ },
+ ],
+ "raw": "(a: string[]) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "emptyObj",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "func",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "arg",
+ "propType": "string",
+ },
+ ],
+ "raw": "(arg: string) => number",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "funcs",
+ "propType": Object {
+ "isRequired": true,
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "n",
+ "propType": Object {
+ "isRequired": true,
+ "raw": "() => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "a",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "arg",
+ "propType": "string",
+ },
+ Object {
+ "name": "num",
+ "propType": "number",
+ },
+ ],
+ "raw": "(arg: string, num: number) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "fuzzy",
+ "propType": Object {
+ "isRequired": true,
+ "type": "oneOfType",
+ "value": Array [
+ "number",
+ "bool",
+ Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "a",
+ "propType": Object {
+ "isRequired": true,
+ "type": "any",
+ },
+ },
+ Object {
+ "name": "sa",
+ "propType": Object {
+ "isRequired": true,
+ "type": "arrayOf",
+ "value": "string",
+ },
+ },
+ ],
+ },
+ Object {
+ "type": "oneOf",
+ "value": Array [
+ "number",
+ "object",
+ "test",
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "oneOf",
+ "propType": Object {
+ "isRequired": true,
+ "type": "oneOfType",
+ "value": Array [
+ "bool",
+ Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "s",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "n",
+ "propType": Object {
+ "isRequired": true,
+ "type": "number",
+ },
+ },
+ ],
+ },
+ Object {
+ "type": "oneOf",
+ "value": Array [
+ "test",
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "refFunc",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "p",
+ "propType": "object",
+ },
+ ],
+ "raw": "(p: Props) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "elementOrOther",
+ "propType": Object {
+ "isRequired": true,
+ "type": "oneOfType",
+ "value": Array [
+ "element",
+ Object {
+ "params": Array [
+ Object {
+ "name": "a",
+ "propType": "string",
+ },
+ ],
+ "raw": "Func",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "obj",
+ "propType": Object {
+ "isRequired": true,
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "a",
+ "propType": Object {
+ "isRequired": true,
+ "type": "number",
+ },
+ },
+ Object {
+ "name": "arrOfStr",
+ "propType": Object {
+ "isRequired": true,
+ "type": "arrayOf",
+ "value": "string",
+ },
+ },
+ Object {
+ "name": "arrOfObj",
+ "propType": Object {
+ "isRequired": true,
+ "type": "arrayOf",
+ "value": Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "s",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "n",
+ "propType": Object {
+ "isRequired": true,
+ "type": "number",
+ },
+ },
+ ],
+ },
+ },
+ },
+ Object {
+ "name": "func",
+ "propType": Object {
+ "isRequired": true,
+ "type": "func",
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "objOf",
+ "propType": Object {
+ "isRequired": true,
+ "type": "objectOf",
+ "value": "number",
+ },
+ },
+ Object {
+ "name": "exact",
+ "propType": Object {
+ "isRequired": true,
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "a",
+ "propType": Object {
+ "isRequired": true,
+ "type": "number",
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "node",
+ "propType": "node",
+ },
+ Object {
+ "name": "element",
+ "propType": "element",
+ },
+ Object {
+ "name": "elementType",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "oneOf",
+ "value": Array [
+ "symbol",
+ "object",
+ "html",
+ "loading",
+ "a",
+ "abbr",
+ "address",
+ "area",
+ "article",
+ "aside",
+ "audio",
+ "b",
+ "base",
+ "bdi",
+ "bdo",
+ "big",
+ "blockquote",
+ "body",
+ "br",
+ "button",
+ "canvas",
+ "caption",
+ "cite",
+ "code",
+ "col",
+ "colgroup",
+ "data",
+ "datalist",
+ "dd",
+ "del",
+ "details",
+ "dfn",
+ "dialog",
+ "div",
+ "dl",
+ "dt",
+ "em",
+ "embed",
+ "fieldset",
+ "figcaption",
+ "figure",
+ "footer",
+ "form",
+ "h1",
+ "h2",
+ "h3",
+ "h4",
+ "h5",
+ "h6",
+ "head",
+ "header",
+ "hgroup",
+ "hr",
+ "i",
+ "iframe",
+ "img",
+ "input",
+ "ins",
+ "kbd",
+ "keygen",
+ "label",
+ "legend",
+ "li",
+ "link",
+ "main",
+ "map",
+ "mark",
+ "menu",
+ "menuitem",
+ "meta",
+ "meter",
+ "nav",
+ "noindex",
+ "noscript",
+ "ol",
+ "optgroup",
+ "option",
+ "output",
+ "p",
+ "param",
+ "picture",
+ "pre",
+ "progress",
+ "q",
+ "rp",
+ "rt",
+ "ruby",
+ "s",
+ "samp",
+ "script",
+ "section",
+ "select",
+ "small",
+ "source",
+ "span",
+ "strong",
+ "style",
+ "sub",
+ "summary",
+ "sup",
+ "table",
+ "tbody",
+ "td",
+ "textarea",
+ "tfoot",
+ "th",
+ "thead",
+ "time",
+ "title",
+ "tr",
+ "track",
+ "u",
+ "ul",
+ "var",
+ "video",
+ "wbr",
+ "webview",
+ "svg",
+ "animate",
+ "animateMotion",
+ "animateTransform",
+ "circle",
+ "clipPath",
+ "defs",
+ "desc",
+ "ellipse",
+ "feBlend",
+ "feColorMatrix",
+ "feComponentTransfer",
+ "feComposite",
+ "feConvolveMatrix",
+ "feDiffuseLighting",
+ "feDisplacementMap",
+ "feDistantLight",
+ "feDropShadow",
+ "feFlood",
+ "feFuncA",
+ "feFuncB",
+ "feFuncG",
+ "feFuncR",
+ "feGaussianBlur",
+ "feImage",
+ "feMerge",
+ "feMergeNode",
+ "feMorphology",
+ "feOffset",
+ "fePointLight",
+ "feSpecularLighting",
+ "feSpotLight",
+ "feTile",
+ "feTurbulence",
+ "filter",
+ "foreignObject",
+ "g",
+ "image",
+ "line",
+ "linearGradient",
+ "marker",
+ "mask",
+ "metadata",
+ "mpath",
+ "path",
+ "pattern",
+ "polygon",
+ "polyline",
+ "radialGradient",
+ "rect",
+ "stop",
+ "switch",
+ "text",
+ "textPath",
+ "tspan",
+ "use",
+ "view",
+ "list",
+ "cell",
+ "refresh",
+ "recycle-list",
+ "scroller",
+ "slider",
+ "indicator",
+ "waterfall",
+ "web",
+ "richtext",
+ "slot",
+ "swiper",
+ "swiper-item",
+ "scroll-view",
+ "cover-view",
+ "cover-image",
+ "camera",
+ "movable-view",
+ "movable-area",
+ "match-media",
+ "icon",
+ "rich-text",
+ "radio",
+ "radio-group",
+ "picker-view",
+ "picker",
+ "navigator",
+ "web-view",
+ "lifestyle",
+ "contact-button",
+ "aria-component",
+ "functional-page-navigator",
+ "live-player",
+ "live-pusher",
+ "ad",
+ "ad-custom",
+ "open-data",
+ "voip-room",
+ "page-meta",
+ "picker-view-column",
+ "official-account",
+ "navigation-bar",
+ "template",
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "union",
+ "propType": Object {
+ "isRequired": true,
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "number",
+ Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "a",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "func2",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "a",
+ "propType": "string",
+ },
+ ],
+ "raw": "Func",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "html",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ Object {
+ "name": "loading",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "bool",
+ Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "delay",
+ "propType": "number",
+ },
+ ],
+ },
+ ],
+ },
+ },
+ ],
+ "screenshot": "",
+ "title": "ts-component",
+ },
+ Object {
+ "componentName": "SubModule",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": false,
+ "exportName": "default",
+ "main": "src/index.tsx",
+ "package": "ts-component",
+ "subName": "SubModule",
+ "version": "1.0.0",
+ },
+ "props": Array [
+ Object {
+ "name": "name",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ ],
+ "screenshot": "",
+ "title": "ts-component",
+ },
+]
+`;
+
+exports[`without display name by local 1`] = `Array []`;
diff --git a/packages/material-parser/test/__snapshots__/online.test.ts.snap b/packages/material-parser/test/__snapshots__/online.test.ts.snap
new file mode 100644
index 000000000..4591246ff
--- /dev/null
+++ b/packages/material-parser/test/__snapshots__/online.test.ts.snap
@@ -0,0 +1,5780 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`materialize mc-hello by online 1`] = `
+Array [
+ Object {
+ "componentName": "default",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": false,
+ "exportName": "default",
+ "main": "lib/index.js",
+ "package": "mc-hello",
+ "subName": "",
+ "version": "1.0.1",
+ },
+ "props": Array [
+ Object {
+ "name": "color",
+ "propType": "string",
+ },
+ Object {
+ "name": "background",
+ "propType": "string",
+ },
+ Object {
+ "defaultValue": false,
+ "name": "round",
+ "propType": "bool",
+ },
+ Object {
+ "defaultValue": 200,
+ "name": "width",
+ "propType": "number",
+ },
+ Object {
+ "defaultValue": 40,
+ "name": "height",
+ "propType": "number",
+ },
+ Object {
+ "name": "children",
+ "propType": "node",
+ },
+ ],
+ "screenshot": "",
+ "title": "mc-hello",
+ },
+]
+`;
+
+exports[`materialize online rax module by path & specify workDir 1`] = `
+Array [
+ Object {
+ "componentName": "default",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": false,
+ "exportName": "default",
+ "main": "es/common/index.d.ts",
+ "package": "rax-view",
+ "subName": "",
+ "version": "2.2.1",
+ },
+ "props": Array [
+ Object {
+ "name": "ref",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ Object {
+ "params": Array [
+ Object {
+ "name": "instance",
+ "propType": "object",
+ },
+ ],
+ "raw": "(instance: HTMLDivElement) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "T",
+ "propType": Object {
+ "isRequired": true,
+ "type": "any",
+ },
+ },
+ Object {
+ "name": "current",
+ "propType": Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "key",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "style",
+ "propType": "object",
+ },
+ Object {
+ "name": "className",
+ "propType": "string",
+ },
+ ],
+ "screenshot": "",
+ "title": "rax-view",
+ },
+]
+`;
+
+exports[`materialize rc-picker by online 1`] = `
+Array [
+ Object {
+ "componentName": "PickerPanel",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "PickerPanel",
+ "main": "./lib/index",
+ "package": "rc-picker",
+ "subName": "",
+ "version": "2.4.3",
+ },
+ "props": Array [
+ Object {
+ "name": "picker",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "oneOf",
+ "value": Array [
+ "time",
+ "date",
+ "week",
+ "month",
+ "quarter",
+ "year",
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "prefixCls",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "className",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "style",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ ],
+ },
+ },
+ Object {
+ "description": "@deprecated Will be removed in next big version. Please use \`mode\` instead",
+ "name": "mode",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "oneOf",
+ "value": Array [
+ "time",
+ "date",
+ "week",
+ "month",
+ "quarter",
+ "year",
+ "decade",
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "tabIndex",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "locale",
+ "propType": Object {
+ "isRequired": true,
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "locale",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "monthBeforeYear",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "yearFormat",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "monthFormat",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "quarterFormat",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "today",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "now",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "backToToday",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "ok",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "timeSelect",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "dateSelect",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "weekSelect",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "clear",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "month",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "year",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "previousMonth",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "nextMonth",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "monthSelect",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "yearSelect",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "decadeSelect",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "dayFormat",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "dateFormat",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "dateTimeFormat",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "previousYear",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "nextYear",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "previousDecade",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "nextDecade",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "previousCentury",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "nextCentury",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "shortWeekDays",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "arrayOf",
+ "value": "string",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "shortMonths",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "arrayOf",
+ "value": "string",
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "generateConfig",
+ "propType": Object {
+ "isRequired": true,
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "DateType",
+ "propType": Object {
+ "isRequired": true,
+ "type": "any",
+ },
+ },
+ Object {
+ "name": "getWeekDay",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getSecond",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getMinute",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getHour",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getMonth",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getYear",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getNow",
+ "propType": Object {
+ "isRequired": true,
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getFixedDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "fixed",
+ "propType": "string",
+ },
+ ],
+ "raw": "(fixed: string) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getEndDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "addYear",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "diff",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, diff: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "addMonth",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "diff",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, diff: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "addDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "diff",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, diff: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setYear",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "year",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, year: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setMonth",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "month",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, month: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "date",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, date: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setHour",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "hour",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, hour: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setMinute",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "minute",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, minute: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setSecond",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "second",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, second: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "isAfter",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "date1",
+ "propType": "object",
+ },
+ Object {
+ "name": "date2",
+ "propType": "object",
+ },
+ ],
+ "raw": "(date1: DateType, date2: DateType) => boolean",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "isValidate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "date",
+ "propType": "object",
+ },
+ ],
+ "raw": "(date: DateType) => boolean",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "locale",
+ "propType": Object {
+ "isRequired": true,
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "getWeekFirstDay",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ ],
+ "raw": "(locale: string) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getWeekFirstDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(locale: string, value: DateType) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getWeek",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(locale: string, value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "format",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ Object {
+ "name": "date",
+ "propType": "object",
+ },
+ Object {
+ "name": "format",
+ "propType": "string",
+ },
+ ],
+ "raw": "(locale: string, date: DateType, format: string) => string",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "parse",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ Object {
+ "name": "text",
+ "propType": "string",
+ },
+ Object {
+ "name": "formats",
+ "propType": Object {
+ "type": "arrayOf",
+ "value": "string",
+ },
+ },
+ ],
+ "raw": "(locale: string, text: string, formats: string[]) => DateType | null",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getShortWeekDays",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ ],
+ "raw": "(locale: string) => string[]",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "getShortMonths",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ ],
+ "raw": "(locale: string) => string[]",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "value",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "null",
+ ],
+ },
+ },
+ Object {
+ "name": "defaultValue",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ ],
+ },
+ },
+ Object {
+ "description": "[Legacy] Set default display picker view date",
+ "name": "pickerValue",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ ],
+ },
+ },
+ Object {
+ "description": "[Legacy] Set default display picker view date",
+ "name": "defaultPickerValue",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ ],
+ },
+ },
+ Object {
+ "name": "disabledDate",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "dateRender",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "monthCellRender",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "renderExtraFooter",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "mode",
+ "propType": Object {
+ "type": "oneOf",
+ "value": Array [
+ "time",
+ "date",
+ "week",
+ "month",
+ "quarter",
+ "year",
+ "decade",
+ ],
+ },
+ },
+ ],
+ "raw": "(mode: PanelMode) => ReactNode",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onSelect",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "onChange",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "onPanelChange",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "onMouseDown",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: MouseEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onOk",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "direction",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "oneOf",
+ "value": Array [
+ "ltr",
+ "rtl",
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "description": "@private This is internal usage. Do not use in your production env",
+ "name": "hideHeader",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "description": "@private This is internal usage. Do not use in your production env",
+ "name": "onPickerValueChange",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "description": "@private Internal usage. Do not use in your production env",
+ "name": "components",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "button",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "rangeItem",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "showToday",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showNow",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showTime",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "DateType",
+ "propType": Object {
+ "isRequired": true,
+ "type": "any",
+ },
+ },
+ Object {
+ "name": "format",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "showNow",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showHour",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showMinute",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showSecond",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "use12Hours",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "hourStep",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "minuteStep",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "secondStep",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "hideDisabledOptions",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "defaultValue",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ ],
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "disabledTime",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "format",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "showHour",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showMinute",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showSecond",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "use12Hours",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "hourStep",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "minuteStep",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "secondStep",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "hideDisabledOptions",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "disabledHours",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "disabledMinutes",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "hour",
+ "propType": "number",
+ },
+ ],
+ "raw": "(hour: number) => number[]",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "disabledSeconds",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "hour",
+ "propType": "number",
+ },
+ Object {
+ "name": "minute",
+ "propType": "number",
+ },
+ ],
+ "raw": "(hour: number, minute: number) => number[]",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ ],
+ "screenshot": "",
+ "title": "rc-picker",
+ },
+ Object {
+ "componentName": "RangePicker",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "RangePicker",
+ "main": "./lib/index",
+ "package": "rc-picker",
+ "subName": "",
+ "version": "2.4.3",
+ },
+ "props": Array [
+ Object {
+ "name": "id",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "value",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "null",
+ Object {
+ "type": "tuple",
+ "value": Array [
+ Object {
+ "isRequired": true,
+ "type": "oneOfType",
+ "value": Array [
+ "null",
+ "object",
+ ],
+ },
+ Object {
+ "isRequired": true,
+ "type": "oneOfType",
+ "value": Array [
+ "null",
+ "object",
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "defaultValue",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "null",
+ Object {
+ "type": "tuple",
+ "value": Array [
+ Object {
+ "isRequired": true,
+ "type": "oneOfType",
+ "value": Array [
+ "null",
+ "object",
+ ],
+ },
+ Object {
+ "isRequired": true,
+ "type": "oneOfType",
+ "value": Array [
+ "null",
+ "object",
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "defaultPickerValue",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "tuple",
+ "value": Array [
+ Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ Object {
+ "isRequired": true,
+ "type": "object",
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "placeholder",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "tuple",
+ "value": Array [
+ Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "disabled",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ Object {
+ "type": "tuple",
+ "value": Array [
+ Object {
+ "isRequired": true,
+ "type": "bool",
+ },
+ Object {
+ "isRequired": true,
+ "type": "bool",
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "disabledTime",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "ranges",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "objectOf",
+ "value": "oneOfType",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "separator",
+ "propType": "node",
+ },
+ Object {
+ "name": "allowEmpty",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "tuple",
+ "value": Array [
+ Object {
+ "isRequired": true,
+ "type": "bool",
+ },
+ Object {
+ "isRequired": true,
+ "type": "bool",
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "mode",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "tuple",
+ "value": Array [
+ Object {
+ "isRequired": true,
+ "type": "oneOf",
+ "value": Array [
+ "time",
+ "date",
+ "week",
+ "month",
+ "quarter",
+ "year",
+ "decade",
+ ],
+ },
+ Object {
+ "isRequired": true,
+ "type": "oneOf",
+ "value": Array [
+ "time",
+ "date",
+ "week",
+ "month",
+ "quarter",
+ "year",
+ "decade",
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onChange",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "onCalendarChange",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "onPanelChange",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "onFocus",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: FocusEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onBlur",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: FocusEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onOk",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "direction",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "oneOf",
+ "value": Array [
+ "ltr",
+ "rtl",
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "autoComplete",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "description": "@private Internal control of active picker. Do not use since it's private usage",
+ "name": "activePickerIndex",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "oneOf",
+ "value": Array [
+ 0,
+ 1,
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "dateRender",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "panelRender",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "originPanel",
+ "propType": "node",
+ },
+ ],
+ "raw": "(originPanel: ReactNode) => ReactNode",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "picker",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "oneOf",
+ "value": Array [
+ "time",
+ "date",
+ "week",
+ "month",
+ "quarter",
+ "year",
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "prefixCls",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "className",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "style",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ ],
+ },
+ },
+ Object {
+ "name": "tabIndex",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "locale",
+ "propType": Object {
+ "isRequired": true,
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "locale",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "monthBeforeYear",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "yearFormat",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "monthFormat",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "quarterFormat",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "today",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "now",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "backToToday",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "ok",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "timeSelect",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "dateSelect",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "weekSelect",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "clear",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "month",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "year",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "previousMonth",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "nextMonth",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "monthSelect",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "yearSelect",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "decadeSelect",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "dayFormat",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "dateFormat",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "dateTimeFormat",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "previousYear",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "nextYear",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "previousDecade",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "nextDecade",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "previousCentury",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "nextCentury",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "shortWeekDays",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "arrayOf",
+ "value": "string",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "shortMonths",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "arrayOf",
+ "value": "string",
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "generateConfig",
+ "propType": Object {
+ "isRequired": true,
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "DateType",
+ "propType": Object {
+ "isRequired": true,
+ "type": "any",
+ },
+ },
+ Object {
+ "name": "getWeekDay",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getSecond",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getMinute",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getHour",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getMonth",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getYear",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getNow",
+ "propType": Object {
+ "isRequired": true,
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getFixedDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "fixed",
+ "propType": "string",
+ },
+ ],
+ "raw": "(fixed: string) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getEndDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "addYear",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "diff",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, diff: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "addMonth",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "diff",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, diff: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "addDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "diff",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, diff: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setYear",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "year",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, year: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setMonth",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "month",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, month: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "date",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, date: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setHour",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "hour",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, hour: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setMinute",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "minute",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, minute: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setSecond",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "second",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, second: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "isAfter",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "date1",
+ "propType": "object",
+ },
+ Object {
+ "name": "date2",
+ "propType": "object",
+ },
+ ],
+ "raw": "(date1: DateType, date2: DateType) => boolean",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "isValidate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "date",
+ "propType": "object",
+ },
+ ],
+ "raw": "(date: DateType) => boolean",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "locale",
+ "propType": Object {
+ "isRequired": true,
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "getWeekFirstDay",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ ],
+ "raw": "(locale: string) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getWeekFirstDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(locale: string, value: DateType) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getWeek",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(locale: string, value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "format",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ Object {
+ "name": "date",
+ "propType": "object",
+ },
+ Object {
+ "name": "format",
+ "propType": "string",
+ },
+ ],
+ "raw": "(locale: string, date: DateType, format: string) => string",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "parse",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ Object {
+ "name": "text",
+ "propType": "string",
+ },
+ Object {
+ "name": "formats",
+ "propType": Object {
+ "type": "arrayOf",
+ "value": "string",
+ },
+ },
+ ],
+ "raw": "(locale: string, text: string, formats: string[]) => DateType | null",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getShortWeekDays",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ ],
+ "raw": "(locale: string) => string[]",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "getShortMonths",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ ],
+ "raw": "(locale: string) => string[]",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "disabledDate",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "monthCellRender",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "renderExtraFooter",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "mode",
+ "propType": Object {
+ "type": "oneOf",
+ "value": Array [
+ "time",
+ "date",
+ "week",
+ "month",
+ "quarter",
+ "year",
+ "decade",
+ ],
+ },
+ },
+ ],
+ "raw": "(mode: PanelMode) => ReactNode",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onMouseDown",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: MouseEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "description": "@private Internal usage. Do not use in your production env",
+ "name": "components",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "button",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "rangeItem",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "dropdownClassName",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "dropdownAlign",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "points",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "arrayOf",
+ "value": "string",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "offset",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "arrayOf",
+ "value": "number",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "targetOffset",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "arrayOf",
+ "value": "number",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "overflow",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "adjustX",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "adjustY",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ "bool",
+ ],
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "useCssRight",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "useCssBottom",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "useCssTransform",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "ignoreShake",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "popupStyle",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ ],
+ },
+ },
+ Object {
+ "name": "transitionName",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "allowClear",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "autoFocus",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "open",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "defaultOpen",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "description": "Make input readOnly to avoid popup keyboard in mobile",
+ "name": "inputReadOnly",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "format",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ "func",
+ Object {
+ "type": "arrayOf",
+ "value": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "func",
+ ],
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "suffixIcon",
+ "propType": "node",
+ },
+ Object {
+ "name": "clearIcon",
+ "propType": "node",
+ },
+ Object {
+ "name": "prevIcon",
+ "propType": "node",
+ },
+ Object {
+ "name": "nextIcon",
+ "propType": "node",
+ },
+ Object {
+ "name": "superPrevIcon",
+ "propType": "node",
+ },
+ Object {
+ "name": "superNextIcon",
+ "propType": "node",
+ },
+ Object {
+ "name": "getPopupContainer",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "node",
+ "propType": "object",
+ },
+ ],
+ "raw": "(node: HTMLElement) => HTMLElement",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onOpenChange",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "open",
+ "propType": "bool",
+ },
+ ],
+ "raw": "(open: boolean) => void",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onMouseUp",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: MouseEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onMouseEnter",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: MouseEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onMouseLeave",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: MouseEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onClick",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: MouseEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onContextMenu",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: MouseEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "description": "@private Internal usage, do not use in production mode!!!",
+ "name": "pickerRef",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ ],
+ },
+ },
+ Object {
+ "name": "role",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "name",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "showTime",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showNow",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "order",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showHour",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showMinute",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showSecond",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "use12Hours",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "hourStep",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "minuteStep",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "secondStep",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "hideDisabledOptions",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "disabledHours",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "disabledMinutes",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "hour",
+ "propType": "number",
+ },
+ ],
+ "raw": "(hour: number) => number[]",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "disabledSeconds",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "hour",
+ "propType": "number",
+ },
+ Object {
+ "name": "minute",
+ "propType": "number",
+ },
+ ],
+ "raw": "(hour: number, minute: number) => number[]",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "description": "@deprecated Please use \`defaultValue\` directly instead",
+ "name": "defaultOpenValue",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ ],
+ },
+ },
+ ],
+ "screenshot": "",
+ "title": "rc-picker",
+ },
+ Object {
+ "componentName": "default",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": false,
+ "exportName": "default",
+ "main": "./lib/index",
+ "package": "rc-picker",
+ "subName": "",
+ "version": "2.4.3",
+ },
+ "props": Array [
+ Object {
+ "name": "dropdownClassName",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "dropdownAlign",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "points",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "arrayOf",
+ "value": "string",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "offset",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "arrayOf",
+ "value": "number",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "targetOffset",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "arrayOf",
+ "value": "number",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "overflow",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "adjustX",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "adjustY",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ "bool",
+ ],
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "useCssRight",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "useCssBottom",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "useCssTransform",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "ignoreShake",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "popupStyle",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ ],
+ },
+ },
+ Object {
+ "name": "transitionName",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "placeholder",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "allowClear",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "autoFocus",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "disabled",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "tabIndex",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "open",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "defaultOpen",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "description": "Make input readOnly to avoid popup keyboard in mobile",
+ "name": "inputReadOnly",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "id",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "format",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ "func",
+ Object {
+ "type": "arrayOf",
+ "value": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "func",
+ ],
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "suffixIcon",
+ "propType": "node",
+ },
+ Object {
+ "name": "clearIcon",
+ "propType": "node",
+ },
+ Object {
+ "name": "prevIcon",
+ "propType": "node",
+ },
+ Object {
+ "name": "nextIcon",
+ "propType": "node",
+ },
+ Object {
+ "name": "superPrevIcon",
+ "propType": "node",
+ },
+ Object {
+ "name": "superNextIcon",
+ "propType": "node",
+ },
+ Object {
+ "name": "getPopupContainer",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "node",
+ "propType": "object",
+ },
+ ],
+ "raw": "(node: HTMLElement) => HTMLElement",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "panelRender",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "originPanel",
+ "propType": "node",
+ },
+ ],
+ "raw": "(originPanel: ReactNode) => ReactNode",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onChange",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "onOpenChange",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "open",
+ "propType": "bool",
+ },
+ ],
+ "raw": "(open: boolean) => void",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onFocus",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: FocusEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onBlur",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: FocusEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onMouseDown",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: MouseEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onMouseUp",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: MouseEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onMouseEnter",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: MouseEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onMouseLeave",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: MouseEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onClick",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: MouseEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onContextMenu",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "event",
+ "propType": "object",
+ },
+ ],
+ "raw": "(event: MouseEvent) => void",
+ "returns": Object {
+ "propType": "number",
+ },
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "description": "@private Internal usage, do not use in production mode!!!",
+ "name": "pickerRef",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ ],
+ },
+ },
+ Object {
+ "name": "role",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "name",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "autoComplete",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "direction",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "oneOf",
+ "value": Array [
+ "ltr",
+ "rtl",
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "value",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "null",
+ ],
+ },
+ },
+ Object {
+ "name": "defaultValue",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ ],
+ },
+ },
+ Object {
+ "description": "[Legacy] Set default display picker view date",
+ "name": "defaultPickerValue",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ ],
+ },
+ },
+ Object {
+ "description": "@deprecated Will be removed in next big version. Please use \`mode\` instead",
+ "name": "mode",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "oneOf",
+ "value": Array [
+ "time",
+ "date",
+ "week",
+ "month",
+ "quarter",
+ "year",
+ "decade",
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "onSelect",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "onPanelChange",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "onOk",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "dateRender",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "picker",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "oneOf",
+ "value": Array [
+ "time",
+ "date",
+ "week",
+ "month",
+ "quarter",
+ "year",
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "prefixCls",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "className",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "style",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ ],
+ },
+ },
+ Object {
+ "name": "locale",
+ "propType": Object {
+ "isRequired": true,
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "locale",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "monthBeforeYear",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "yearFormat",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "monthFormat",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "quarterFormat",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "today",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "now",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "backToToday",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "ok",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "timeSelect",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "dateSelect",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "weekSelect",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "clear",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "month",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "year",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "previousMonth",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "nextMonth",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "monthSelect",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "yearSelect",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "decadeSelect",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "dayFormat",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "dateFormat",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "dateTimeFormat",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "previousYear",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "nextYear",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "previousDecade",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "nextDecade",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "previousCentury",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "nextCentury",
+ "propType": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ },
+ Object {
+ "name": "shortWeekDays",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "arrayOf",
+ "value": "string",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "shortMonths",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "arrayOf",
+ "value": "string",
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "generateConfig",
+ "propType": Object {
+ "isRequired": true,
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "DateType",
+ "propType": Object {
+ "isRequired": true,
+ "type": "any",
+ },
+ },
+ Object {
+ "name": "getWeekDay",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getSecond",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getMinute",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getHour",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getMonth",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getYear",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getNow",
+ "propType": Object {
+ "isRequired": true,
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getFixedDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "fixed",
+ "propType": "string",
+ },
+ ],
+ "raw": "(fixed: string) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getEndDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(value: DateType) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "addYear",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "diff",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, diff: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "addMonth",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "diff",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, diff: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "addDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "diff",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, diff: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setYear",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "year",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, year: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setMonth",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "month",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, month: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "date",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, date: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setHour",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "hour",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, hour: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setMinute",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "minute",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, minute: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "setSecond",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ Object {
+ "name": "second",
+ "propType": "number",
+ },
+ ],
+ "raw": "(value: DateType, second: number) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "isAfter",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "date1",
+ "propType": "object",
+ },
+ Object {
+ "name": "date2",
+ "propType": "object",
+ },
+ ],
+ "raw": "(date1: DateType, date2: DateType) => boolean",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "isValidate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "date",
+ "propType": "object",
+ },
+ ],
+ "raw": "(date: DateType) => boolean",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "locale",
+ "propType": Object {
+ "isRequired": true,
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "getWeekFirstDay",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ ],
+ "raw": "(locale: string) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getWeekFirstDate",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(locale: string, value: DateType) => DateType",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getWeek",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ Object {
+ "name": "value",
+ "propType": "object",
+ },
+ ],
+ "raw": "(locale: string, value: DateType) => number",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "format",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ Object {
+ "name": "date",
+ "propType": "object",
+ },
+ Object {
+ "name": "format",
+ "propType": "string",
+ },
+ ],
+ "raw": "(locale: string, date: DateType, format: string) => string",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "parse",
+ "propType": Object {
+ "isRequired": true,
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ Object {
+ "name": "text",
+ "propType": "string",
+ },
+ Object {
+ "name": "formats",
+ "propType": Object {
+ "type": "arrayOf",
+ "value": "string",
+ },
+ },
+ ],
+ "raw": "(locale: string, text: string, formats: string[]) => DateType | null",
+ "type": "func",
+ },
+ },
+ Object {
+ "name": "getShortWeekDays",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ ],
+ "raw": "(locale: string) => string[]",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "getShortMonths",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "locale",
+ "propType": "string",
+ },
+ ],
+ "raw": "(locale: string) => string[]",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "disabledDate",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "monthCellRender",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "renderExtraFooter",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "mode",
+ "propType": Object {
+ "type": "oneOf",
+ "value": Array [
+ "time",
+ "date",
+ "week",
+ "month",
+ "quarter",
+ "year",
+ "decade",
+ ],
+ },
+ },
+ ],
+ "raw": "(mode: PanelMode) => ReactNode",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "description": "@private Internal usage. Do not use in your production env",
+ "name": "components",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "button",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "rangeItem",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "disabledTime",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "showToday",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showTime",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ Object {
+ "type": "shape",
+ "value": Array [
+ Object {
+ "name": "DateType",
+ "propType": Object {
+ "isRequired": true,
+ "type": "any",
+ },
+ },
+ Object {
+ "name": "format",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "string",
+ ],
+ },
+ },
+ Object {
+ "name": "showNow",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showHour",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showMinute",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showSecond",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "use12Hours",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "hourStep",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "minuteStep",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "secondStep",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "hideDisabledOptions",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "defaultValue",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ ],
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "showNow",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "description": "@deprecated Please use \`defaultValue\` directly instead",
+ "name": "defaultOpenValue",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ ],
+ },
+ },
+ Object {
+ "name": "showHour",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showMinute",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "showSecond",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "use12Hours",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "hourStep",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "minuteStep",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "secondStep",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "hideDisabledOptions",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "bool",
+ ],
+ },
+ },
+ Object {
+ "name": "disabledHours",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ "func",
+ ],
+ },
+ },
+ Object {
+ "name": "disabledMinutes",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "hour",
+ "propType": "number",
+ },
+ ],
+ "raw": "(hour: number) => number[]",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ Object {
+ "name": "disabledSeconds",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "object",
+ Object {
+ "params": Array [
+ Object {
+ "name": "hour",
+ "propType": "number",
+ },
+ Object {
+ "name": "minute",
+ "propType": "number",
+ },
+ ],
+ "raw": "(hour: number, minute: number) => number[]",
+ "type": "func",
+ },
+ ],
+ },
+ },
+ ],
+ "screenshot": "",
+ "title": "rc-picker",
+ },
+]
+`;
+
+exports[`materialize react-color by online 1`] = `
+Array [
+ Object {
+ "componentName": "BlockPicker",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "BlockPicker",
+ "main": "lib/index.js",
+ "package": "react-color",
+ "subName": "",
+ "version": "2.19.3",
+ },
+ "props": Array [
+ Object {
+ "defaultValue": 170,
+ "name": "width",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "triangle",
+ "propType": Object {
+ "type": "oneOf",
+ "value": Array [
+ "top",
+ "hide",
+ ],
+ },
+ },
+ Object {
+ "defaultValue": Object {},
+ "name": "styles",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "react-color",
+ },
+ Object {
+ "componentName": "CirclePicker",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "CirclePicker",
+ "main": "lib/index.js",
+ "package": "react-color",
+ "subName": "",
+ "version": "2.19.3",
+ },
+ "props": Array [
+ Object {
+ "defaultValue": 252,
+ "name": "width",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "defaultValue": 28,
+ "name": "circleSize",
+ "propType": "number",
+ },
+ Object {
+ "defaultValue": 14,
+ "name": "circleSpacing",
+ "propType": "number",
+ },
+ Object {
+ "defaultValue": Object {},
+ "name": "styles",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "react-color",
+ },
+ Object {
+ "componentName": "default",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": false,
+ "exportName": "default",
+ "main": "lib/index.js",
+ "package": "react-color",
+ "subName": "",
+ "version": "2.19.3",
+ },
+ "props": Array [
+ Object {
+ "defaultValue": 225,
+ "name": "width",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "defaultValue": false,
+ "name": "disableAlpha",
+ "propType": "bool",
+ },
+ Object {
+ "defaultValue": Object {},
+ "name": "styles",
+ "propType": "object",
+ },
+ Object {
+ "name": "defaultView",
+ "propType": Object {
+ "type": "oneOf",
+ "value": Array [
+ "hex",
+ "rgb",
+ "hsl",
+ ],
+ },
+ },
+ ],
+ "screenshot": "",
+ "title": "react-color",
+ },
+ Object {
+ "componentName": "ChromePicker",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "ChromePicker",
+ "main": "lib/index.js",
+ "package": "react-color",
+ "subName": "",
+ "version": "2.19.3",
+ },
+ "props": Array [
+ Object {
+ "defaultValue": 225,
+ "name": "width",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "defaultValue": false,
+ "name": "disableAlpha",
+ "propType": "bool",
+ },
+ Object {
+ "defaultValue": Object {},
+ "name": "styles",
+ "propType": "object",
+ },
+ Object {
+ "name": "defaultView",
+ "propType": Object {
+ "type": "oneOf",
+ "value": Array [
+ "hex",
+ "rgb",
+ "hsl",
+ ],
+ },
+ },
+ ],
+ "screenshot": "",
+ "title": "react-color",
+ },
+ Object {
+ "componentName": "CompactPicker",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "CompactPicker",
+ "main": "lib/index.js",
+ "package": "react-color",
+ "subName": "",
+ "version": "2.19.3",
+ },
+ "props": Array [
+ Object {
+ "defaultValue": Object {},
+ "name": "styles",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "react-color",
+ },
+ Object {
+ "componentName": "GithubPicker",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "GithubPicker",
+ "main": "lib/index.js",
+ "package": "react-color",
+ "subName": "",
+ "version": "2.19.3",
+ },
+ "props": Array [
+ Object {
+ "defaultValue": 200,
+ "name": "width",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "triangle",
+ "propType": Object {
+ "type": "oneOf",
+ "value": Array [
+ "hide",
+ "top-left",
+ "top-right",
+ "bottom-left",
+ "bottom-right",
+ ],
+ },
+ },
+ Object {
+ "defaultValue": Object {},
+ "name": "styles",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "react-color",
+ },
+ Object {
+ "componentName": "HuePicker",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "HuePicker",
+ "main": "lib/index.js",
+ "package": "react-color",
+ "subName": "",
+ "version": "2.19.3",
+ },
+ "props": Array [
+ Object {
+ "defaultValue": Object {},
+ "name": "styles",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "react-color",
+ },
+ Object {
+ "componentName": "PhotoshopPicker",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "PhotoshopPicker",
+ "main": "lib/index.js",
+ "package": "react-color",
+ "subName": "",
+ "version": "2.19.3",
+ },
+ "props": Array [
+ Object {
+ "name": "header",
+ "propType": "string",
+ },
+ Object {
+ "defaultValue": Object {},
+ "name": "styles",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "react-color",
+ },
+ Object {
+ "componentName": "SketchPicker",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "SketchPicker",
+ "main": "lib/index.js",
+ "package": "react-color",
+ "subName": "",
+ "version": "2.19.3",
+ },
+ "props": Array [
+ Object {
+ "defaultValue": false,
+ "name": "disableAlpha",
+ "propType": "bool",
+ },
+ Object {
+ "defaultValue": 200,
+ "name": "width",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "defaultValue": Object {},
+ "name": "styles",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "react-color",
+ },
+ Object {
+ "componentName": "SliderPicker",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "SliderPicker",
+ "main": "lib/index.js",
+ "package": "react-color",
+ "subName": "",
+ "version": "2.19.3",
+ },
+ "props": Array [
+ Object {
+ "defaultValue": Object {},
+ "name": "styles",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "react-color",
+ },
+ Object {
+ "componentName": "SwatchesPicker",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "SwatchesPicker",
+ "main": "lib/index.js",
+ "package": "react-color",
+ "subName": "",
+ "version": "2.19.3",
+ },
+ "props": Array [
+ Object {
+ "defaultValue": 320,
+ "name": "width",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "defaultValue": 240,
+ "name": "height",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "defaultValue": Object {},
+ "name": "styles",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "react-color",
+ },
+ Object {
+ "componentName": "TwitterPicker",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "TwitterPicker",
+ "main": "lib/index.js",
+ "package": "react-color",
+ "subName": "",
+ "version": "2.19.3",
+ },
+ "props": Array [
+ Object {
+ "defaultValue": 276,
+ "name": "width",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "name": "triangle",
+ "propType": Object {
+ "type": "oneOf",
+ "value": Array [
+ "hide",
+ "top-left",
+ "top-right",
+ ],
+ },
+ },
+ Object {
+ "defaultValue": Object {},
+ "name": "styles",
+ "propType": "object",
+ },
+ ],
+ "screenshot": "",
+ "title": "react-color",
+ },
+ Object {
+ "componentName": "GooglePicker",
+ "devMode": "proCode",
+ "docUrl": "",
+ "npm": Object {
+ "destructuring": true,
+ "exportName": "GooglePicker",
+ "main": "lib/index.js",
+ "package": "react-color",
+ "subName": "",
+ "version": "2.19.3",
+ },
+ "props": Array [
+ Object {
+ "defaultValue": 652,
+ "name": "width",
+ "propType": Object {
+ "type": "oneOfType",
+ "value": Array [
+ "string",
+ "number",
+ ],
+ },
+ },
+ Object {
+ "defaultValue": Object {},
+ "name": "styles",
+ "propType": "object",
+ },
+ Object {
+ "name": "header",
+ "propType": "string",
+ },
+ ],
+ "screenshot": "",
+ "title": "react-color",
+ },
+]
+`;
diff --git a/packages/material-parser/test/dynamic.test.ts b/packages/material-parser/test/dynamic.test.ts
new file mode 100644
index 000000000..f2731f0c9
--- /dev/null
+++ b/packages/material-parser/test/dynamic.test.ts
@@ -0,0 +1,14 @@
+import parse from '../src';
+import { IMaterializeOptions } from '../src/types';
+
+const dynamicComponent = '@alifd/biz-anchor@1.1.7';
+
+test('materialize dynamic component by online', async () => {
+ const options: IMaterializeOptions = {
+ entry: dynamicComponent,
+ accesser: 'online',
+ };
+
+ const actual = await parse(options);
+ expect(actual).toMatchSnapshot();
+});
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/dts-component/index.d.ts b/packages/material-parser/test/fixtures/dts-component/index.d.ts
new file mode 100644
index 000000000..a9e95203f
--- /dev/null
+++ b/packages/material-parser/test/fixtures/dts-component/index.d.ts
@@ -0,0 +1,168 @@
+import * as React from 'react';
+
+/**
+ * 财鲸Layout属性配置
+ */
+export interface WhaleLayoutProps {
+ /**
+ * 是否是财鲸主站,该字段由后端 vm 中吐出在 window.appConfig 中
+ * @defaultValue false
+ */
+ isMainSite?: boolean;
+ /**
+ * 财鲸主站的 app 名称,该字段由后端 vm 中吐出在 window.appConfig 中
+ * @defaultValue 'caijing'
+ */
+ mainSiteAppName?: string;
+ /**
+ * 主站中文名,该字段由后端 vm 中吐出在 window.appConfig 中
+ * @defaultValue '财鲸'
+ */
+ mainSiteName?: string;
+ /**
+ * 主站英文名,该字段由后端 vm 中吐出在 window.appConfig 中
+ * @defaultValue 'Caijing'
+ */
+ mainSiteNameEn?: string;
+ /**
+ * 主站链接,该字段由后端 vm 中吐出在 window.appConfig 中
+ * @defaultValue '//caijing.alibaba-inc.com'
+ */
+ mainSiteLink?: string;
+ /**
+ * 子站点的应用名,该字段由后端 vm 中吐出在 window.appConfig 中
+ */
+ subSiteAppName: string;
+ /**
+ * 子站点的名称,该字段由后端 vm 中吐出在 window.appConfig 中
+ */
+ subSiteName: string;
+ /**
+ * 子站点的英文名称,该字段由后端 vm 中吐出在 window.appConfig 中
+ */
+ subSiteNameEn: string;
+ /**
+ * 子站点的链接,该字段由后端 vm 中吐出在 window.appConfig 中
+ */
+ subSiteLink: string;
+ /**
+ * 子站访问相关接口时,属于buc 跨域请求,需要把 ssoTicket 带上,该字段由后端 vm 中吐出在 window.appConfig 中
+ */
+ ssoTicket: string;
+ /**
+ * 是否使用 ak/sk 方案(用于登录)
+ * @defaultValue false
+ */
+ aksk?: boolean;
+ /**
+ * 是否显示左侧导航
+ * @defaultValue true
+ */
+ sidebarVisible?: boolean;
+ /**
+ * 是否显示顶部菜单栏
+ * @defaultValue true
+ */
+ topbarVisible?: boolean;
+ /**
+ * 是否开启全屏
+ * @defaultValue false
+ */
+ isFullScreen?: boolean;
+ /**
+ * 当前选中的导航 key
+ * @defaultValue 'home'
+ */
+ navSelectedKeys?: string | string[];
+ /**
+ * history 对象
+ * @defaultValue {}
+ */
+ history?: string | {};
+ /**
+ * 左侧子导航数组
+ * 参考:https://whale.fusion.alibaba-inc.com/73015/component/basic/nav#demo-api
+ * @defaultValue []
+ */
+ nav?: Array<{}>;
+ /**
+ * Next Nav 组件本身的配置
+ * @defaultValue {}
+ */
+ nextNavConfig?: {};
+ /**
+ * 切换语言的 Url
+ * @defaultValue null
+ */
+ setLanguageUrl?: string;
+ /**
+ * 顶部控件的扩展区渲染内容
+ * @defaultValue null
+ */
+ extra?: React.ReactNode;
+ /**
+ * 顶部导航站点名称后面的快速入口区域自定义渲染
+ * @defaultValue null
+ */
+ quickEntry?: React.ReactNode;
+ /**
+ * 水印配置项
+ * 配置文档参考:{@link https://npm.alibaba-inc.com/package/@alife/waterMark}
+ * @defaultValue null
+ */
+ waterMarkOptions?: {};
+ /**
+ * 是否需要默认的登出行为
+ * @defaultValue true
+ */
+ needDefaultLogout?: boolean;
+ /**
+ * 点击登出按钮后的回调函数
+ * @defaultValue null
+ */
+ onLogoutClick?: () => void;
+ /**
+ * 侧边栏收起展开回调函数
+ * @defaultValue null
+ */
+ onToggleMenu?: () => void;
+ /**
+ * logo 的 style 覆盖
+ * @defaultValue null
+ */
+ logoStyle?: React.CSSProperties;
+ /**
+ * logo 点击事件,传入覆盖
+ * @defaultValue null
+ */
+ onLogoClick?: () => void;
+ /**
+ * 切换语言自定义事件
+ *
+ */
+ onToggleLang?: (nextConfig: Record, appName: any) => void;
+ /**
+ * 语言切换器显示切换
+ * @defaultValueValue true
+ */
+ langVisible?: boolean;
+ /**
+ * 打开启用浏览器缩放警告
+ * @defaultValue `true`
+ */
+ scaleWarning?: boolean;
+ /**
+ * This event is fired whenever the application navigates to a new page.
+ * @eventProperty
+ */
+ test: string;
+}
+
+/**
+ * 财鲸Layout owner: 昔夜
+ *
+ * 查看组件文档: https://whale.fusion.alibaba-inc.com/73015/component/bizcomps/692
+ */
+declare class WhaleLayout extends React.Component { }
+
+export default WhaleLayout;
diff --git a/packages/material-parser/test/fixtures/dts-component/package.json b/packages/material-parser/test/fixtures/dts-component/package.json
new file mode 100644
index 000000000..09eb1bbc8
--- /dev/null
+++ b/packages/material-parser/test/fixtures/dts-component/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "dts-component",
+ "version": "1.2.3",
+ "main": "./src/index.jsx"
+}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/dts-component/src/data.js b/packages/material-parser/test/fixtures/dts-component/src/data.js
new file mode 100644
index 000000000..aeee9f466
--- /dev/null
+++ b/packages/material-parser/test/fixtures/dts-component/src/data.js
@@ -0,0 +1,1264 @@
+export default [
+ {
+ countryKey: 'CN',
+ value: '+86',
+ countryName_zh: '中国',
+ countryName: 'China',
+ flag: 'C',
+ },
+ {
+ countryKey: 'US',
+ value: '+1',
+ countryName_zh: '美国',
+ countryName: 'United States',
+ flag: 'U',
+ }, {
+ countryKey: 'JP',
+ value: '+81',
+ countryName_zh: '日本',
+ countryName: 'Japan',
+ flag: 'J',
+ }, {
+ countryKey: 'TW',
+ value: '+886',
+ countryName_zh: '中国台湾',
+ countryName: 'Taiwan',
+ flag: 'T',
+ }, {
+ countryKey: 'HK',
+ value: '+852',
+ countryName_zh: '中国香港',
+ countryName: 'Hong Kong',
+ flag: 'H',
+ }, {
+ countryKey: 'IN',
+ value: '+91',
+ countryName_zh: '印度',
+ countryName: 'India',
+ flag: 'I',
+ }, {
+ countryKey: 'AF',
+ value: '+93',
+ countryName_zh: '阿富汗',
+ countryName: 'Afghanistan',
+ flag: 'A',
+ }, {
+ countryKey: 'AL',
+ value: '+355',
+ countryName_zh: '阿尔巴尼亚',
+ countryName: 'Albania',
+ flag: 'A',
+ }, {
+ countryKey: 'DZ',
+ value: '+213',
+ countryName_zh: '阿尔及利亚',
+ countryName: 'Algeria',
+ flag: 'A',
+ }, {
+ countryKey: 'AD',
+ value: '+376',
+ countryName_zh: '安道尔',
+ countryName: 'Andorra',
+ flag: 'A',
+ }, {
+ countryKey: 'AO',
+ value: '+244',
+ countryName_zh: '安哥拉',
+ countryName: 'Angola',
+ flag: 'A',
+ }, {
+ countryKey: 'AI',
+ value: '+1264',
+ countryName_zh: '安圭拉岛',
+ countryName: 'Anguilla',
+ flag: 'A',
+ }, {
+ countryKey: 'AG',
+ value: '+1268',
+ countryName_zh: '安提瓜岛和巴布达',
+ countryName: 'Antigua and Barbuda',
+ flag: 'A',
+ }, {
+ countryKey: 'AR',
+ value: '+54',
+ countryName_zh: '阿根廷',
+ countryName: 'Argentina',
+ flag: 'A',
+ }, {
+ countryKey: 'AM',
+ value: '+374',
+ countryName_zh: '亚美尼亚',
+ countryName: 'Armenia',
+ flag: 'A',
+ }, {
+ countryKey: 'AW',
+ value: '+297',
+ countryName_zh: '阿鲁巴',
+ countryName: 'Aruba',
+ flag: 'A',
+ }, {
+ countryKey: 'AU',
+ value: '+61',
+ countryName_zh: '澳大利亚',
+ countryName: 'Australia',
+ flag: 'A',
+ }, {
+ countryKey: 'AT',
+ value: '+43',
+ countryName_zh: '奥地利',
+ countryName: 'Austria',
+ flag: 'A',
+ }, {
+ countryKey: 'AZ',
+ value: '+994',
+ countryName_zh: '阿塞拜疆',
+ countryName: 'Azerbaijan',
+ flag: 'A',
+ }, {
+ countryKey: 'BS',
+ value: '+1242',
+ countryName_zh: '巴哈马',
+ countryName: 'Bahamas',
+ flag: 'B',
+ }, {
+ countryKey: 'BH',
+ value: '+973',
+ countryName_zh: '巴林',
+ countryName: 'Bahrain',
+ flag: 'B',
+ }, {
+ countryKey: 'BD',
+ value: '+880',
+ countryName_zh: '孟加拉',
+ countryName: 'Bangladesh',
+ flag: 'B',
+ }, {
+ countryKey: 'BB',
+ value: '+1246',
+ countryName_zh: '巴巴多斯岛',
+ countryName: 'Barbados',
+ flag: 'B',
+ }, {
+ countryKey: 'BY',
+ value: '+375',
+ countryName_zh: '白俄罗斯',
+ countryName: 'Belarus',
+ flag: 'B',
+ }, {
+ countryKey: 'BE',
+ value: '+32',
+ countryName_zh: '比利时',
+ countryName: 'Belgium',
+ flag: 'B',
+ }, {
+ countryKey: 'BZ',
+ value: '+501',
+ countryName_zh: '伯利兹',
+ countryName: 'Belize',
+ flag: 'B',
+ }, {
+ countryKey: 'BJ',
+ value: '+229',
+ countryName_zh: '贝宁',
+ countryName: 'Benin',
+ flag: 'B',
+ }, {
+ countryKey: 'BM',
+ value: '+1441',
+ countryName_zh: '百慕大',
+ countryName: 'Bermuda',
+ flag: 'B',
+ }, {
+ countryKey: 'BT',
+ value: '+975',
+ countryName_zh: '不丹',
+ countryName: 'Bhutan',
+ flag: 'B',
+ }, {
+ countryKey: 'BO',
+ value: '+591',
+ countryName_zh: '玻利维亚',
+ countryName: 'Bolivia',
+ flag: 'B',
+ }, {
+ countryKey: 'BA',
+ value: '+387',
+ countryName_zh: '波斯尼亚和黑塞哥维那',
+ countryName: 'Bosnia And Herzegovina',
+ flag: 'B',
+ }, {
+ countryKey: 'BW',
+ value: '+267',
+ countryName_zh: '博茨瓦纳',
+ countryName: 'Botswana',
+ flag: 'B',
+ }, {
+ countryKey: 'BR',
+ value: '+55',
+ countryName_zh: '巴西',
+ countryName: 'Brazil',
+ flag: 'B',
+ }, {
+ countryKey: 'VG',
+ value: '+1284',
+ countryName_zh: '英属维尔京群岛',
+ countryName: 'British Virgin Islands',
+ flag: 'B',
+ }, {
+ countryKey: 'BN',
+ value: '+673',
+ countryName_zh: '文莱',
+ countryName: 'Brunei',
+ flag: 'B',
+ }, {
+ countryKey: 'BG',
+ value: '+359',
+ countryName_zh: '保加利亚',
+ countryName: 'Bulgaria',
+ flag: 'B',
+ }, {
+ countryKey: 'BF',
+ value: '+226',
+ countryName_zh: '布基纳法索',
+ countryName: 'Burkina Faso',
+ flag: 'B',
+ }, {
+ countryKey: 'BI',
+ value: '+257',
+ countryName_zh: '布隆迪',
+ countryName: 'Burundi',
+ flag: 'B',
+ }, {
+ countryKey: 'KH',
+ value: '+855',
+ countryName_zh: '柬埔寨',
+ countryName: 'Cambodia',
+ flag: 'C',
+ }, {
+ countryKey: 'CM',
+ value: '+237',
+ countryName_zh: '喀麦隆',
+ countryName: 'Cameroon',
+ flag: 'C',
+ }, {
+ countryKey: 'CA',
+ value: '+1',
+ countryName_zh: '加拿大',
+ countryName: 'Canada',
+ flag: 'C',
+ }, {
+ countryKey: 'CV',
+ value: '+238',
+ countryName_zh: '佛得角',
+ countryName: 'Cape verde',
+ flag: 'C',
+ }, {
+ countryKey: 'KY',
+ value: '+1345',
+ countryName_zh: '开曼群岛',
+ countryName: 'Cayman Islands',
+ flag: 'C',
+ }, {
+ countryKey: 'CF',
+ value: '+236',
+ countryName_zh: '中非共和国',
+ countryName: 'Central African Republic',
+ flag: 'C',
+ }, {
+ countryKey: 'TD',
+ value: '+235',
+ countryName_zh: '乍得',
+ countryName: 'Chad',
+ flag: 'C',
+ }, {
+ countryKey: 'CL',
+ value: '+56',
+ countryName_zh: '智利',
+ countryName: 'Chile',
+ flag: 'C',
+ }, {
+ countryKey: 'CN',
+ value: '+86',
+ countryName_zh: '中国',
+ countryName: 'China',
+ flag: 'C',
+ }, {
+ countryKey: 'CO',
+ value: '+57',
+ countryName_zh: '哥伦比亚',
+ countryName: 'Columbia',
+ flag: 'C',
+ }, {
+ countryKey: 'KM',
+ value: '+269',
+ countryName_zh: '科摩罗',
+ countryName: 'Comoros',
+ flag: 'C',
+ }, {
+ countryKey: 'CG',
+ value: '+242',
+ countryName_zh: '刚果民主共和国',
+ countryName: 'Congo-Kinshasa',
+ flag: 'C',
+ }, {
+ countryKey: 'CD',
+ value: '+243',
+ countryName_zh: '刚果共和国',
+ countryName: 'Congo-Brazzaville',
+ flag: 'C',
+ }, {
+ countryKey: 'CK',
+ value: '+682',
+ countryName_zh: '库克群岛',
+ countryName: 'Cook Islands',
+ flag: 'C',
+ }, {
+ countryKey: 'CR',
+ value: '+506',
+ countryName_zh: '哥斯达黎加',
+ countryName: 'Costa Rica',
+ flag: 'C',
+ }, {
+ countryKey: 'CI',
+ value: '+225',
+ countryName_zh: '科特迪瓦',
+ countryName: "Cote d'lvoire",
+ flag: 'C',
+ }, {
+ countryKey: 'HR',
+ value: '+385',
+ countryName_zh: '克罗地亚',
+ countryName: 'Croatia',
+ flag: 'C',
+ }, {
+ countryKey: 'CU',
+ value: '+53',
+ countryName_zh: '古巴',
+ countryName: 'Cuba',
+ flag: 'C',
+ }, {
+ countryKey: 'CY',
+ value: '+357',
+ countryName_zh: '塞浦路斯',
+ countryName: 'Cyprus',
+ flag: 'C',
+ }, {
+ countryKey: 'CZ',
+ value: '+420',
+ countryName_zh: '捷克共和国',
+ countryName: 'Czech Republic',
+ flag: 'C',
+ }, {
+ countryKey: 'DK',
+ value: '+45',
+ countryName_zh: '丹麦',
+ countryName: 'Denmark',
+ flag: 'D',
+ }, {
+ countryKey: 'DJ',
+ value: '+253',
+ countryName_zh: '吉布提',
+ countryName: 'Djibouti',
+ flag: 'D',
+ }, {
+ countryKey: 'DM',
+ value: '+1767',
+ countryName_zh: '多米尼加',
+ countryName: 'Domilica',
+ flag: 'D',
+ }, {
+ countryKey: 'DO',
+ value: '+1809',
+ countryName_zh: '多米尼加共和国',
+ countryName: 'Dominican Republic',
+ flag: 'D',
+ }, {
+ countryKey: 'EC',
+ value: '+593',
+ countryName_zh: '厄瓜多尔',
+ countryName: 'Ecuador',
+ flag: 'E',
+ }, {
+ countryKey: 'EG',
+ value: '+20',
+ countryName_zh: '埃及',
+ countryName: 'Egypt',
+ flag: 'E',
+ }, {
+ countryKey: 'SV',
+ value: '+503',
+ countryName_zh: '萨尔瓦多',
+ countryName: 'EI Salvador',
+ flag: 'E',
+ }, {
+ countryKey: 'GQ',
+ value: '+240',
+ countryName_zh: '赤道几内亚',
+ countryName: 'Equatorial Guinea',
+ flag: 'E',
+ }, {
+ countryKey: 'ER',
+ value: '+291',
+ countryName_zh: '厄立特里亚',
+ countryName: 'Eritrea',
+ flag: 'E',
+ }, {
+ countryKey: 'EE',
+ value: '+372',
+ countryName_zh: '爱沙尼亚',
+ countryName: 'Estonia',
+ flag: 'E',
+ }, {
+ countryKey: 'ET',
+ value: '+251',
+ countryName_zh: '埃塞俄比亚',
+ countryName: 'Ethiopia',
+ flag: 'E',
+ }, {
+ countryKey: 'FO',
+ value: '+298',
+ countryName_zh: '法罗群岛',
+ countryName: 'Faroe Islands',
+ flag: 'F',
+ }, {
+ countryKey: 'FJ',
+ value: '+679',
+ countryName_zh: '斐济',
+ countryName: 'Fiji Islands',
+ flag: 'F',
+ }, {
+ countryKey: 'FI',
+ value: '+358',
+ countryName_zh: '芬兰',
+ countryName: 'Finland',
+ flag: 'F',
+ }, {
+ countryKey: 'FR',
+ value: '+33',
+ countryName_zh: '法国',
+ countryName: 'France',
+ flag: 'F',
+ }, {
+ countryKey: 'PF',
+ value: '+689',
+ countryName_zh: '法属波利尼西亚',
+ countryName: 'French Polynesia',
+ flag: 'F',
+ }, {
+ countryKey: 'GA',
+ value: '+241',
+ countryName_zh: '加蓬',
+ countryName: 'Gabon',
+ flag: 'G',
+ }, {
+ countryKey: 'GM',
+ value: '+220',
+ countryName_zh: '冈比亚',
+ countryName: 'Gambia',
+ flag: 'G',
+ }, {
+ countryKey: 'GE',
+ value: '+995',
+ countryName_zh: '乔治亚',
+ countryName: 'Georgia',
+ flag: 'G',
+ }, {
+ countryKey: 'DE',
+ value: '+49',
+ countryName_zh: '德国',
+ countryName: 'Germany',
+ flag: 'G',
+ }, {
+ countryKey: 'GH',
+ value: '+233',
+ countryName_zh: '加纳',
+ countryName: 'Ghana',
+ flag: 'G',
+ }, {
+ countryKey: 'GI',
+ value: '+350',
+ countryName_zh: '直布罗陀',
+ countryName: 'Gibraltar',
+ flag: 'G',
+ }, {
+ countryKey: 'GR',
+ value: '+30',
+ countryName_zh: '希腊',
+ countryName: 'Greece',
+ flag: 'G',
+ }, {
+ countryKey: 'GL',
+ value: '+299',
+ countryName_zh: '格陵兰',
+ countryName: 'Greenland',
+ flag: 'G',
+ }, {
+ countryKey: 'GD',
+ value: '+1473',
+ countryName_zh: '格林纳达',
+ countryName: 'Grenada',
+ flag: 'G',
+ }, {
+ countryKey: 'GU',
+ value: '+1671',
+ countryName_zh: '关岛',
+ countryName: 'Guam',
+ flag: 'G',
+ }, {
+ countryKey: 'GT',
+ value: '+502',
+ countryName_zh: '危地马拉',
+ countryName: 'Guatemala',
+ flag: 'G',
+ }, {
+ countryKey: 'GN',
+ value: '+224',
+ countryName_zh: '几内亚',
+ countryName: 'Guinea',
+ flag: 'G',
+ }, {
+ countryKey: 'GW',
+ value: '+245',
+ countryName_zh: '几内亚比绍',
+ countryName: 'Guinea-Bissau',
+ flag: 'G',
+ }, {
+ countryKey: 'GY',
+ value: '+592',
+ countryName_zh: '圭亚那',
+ countryName: 'Guyana',
+ flag: 'G',
+ }, {
+ countryKey: 'HT',
+ value: '+509',
+ countryName_zh: '海地',
+ countryName: 'Haiti',
+ flag: 'H',
+ }, {
+ countryKey: 'HN',
+ value: '+504',
+ countryName_zh: '洪都拉斯',
+ countryName: 'Honduras',
+ flag: 'H',
+ }, {
+ countryKey: 'HK',
+ value: '+852',
+ countryName_zh: '中国香港',
+ countryName: 'Hong Kong',
+ flag: 'H',
+ }, {
+ countryKey: 'HU',
+ value: '+36',
+ countryName_zh: '匈牙利',
+ countryName: 'Hungary',
+ flag: 'H',
+ }, {
+ countryKey: 'IS',
+ value: '+354',
+ countryName_zh: '冰岛',
+ countryName: 'Iceland',
+ flag: 'I',
+ }, {
+ countryKey: 'IN',
+ value: '+91',
+ countryName_zh: '印度',
+ countryName: 'India',
+ flag: 'I',
+ }, {
+ countryKey: 'ID',
+ value: '+62',
+ countryName_zh: '印度尼西亚',
+ countryName: 'Indonesia',
+ flag: 'I',
+ }, {
+ countryKey: 'IR',
+ value: '+98',
+ countryName_zh: '伊朗',
+ countryName: 'Iran',
+ flag: 'I',
+ }, {
+ countryKey: 'IQ',
+ value: '+964',
+ countryName_zh: '伊拉克',
+ countryName: 'Iraq',
+ flag: 'I',
+ }, {
+ countryKey: 'IE',
+ value: '+353',
+ countryName_zh: '爱尔兰',
+ countryName: 'Ireland',
+ flag: 'I',
+ }, {
+ countryKey: 'IL',
+ value: '+972',
+ countryName_zh: '以色列',
+ countryName: 'Israel',
+ flag: 'I',
+ }, {
+ countryKey: 'IT',
+ value: '+39',
+ countryName_zh: '意大利',
+ countryName: 'Italy',
+ flag: 'I',
+ }, {
+ countryKey: 'JM',
+ value: '+1876',
+ countryName_zh: '牙买加',
+ countryName: 'Jamaica',
+ flag: 'J',
+ }, {
+ countryKey: 'JP',
+ value: '+81',
+ countryName_zh: '日本',
+ countryName: 'Japan',
+ flag: 'J',
+ }, {
+ countryKey: 'JE',
+ value: '+44',
+ countryName_zh: '泽西岛',
+ countryName: 'Jersey',
+ flag: 'J',
+ }, {
+ countryKey: 'JO',
+ value: '+962',
+ countryName_zh: '约旦',
+ countryName: 'Jordan',
+ flag: 'J',
+ }, {
+ countryKey: 'KZ',
+ value: '+7',
+ countryName_zh: '哈萨克斯坦',
+ countryName: 'Kazakhstan',
+ flag: 'K',
+ }, {
+ countryKey: 'KE',
+ value: '+254',
+ countryName_zh: '肯尼亚',
+ countryName: 'Kenya',
+ flag: 'K',
+ }, {
+ countryKey: 'KR',
+ value: '+82',
+ countryName_zh: '韩国',
+ countryName: 'Korea',
+ flag: 'K',
+ }, {
+ countryKey: 'KW',
+ value: '+965',
+ countryName_zh: '科威特',
+ countryName: 'Kuwait',
+ flag: 'K',
+ }, {
+ countryKey: 'KG',
+ value: '+996',
+ countryName_zh: '吉尔吉斯斯坦',
+ countryName: 'Kyrgyzstan',
+ flag: 'K',
+ }, {
+ countryKey: 'LA',
+ value: '+856',
+ countryName_zh: '老挝',
+ countryName: 'Laos',
+ flag: 'L',
+ }, {
+ countryKey: 'LV',
+ value: '+371',
+ countryName_zh: '拉脱维亚',
+ countryName: 'Latvia',
+ flag: 'L',
+ }, {
+ countryKey: 'LB',
+ value: '+961',
+ countryName_zh: '黎巴嫩',
+ countryName: 'Lebanon',
+ flag: 'L',
+ }, {
+ countryKey: 'LS',
+ value: '+266',
+ countryName_zh: '莱索托',
+ countryName: 'Lesotho',
+ flag: 'L',
+ }, {
+ countryKey: 'LR',
+ value: '+231',
+ countryName_zh: '利比里亚',
+ countryName: 'Liberia',
+ flag: 'L',
+ }, {
+ countryKey: 'LY',
+ value: '+218',
+ countryName_zh: '利比亚',
+ countryName: 'Libya',
+ flag: 'L',
+ }, {
+ countryKey: 'LI',
+ value: '+423',
+ countryName_zh: '列支敦士登',
+ countryName: 'Liechtenstein',
+ flag: 'L',
+ }, {
+ countryKey: 'LT',
+ value: '+370',
+ countryName_zh: '立陶宛',
+ countryName: 'Lithuania',
+ flag: 'L',
+ }, {
+ countryKey: 'LU',
+ value: '+352',
+ countryName_zh: '卢森堡',
+ countryName: 'Luxembourg',
+ flag: 'L',
+ }, {
+ countryKey: 'MO',
+ value: '+853',
+ countryName_zh: '中国澳门',
+ countryName: 'Macao',
+ flag: 'M',
+ }, {
+ countryKey: 'MK',
+ value: '+389',
+ countryName_zh: '马其顿',
+ countryName: 'Macedonia,Former Yugoslav Republic of',
+ flag: 'M',
+ }, {
+ countryKey: 'MG',
+ value: '+261',
+ countryName_zh: '马达加斯加',
+ countryName: 'Madagascar',
+ flag: 'M',
+ }, {
+ countryKey: 'MW',
+ value: '+265',
+ countryName_zh: '马拉维',
+ countryName: 'Malawi',
+ flag: 'M',
+ }, {
+ countryKey: 'MY',
+ value: '+60',
+ countryName_zh: '马来西亚',
+ countryName: 'Malaysia',
+ flag: 'M',
+ }, {
+ countryKey: 'MV',
+ value: '+960',
+ countryName_zh: '马尔代夫',
+ countryName: 'Maldives',
+ flag: 'M',
+ }, {
+ countryKey: 'ML',
+ value: '+223',
+ countryName_zh: '马里',
+ countryName: 'Mali',
+ flag: 'M',
+ }, {
+ countryKey: 'MT',
+ value: '+356',
+ countryName_zh: '马耳他',
+ countryName: 'Malta',
+ flag: 'M',
+ }, {
+ countryKey: 'MR',
+ value: '+222',
+ countryName_zh: '毛里塔尼亚',
+ countryName: 'Mauritania',
+ flag: 'M',
+ }, {
+ countryKey: 'MX',
+ value: '+52',
+ countryName_zh: '墨西哥',
+ countryName: 'Mexico',
+ flag: 'M',
+ }, {
+ countryKey: 'MD',
+ value: '+373',
+ countryName_zh: '摩尔多瓦',
+ countryName: 'Moldova',
+ flag: 'M',
+ }, {
+ countryKey: 'MC',
+ value: '+377',
+ countryName_zh: '摩纳哥',
+ countryName: 'Monaco',
+ flag: 'M',
+ }, {
+ countryKey: 'MN',
+ value: '+976',
+ countryName_zh: '蒙古',
+ countryName: 'Mongolia',
+ flag: 'M',
+ }, {
+ countryKey: 'ME',
+ value: '+382',
+ countryName_zh: '黑山共和国',
+ countryName: 'Montenegro',
+ flag: 'M',
+ }, {
+ countryKey: 'MA',
+ value: '+212',
+ countryName_zh: '摩洛哥',
+ countryName: 'Morocco',
+ flag: 'M',
+ }, {
+ countryKey: 'MZ',
+ value: '+258',
+ countryName_zh: '莫桑比克',
+ countryName: 'Mozambique',
+ flag: 'M',
+ }, {
+ countryKey: 'MM',
+ value: '+95',
+ countryName_zh: '缅甸',
+ countryName: 'Myanmar',
+ flag: 'M',
+ }, {
+ countryKey: 'NA',
+ value: '+264',
+ countryName_zh: '纳米比亚',
+ countryName: 'Namibia',
+ flag: 'N',
+ }, {
+ countryKey: 'NP',
+ value: '+977',
+ countryName_zh: '尼泊尔',
+ countryName: 'Nepal',
+ flag: 'N',
+ }, {
+ countryKey: 'NL',
+ value: '+31',
+ countryName_zh: '荷兰',
+ countryName: 'Netherlands',
+ flag: 'N',
+ }, {
+ countryKey: 'AN',
+ value: '+599',
+ countryName_zh: '荷属安的列斯群岛',
+ countryName: 'Netherlands Antilles',
+ flag: 'N',
+ }, {
+ countryKey: 'NC',
+ value: '+687',
+ countryName_zh: '新喀里多尼亚',
+ countryName: 'New Caledonia',
+ flag: 'N',
+ }, {
+ countryKey: 'NZ',
+ value: '+64',
+ countryName_zh: '新西兰',
+ countryName: 'New Zealand',
+ flag: 'N',
+ }, {
+ countryKey: 'NI',
+ value: '+505',
+ countryName_zh: '尼加拉瓜',
+ countryName: 'Nicaragua',
+ flag: 'N',
+ }, {
+ countryKey: 'NE',
+ value: '+227',
+ countryName_zh: '尼日尔',
+ countryName: 'Niger',
+ flag: 'N',
+ }, {
+ countryKey: 'NG',
+ value: '+234',
+ countryName_zh: '尼日利亚',
+ countryName: 'Nigeria',
+ flag: 'N',
+ }, {
+ countryKey: 'KP',
+ value: '+850',
+ countryName_zh: '朝鲜',
+ countryName: 'North Korea',
+ flag: 'N',
+ }, {
+ countryKey: 'NO',
+ value: '+47',
+ countryName_zh: '挪威',
+ countryName: 'Norway',
+ flag: 'N',
+ }, {
+ countryKey: 'OM',
+ value: '+968',
+ countryName_zh: '阿曼',
+ countryName: 'Oman',
+ flag: 'O',
+ }, {
+ countryKey: 'PK',
+ value: '+92',
+ countryName_zh: '巴基斯坦',
+ countryName: 'Pakistan',
+ flag: 'P',
+ }, {
+ countryKey: 'PA',
+ value: '+507',
+ countryName_zh: '巴拿马',
+ countryName: 'Panama',
+ flag: 'P',
+ }, {
+ countryKey: 'PG',
+ value: '+675',
+ countryName_zh: '巴布亚新几内亚',
+ countryName: 'Papua New Guinea',
+ flag: 'P',
+ }, {
+ countryKey: 'PY',
+ value: '+595',
+ countryName_zh: '巴拉圭',
+ countryName: 'Paraguay',
+ flag: 'P',
+ }, {
+ countryKey: 'PE',
+ value: '+51',
+ countryName_zh: '秘鲁',
+ countryName: 'Peru',
+ flag: 'P',
+ }, {
+ countryKey: 'PH',
+ value: '+63',
+ countryName_zh: '菲律宾',
+ countryName: 'Philippines',
+ flag: 'P',
+ }, {
+ countryKey: 'PL',
+ value: '+48',
+ countryName_zh: '波兰',
+ countryName: 'Poland',
+ flag: 'P',
+ }, {
+ countryKey: 'PT',
+ value: '+351',
+ countryName_zh: '葡萄牙',
+ countryName: 'Portugal',
+ flag: 'P',
+ }, {
+ countryKey: 'PR',
+ value: '+1',
+ countryName_zh: '波多黎各',
+ countryName: 'Puerto Rico',
+ flag: 'P',
+ }, {
+ countryKey: 'QA',
+ value: '+974',
+ countryName_zh: '卡塔尔',
+ countryName: 'Qatar',
+ flag: 'Q',
+ }, {
+ countryKey: 'RO',
+ value: '+40',
+ countryName_zh: '罗马尼亚',
+ countryName: 'Romania',
+ flag: 'R',
+ }, {
+ countryKey: 'RU',
+ value: '+7',
+ countryName_zh: '俄罗斯',
+ countryName: 'Russia',
+ flag: 'R',
+ }, {
+ countryKey: 'RW',
+ value: '+250',
+ countryName_zh: '卢旺达',
+ countryName: 'Rwanda',
+ flag: 'R',
+ }, {
+ countryKey: 'LC',
+ value: '+1758',
+ countryName_zh: '圣卢西亚',
+ countryName: 'Saint Lucia',
+ flag: 'S',
+ }, {
+ countryKey: 'PM',
+ value: '+508',
+ countryName_zh: '圣皮埃尔和密克隆',
+ countryName: 'Saint Pierre and Miquelon',
+ flag: 'S',
+ }, {
+ countryKey: 'VC',
+ value: '+1784',
+ countryName_zh: '圣文森特河格林纳丁斯',
+ countryName: 'Saint Vincent And the Grenadines',
+ flag: 'S',
+ }, {
+ countryKey: 'WS',
+ value: '+685',
+ countryName_zh: '萨摩亚',
+ countryName: 'Samoa',
+ flag: 'S',
+ }, {
+ countryKey: 'SM',
+ value: '+378',
+ countryName_zh: '圣马力诺',
+ countryName: 'San Marino',
+ flag: 'S',
+ }, {
+ countryKey: 'ST',
+ value: '+239',
+ countryName_zh: '圣多美和普林西比',
+ countryName: 'Sao Tome and Principe',
+ flag: 'S',
+ }, {
+ countryKey: 'SA',
+ value: '+966',
+ countryName_zh: '沙特阿拉伯',
+ countryName: 'Saudi Arabia',
+ flag: 'S',
+ }, {
+ countryKey: 'SN',
+ value: '+221',
+ countryName_zh: '塞内加尔',
+ countryName: 'Senegal',
+ flag: 'S',
+ }, {
+ countryKey: 'RS',
+ value: '+381',
+ countryName_zh: '塞尔维亚',
+ countryName: 'Serbia',
+ flag: 'S',
+ }, {
+ countryKey: 'SC',
+ value: '+248',
+ countryName_zh: '塞舌尔',
+ countryName: 'Seychelles',
+ flag: 'S',
+ }, {
+ countryKey: 'SL',
+ value: '+232',
+ countryName_zh: '塞拉利昂',
+ countryName: 'Sierra Leone',
+ flag: 'S',
+ }, {
+ countryKey: 'SG',
+ value: '+65',
+ countryName_zh: '新加坡',
+ countryName: 'Singapore',
+ flag: 'S',
+ }, {
+ countryKey: 'SK',
+ value: '+421',
+ countryName_zh: '斯洛伐克',
+ countryName: 'Slovakia',
+ flag: 'S',
+ }, {
+ countryKey: 'SI',
+ value: '+386',
+ countryName_zh: '斯洛文尼亚',
+ countryName: 'Slovenia',
+ flag: 'S',
+ }, {
+ countryKey: 'SO',
+ value: '+252',
+ countryName_zh: '索马里',
+ countryName: 'Somalia',
+ flag: 'S',
+ }, {
+ countryKey: 'ZA',
+ value: '+27',
+ countryName_zh: '南非',
+ countryName: 'South Africa',
+ flag: 'S',
+ }, {
+ countryKey: 'ES',
+ value: '+34',
+ countryName_zh: '西班牙',
+ countryName: 'Spain',
+ flag: 'S',
+ }, {
+ countryKey: 'LK',
+ value: '+94',
+ countryName_zh: '斯里兰卡',
+ countryName: 'Sri Lanka',
+ flag: 'S',
+ }, {
+ countryKey: 'KN',
+ value: '+1869',
+ countryName_zh: '圣基茨和尼维斯',
+ countryName: 'St.Kitts and Nevis',
+ flag: 'S',
+ }, {
+ countryKey: 'SD',
+ value: '+249',
+ countryName_zh: '苏丹',
+ countryName: 'Sudan',
+ flag: 'S',
+ }, {
+ countryKey: 'SR',
+ value: '+597',
+ countryName_zh: '苏里南',
+ countryName: 'Surinam',
+ flag: 'S',
+ }, {
+ countryKey: 'SZ',
+ value: '+268',
+ countryName_zh: '斯威士兰',
+ countryName: 'Swaziland',
+ flag: 'S',
+ }, {
+ countryKey: 'SE',
+ value: '+46',
+ countryName_zh: '瑞典',
+ countryName: 'Sweden',
+ flag: 'S',
+ }, {
+ countryKey: 'CH',
+ value: '+41',
+ countryName_zh: '瑞士',
+ countryName: 'Switzerland',
+ flag: 'S',
+ }, {
+ countryKey: 'SY',
+ value: '+963',
+ countryName_zh: '叙利亚',
+ countryName: 'Syria',
+ flag: 'S',
+ }, {
+ countryKey: 'TW',
+ value: '+886',
+ countryName_zh: '中国台湾',
+ countryName: 'Taiwan',
+ flag: 'T',
+ }, {
+ countryKey: 'TJ',
+ value: '+992',
+ countryName_zh: '塔吉克斯坦',
+ countryName: 'Tajikistan',
+ flag: 'T',
+ }, {
+ countryKey: 'TZ',
+ value: '+255',
+ countryName_zh: '坦桑尼亚',
+ countryName: 'Tanzania',
+ flag: 'T',
+ }, {
+ countryKey: 'TH',
+ value: '+66',
+ countryName_zh: '泰国',
+ countryName: 'Thailand',
+ flag: 'T',
+ }, {
+ countryKey: 'TL',
+ value: '+670',
+ countryName_zh: '东帝汶',
+ countryName: 'Timor-Leste',
+ flag: 'T',
+ }, {
+ countryKey: 'TG',
+ value: '+228',
+ countryName_zh: '多哥',
+ countryName: 'Togo',
+ flag: 'T',
+ }, {
+ countryKey: 'TO',
+ value: '+676',
+ countryName_zh: '汤加',
+ countryName: 'Tonga',
+ flag: 'T',
+ }, {
+ countryKey: 'TT',
+ value: '+1868',
+ countryName_zh: '特立尼达和多巴哥',
+ countryName: 'Trinidad and Tobago',
+ flag: 'T',
+ }, {
+ countryKey: 'TN',
+ value: '+216',
+ countryName_zh: '突尼斯',
+ countryName: 'Tunisia',
+ flag: 'T',
+ }, {
+ countryKey: 'TR',
+ value: '+90',
+ countryName_zh: '土耳其',
+ countryName: 'Turkey',
+ flag: 'T',
+ }, {
+ countryKey: 'TM',
+ value: '+993',
+ countryName_zh: '土库曼斯坦',
+ countryName: 'Turkmenistan',
+ flag: 'T',
+ }, {
+ countryKey: 'TC',
+ value: '+1649',
+ countryName_zh: '特克斯和凯科斯群岛',
+ countryName: 'Turks and Caicos Islands',
+ flag: 'T',
+ }, {
+ countryKey: 'UG',
+ value: '+256',
+ countryName_zh: '乌干达',
+ countryName: 'Uganda',
+ flag: 'U',
+ }, {
+ countryKey: 'UA',
+ value: '+380',
+ countryName_zh: '乌克兰',
+ countryName: 'Ukraine',
+ flag: 'U',
+ }, {
+ countryKey: 'AE',
+ value: '+971',
+ countryName_zh: '阿拉伯联合酋长国',
+ countryName: 'United Arab Emirates',
+ flag: 'U',
+ }, {
+ countryKey: 'GB',
+ value: '+44',
+ countryName_zh: '英国',
+ countryName: 'United Kingdom',
+ flag: 'U',
+ }, {
+ countryKey: 'US',
+ value: '+1',
+ countryName_zh: '美国',
+ countryName: 'United States',
+ flag: 'U',
+ }, {
+ countryKey: 'UY',
+ value: '+598',
+ countryName_zh: '乌拉圭',
+ countryName: 'Uruguay',
+ flag: 'U',
+ }, {
+ countryKey: 'UZ',
+ value: '+998',
+ countryName_zh: '乌兹别克斯坦',
+ countryName: 'Uzbekistan',
+ flag: 'U',
+ }, {
+ countryKey: 'VU',
+ value: '+678',
+ countryName_zh: '瓦努阿图',
+ countryName: 'Vanuatu',
+ flag: 'V',
+ }, {
+ countryKey: 'VE',
+ value: '+58',
+ countryName_zh: '委内瑞拉',
+ countryName: 'Venezuela',
+ flag: 'V',
+ }, {
+ countryKey: 'VN',
+ value: '+84',
+ countryName_zh: '越南',
+ countryName: 'Vietnam',
+ flag: 'V',
+ }, {
+ countryKey: 'YE',
+ value: '+967',
+ countryName_zh: '也门',
+ countryName: 'Yemen',
+ flag: 'Y',
+ }, {
+ countryKey: 'ZM',
+ value: '+260',
+ countryName_zh: '赞比亚',
+ countryName: 'Zambia',
+ flag: 'Z',
+ }, {
+ countryKey: 'ZW',
+ value: '+263',
+ countryName_zh: '津巴布韦',
+ countryName: 'Zimbabwe',
+ flag: 'Z',
+ },
+];
diff --git a/packages/material-parser/test/fixtures/dts-component/src/i18n.js b/packages/material-parser/test/fixtures/dts-component/src/i18n.js
new file mode 100644
index 000000000..0b4c2e79f
--- /dev/null
+++ b/packages/material-parser/test/fixtures/dts-component/src/i18n.js
@@ -0,0 +1,27 @@
+/**
+ * 组件内置的多语言文案
+ */
+
+const bundles = {
+ 'zh-CN': {
+ dataSource: [
+ {
+ label: '+86',
+ value: '86',
+ country: '中国',
+ rule: /(?=(\d{4})+$)/g,
+ },
+ ],
+ },
+ 'en-US': {
+ dataSource: [
+ {
+ label: '+86',
+ value: '86',
+ country: 'china',
+ rule: /(?=(\d{4})+$)/g,
+ },
+ ],
+ },
+};
+export default bundles;
diff --git a/packages/material-parser/test/fixtures/dts-component/src/index.jsx b/packages/material-parser/test/fixtures/dts-component/src/index.jsx
new file mode 100644
index 000000000..eb76866db
--- /dev/null
+++ b/packages/material-parser/test/fixtures/dts-component/src/index.jsx
@@ -0,0 +1,142 @@
+import React from 'react';
+import { Select, Input } from '@alifd/next';
+import i18n from '@alife/whale-i18n';
+import classnames from 'classnames';
+import PropTypes from 'prop-types';
+import { getLanguage } from '@alife/whale-util';
+
+import i18nBundles from './i18n';
+import countryDataSource from './data';
+
+const lang = getLanguage();
+const isCN = ['ZH_CN', 'ZH-CN'].includes(lang && lang.toUpperCase());
+
+class WhaleTelephone extends React.Component {
+ static displayName = 'WhaleTelephone';
+
+ static propTypes = {
+ style: PropTypes.object,
+ className: PropTypes.string,
+ disabled: PropTypes.bool,
+ value: PropTypes.object,
+ onChange: PropTypes.func,
+ };
+
+ static defaultProps = {
+ style: {},
+ className: '',
+ disabled: false,
+ onChange: undefined,
+ value: {
+ countryCode: '+86',
+ phoneNumber: '',
+ },
+ };
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ popupStyle: {},
+ tmpSelectedItem: {},
+ };
+ }
+
+ componentDidMount() {
+ if (!this.props.readOnly) {
+ this.handleStyle();
+ window.addEventListener('resize', this.resizeEventFunction);
+ }
+ }
+
+ componentWillUnmount() {
+ if (!this.props.readOnly) {
+ window.removeEventListener('resize', this.resizeEventFunction);
+ }
+ }
+
+ resizeEventFunction = () => this.handleStyle();
+
+ handleStyle = () => {
+ const { el } = this;
+ const elWidth = el.offsetWidth;
+ this.setState({
+ popupStyle: {
+ width: elWidth,
+ },
+ });
+ };
+
+ selectChange=(val, actionType, tmpSelectedItem) => {
+ const { value, onChange } = this.props;
+ this.setState({ tmpSelectedItem });
+ onChange && onChange(Object.assign({}, value, { countryCode: val }), tmpSelectedItem, 'select');
+ };
+
+ inputChange = (val) => {
+ const { value, onChange } = this.props;
+ const { tmpSelectedItem } = this.state;
+ onChange && onChange(Object.assign({}, value, { phoneNumber: val }), tmpSelectedItem, 'input');
+ };
+
+ renderItem = (item) => {
+ const { countryName, countryName_zh: countryNameZh, value } = item;
+ return (
+
+ {!isCN ? countryName : countryNameZh}
+ {value}
+
+ );
+ };
+
+ render() {
+ // i18nBundle 是 i18n 包装后额外提供的 prop,表示组件当前实际使用的文案
+ const {
+ style,
+ className,
+ disabled,
+ value: { countryCode, phoneNumber },
+ readOnly,
+ } = this.props;
+ // 排除掉不需要透传下去的参数,特别地适用于直接把大部分特殊控制外的参数透传给 Fusion 等组件的用法
+ const cls = classnames({
+ 'whale-telephone': true,
+ 'whale-telephone-readonly': !!readOnly,
+ [className]: className,
+ });
+ const { popupStyle } = this.state;
+
+ if (readOnly) {
+ return (
+
+ {countryCode} {phoneNumber}
+
+ );
+ }
+
+ return (
+ { this.el = ref; }} data-name="WhaleTelephone">
+
+
+
+ );
+ }
+}
+
+// 默认 export 提供了内置多语言文案的组件
+export default i18n(WhaleTelephone, i18nBundles);
+// 万一需有对组件进行扩展,为了避免 HOC 后无法直接继承,提供了导出组件内置多语言文案及未经 HOC 的组件
+export { i18nBundles, WhaleTelephone as Pure };
diff --git a/packages/material-parser/test/fixtures/dts-component/src/main.scss b/packages/material-parser/test/fixtures/dts-component/src/main.scss
new file mode 100644
index 000000000..0f2567674
--- /dev/null
+++ b/packages/material-parser/test/fixtures/dts-component/src/main.scss
@@ -0,0 +1,40 @@
+
+@import 'scss/variable';
+
+// put your code here
+
+.whale-telephone {
+ display: flex;
+ .whale-telephone-select {
+ min-width: 72px;
+ width: 72px;
+ .next-select-inner {
+ min-width: 72px;
+ }
+ .next-input.next-medium {
+ border-radius: 0;
+ border-right: none;
+ }
+ }
+ .whale-telephone-number-input {
+ flex-grow: 2;
+ border-radius: 0;
+ &.next-input.next-medium {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ }
+ }
+
+ &.whale-telephone-readonly {
+ font-family: Roboto;
+ color: #262626;
+ font-size: 14px;
+ line-height: 1.7;
+ }
+}
+
+.whale-telephone-select-popup {
+ .code-span {
+ float: right;
+ }
+}
diff --git a/packages/material-parser/test/fixtures/dts-component/src/scss/variable.scss b/packages/material-parser/test/fixtures/dts-component/src/scss/variable.scss
new file mode 100644
index 000000000..46edcf719
--- /dev/null
+++ b/packages/material-parser/test/fixtures/dts-component/src/scss/variable.scss
@@ -0,0 +1,12 @@
+////
+/// @module @alife/whale-telephone: 组件中文名
+/// @tag WhaleTelephone
+/// @category custom
+/// @family whale-telephone
+/// @varPrefix $whale-telephone
+/// @classPrefix whale-telephone
+////
+
+/// backgroud
+/// @namespace statement/normal
+$whale-telephone-color: $color-brand1-1 !default;
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/amContainer.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/amContainer.js
new file mode 100644
index 000000000..45df1897e
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/amContainer.js
@@ -0,0 +1,11 @@
+import component from './index.js';
+import amManifest from './amManifest.js';
+
+const getComponent = function () {
+ return Promise.resolve(component);
+};
+
+export default {
+ getComponent,
+ manifest: amManifest,
+};
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/amManifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/amManifest.js
new file mode 100644
index 000000000..c9c2b1b05
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/amManifest.js
@@ -0,0 +1,144 @@
+/**
+ * The template of manifest for AiMake studio.
+ */
+function _update(Nygma, node) {
+ const attributes = node.get();
+ const display = attributes.display;
+ const flexDirection = attributes.flexDirection;
+ const alignItems = attributes.alignItems;
+ const justifyContent = attributes.justifyContent;
+ const flexWrap = attributes.flexWrap;
+ const isFlex = display === 'flex';
+ node.set({
+ display,
+ flexDirection: isFlex ? flexDirection : undefined,
+ alignItems: isFlex ? alignItems : undefined,
+ justifyContent: isFlex ? justifyContent : undefined,
+ flexWrap: isFlex ? flexWrap : undefined,
+ });
+}
+
+const manifest = {
+ // The name of current component.
+ name: 'AIMakeBlank',
+ // The description of current component.
+ description: '空白卡片',
+ // The coverimage's url of current component.
+ coverImage: 'https://img.alicdn.com/tfs/TB1un9tqntYBeNjy1XdXXXXyVXa-366-124.png',
+ // The category of current component in AiMake studio.
+ // can be:
+ // `分栏` or `文本` or `按钮` or `标签` or `标签页` or `表格` or `单选` or `分割线`
+ // or `分页` or `复选` or `滑动条` or `进度条` or `卡片` or `开关` or `缺省状态`
+ // or `日期选择` or `输入框` or `搜索框` or `图表` or `图片` or `下拉选择` or `表单行`
+ // or `树控件` or `折叠面板` or `占位图`
+ category: '布局',
+ // card.blank
+ // The preview list of current component in AiMake studio.
+ // Each preset contains following keys:
+ // - `alias`: string. required. The previewing component's name to display
+ // - `thumbnail`: string. not required. The previewing component's thumbnail
+ // - `customProps`: object. not required.
+ // The previewing component's customize props, e.g. { [propName]: [propValue] }
+ // - `colSpan`: number. not required. default 24 (1~24). The previewing component's size when to display
+ presets: [{
+ alias: '空白卡片',
+ thumbnail: 'https://img.alicdn.com/tfs/TB1ucPNVsbpK1RjSZFyXXX_qFXa-198-120.png',
+ colSpan: 12,
+ customProps: {
+ id: '',
+ textAlign: 'left',
+ padding: '12px',
+ width: '100%',
+ backgroundColor: '#FFF',
+ },
+ }],
+ // Other settings of current component for AiMake studio.
+ settings: {
+ // The render type of current component in AiMake studio.
+ // can be:
+ // `element_inline` or `element_block` or `container`
+ type: 'container',
+ // The insert mode of current component in AiMake studio.
+ // can be:
+ // one or combine of `t` and `b` and `r` and `l`
+ insertionModes: 'tbrlv',
+ // The handle list of current component in AiMake studio.
+ // can be:
+ // an array contains one and more of ['cut', 'copy', 'paste', 'delete', 'duplicate']
+ handles: ['cut', 'copy', 'paste', 'delete', 'duplicate'],
+ // Whether the component can be actived.
+ shouldActive: true,
+ // Whether the component can be dragged.
+ shouldDrag: true,
+ lifeCycle: {
+ didMount (props) {
+ const Nygma = props.Nygma;
+ const dragInstance = props.dragInstance;
+ const Drager = dragInstance.NygmaNode;
+
+ _update(Nygma, Drager);
+ },
+ didUpdate (Nygma, node, args) {
+ const newvalue = args[1];
+ const oldvalue = args[2];
+
+ if (JSON.stringify(newvalue) !== JSON.stringify(oldvalue)) {
+ _update(Nygma, node);
+ }
+ },
+ },
+ // The props of current component in AiMake studio.
+ // Each property contains following keys:
+ // - `name`: string. required. The property's name
+ // - `label`: string. required. The property's name to display
+ // - `renderer`: string. required. The property's editor. can be: (@冰骊)
+ // - `defaultValue`: any. not required. The property's default value
+ // - `params`: any. not required. The parameters for property's editor
+ // - `placeholder`: string. not required. The placeholder for property's editor
+ // - `hint`: string. not required. The hint for property's editor
+ props: [{
+ name: 'id',
+ label: 'id',
+ defaultValue: '',
+ renderer: 'Input',
+ }, {
+ name: 'textAlign',
+ label: '水平对齐',
+ defaultValue: 'left',
+ renderer: 'TextAlign',
+ }, {
+ name: 'margin',
+ label: '外边距',
+ renderer: 'Quadrant',
+ }, {
+ name: 'padding',
+ label: '内边距',
+ renderer: 'Quadrant',
+ defaultValue: '12px',
+ }, {
+ name: 'width',
+ label: '宽度',
+ defaultValue: '100%',
+ renderer: 'Width',
+ }, {
+ name: 'height',
+ label: '高度',
+ renderer: 'Height',
+ defaultValue: undefined,
+ }, {
+ name: 'backgroundColor',
+ label: '背景颜色',
+ renderer: 'Color',
+ defaultValue: '#FFF',
+ }, {
+ name: 'border',
+ label: '边框',
+ renderer: 'BarBorder',
+ }, {
+ name: 'display',
+ label: '布局设置',
+ renderer: 'FlexLayout',
+ }],
+ },
+};
+export default manifest;
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/container.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/container.js
new file mode 100644
index 000000000..30e1f2996
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/container.js
@@ -0,0 +1,6 @@
+
+ import AIMakeBlank from './index.js';
+ import manifest from './manifest.js';
+
+ export default { origin: AIMakeBlank, manifest };
+
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/index.js
new file mode 100644
index 000000000..429bfc0df
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/index.js
@@ -0,0 +1,74 @@
+import _extends from "@babel/runtime/helpers/extends";
+import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
+import _createClass from "@babel/runtime/helpers/createClass";
+import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
+import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
+import _inherits from "@babel/runtime/helpers/inherits";
+import _defineProperty from "@babel/runtime/helpers/defineProperty";
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import HOCBoxModelProps from '../utils/HOCBoxModelProps';
+import HOCLayoutProps from '../utils/HOCLayoutProps';
+import HOCBackgroundProps from '../utils/HOCBackgroundProps';
+import HOCFlexLayoutProps from '../utils/HOCFlexLayoutProps';
+
+const AIMakeBlank =
+/* #__PURE__ */
+function (_Component) {
+ _inherits(AIMakeBlank, _Component);
+
+ function AIMakeBlank() {
+ _classCallCheck(this, AIMakeBlank);
+
+ return _possibleConstructorReturn(this, _getPrototypeOf(AIMakeBlank).apply(this, arguments));
+ }
+
+ _createClass(AIMakeBlank, [{
+ key: "render",
+ value: function render() {
+ const merged = {};
+ const _this$props = this.props;
+ const children = _this$props.children;
+ const styleBoxModel = _this$props.styleBoxModel;
+ const styleLayout = _this$props.styleLayout;
+ const styleBackground = _this$props.styleBackground;
+ const styleFlexLayout = _this$props.styleFlexLayout;
+ const style = _this$props.style;
+ const id = _this$props.id;
+ const styles = { ...styleBoxModel,
+ ...styleLayout,
+ ...styleBackground,
+ ...styleFlexLayout,
+ ...style,
+ };
+
+ if (id) {
+ merged.id = id;
+ }
+
+ return React.createElement("div", _extends({
+ style: styles,
+ }, merged), children);
+ },
+ }]);
+
+ return AIMakeBlank;
+}(Component);
+
+_defineProperty(AIMakeBlank, "propTypes", {
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
+ styleBoxModel: PropTypes.object.isRequired,
+ styleLayout: PropTypes.object.isRequired,
+ styleBackground: PropTypes.object.isRequired,
+ styleFlexLayout: PropTypes.object.isRequired,
+ style: PropTypes.object,
+ id: PropTypes.string,
+});
+
+_defineProperty(AIMakeBlank, "defaultProps", {
+ children: [],
+ style: {},
+ id: '',
+});
+
+export default HOCBoxModelProps(HOCLayoutProps(HOCBackgroundProps(HOCFlexLayoutProps(AIMakeBlank))));
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/manifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/manifest.js
new file mode 100644
index 000000000..6ef1078e0
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/manifest.js
@@ -0,0 +1 @@
+{"componentName":"AIMakeBlank","title":"","docUrl":"","screenshot":"","npm":{"package":"@ali/lowcode-engine-material-parser","version":"0.1.0","exportName":"AIMakeBlank","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[{"name":"children","propType":"oneOfType","description":""},{"name":"styleBoxModel","propType":"object","description":""},{"name":"styleLayout","propType":"object","description":""},{"name":"styleBackground","propType":"object","description":""},{"name":"styleFlexLayout","propType":"object","description":""},{"name":"style","propType":"object","description":"","defaultValue":"{}"},{"name":"id","propType":"string","description":""}]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/manifest.json b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/manifest.json
new file mode 100644
index 000000000..13da88146
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/manifest.json
@@ -0,0 +1 @@
+{"title":"multiple-exported-component","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/IconFont.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/IconFont.js
new file mode 100644
index 000000000..fa86f316d
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/IconFont.js
@@ -0,0 +1,67 @@
+import _extends from "@babel/runtime/helpers/extends";
+import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
+import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
+import _createClass from "@babel/runtime/helpers/createClass";
+import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
+import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
+import _inherits from "@babel/runtime/helpers/inherits";
+import React, { Component } from 'react';
+import PropTypes from 'prop-types'; // 缓存已加载的字体文件
+
+const customCache = new Set(); // 动态加载字体文件
+
+export default function createFromIconfont(options) {
+ const scriptUrl = options.scriptUrl;
+
+ if (typeof document !== 'undefined' && typeof window !== 'undefined' && typeof document.createElement === 'function' && typeof scriptUrl === 'string' && scriptUrl.length && !customCache.has(scriptUrl)) {
+ const script = document.createElement('script');
+ script.setAttribute('src', scriptUrl);
+ script.setAttribute('data-namespace', scriptUrl);
+ customCache.add(scriptUrl);
+ document.body.appendChild(script);
+ }
+
+ const IconFont =
+ /* #__PURE__ */
+ function (_Component) {
+ _inherits(IconFont, _Component);
+
+ function IconFont() {
+ _classCallCheck(this, IconFont);
+
+ return _possibleConstructorReturn(this, _getPrototypeOf(IconFont).apply(this, arguments));
+ }
+
+ _createClass(IconFont, [{
+ key: "render",
+ value: function render() {
+ const _this$props = this.props;
+ const type = _this$props.type;
+ const restProps = _objectWithoutProperties(_this$props, ["type"]);
+
+ const innerSvgProps = {
+ width: '1em',
+ height: '1em',
+ fill: 'currentColor',
+ 'aria-hidden': 'true',
+ focusable: 'false',
+ }; // 引用指定svg
+
+ const content = React.createElement("use", {
+ xlinkHref: `#${type}`,
+ });
+ return React.createElement("i", _extends({}, restProps, {
+ className: `iconfont ${type}`,
+ }), React.createElement("svg", innerSvgProps, content));
+ },
+ }]);
+
+ return IconFont;
+ }(Component);
+
+ IconFont.propTypes = {
+ type: PropTypes.string.isRequired, // icon
+
+ };
+ return IconFont;
+}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/amContainer.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/amContainer.js
new file mode 100644
index 000000000..35715351d
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/amContainer.js
@@ -0,0 +1,13 @@
+import component from './index.js';
+import amManifest from './amManifest.js';
+import createFromIconfont from './IconFont';
+
+const getComponent = function () {
+ return Promise.resolve(component);
+};
+
+export default {
+ getComponent,
+ manifest: amManifest,
+ createFromIconfont,
+};
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/amManifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/amManifest.js
new file mode 100644
index 000000000..3af2f5c8c
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/amManifest.js
@@ -0,0 +1,82 @@
+/**
+ * The template of manifest for AiMake studio.
+ */
+const manifest = {
+ // The name of current component.
+ name: 'AIMakeIcon',
+ // The description of current component.
+ description: '图标',
+ // The coverimage's url of current component.
+ coverImage: '',
+ // The category of current component in AiMake studio.
+ // can be:
+ // `分栏` or `文本` or `按钮` or `标签` or `标签页` or `表格` or `单选` or `分割线`
+ // or `分页` or `复选` or `滑动条` or `进度条` or `卡片` or `开关` or `缺省状态`
+ // or `日期选择` or `输入框` or `搜索框` or `图表` or `图片` or `下拉选择` or `表单行`
+ // or `树控件` or `折叠面板` or `占位图`
+ category: 'AIMakeIcon',
+ // The preview list of current component in AiMake studio.
+ // Each preset contains following keys:
+ // - `alias`: string. required. The previewing component's name to display
+ // - `thumbnail`: string. not required. The previewing component's thumbnail
+ // - `customProps`: object. not required.
+ // The previewing component's customize props, e.g. { [propName]: [propValue] }
+ // - `colSpan`: number. not required. default 24 (1~24). The previewing component's size when to display
+ presets: [],
+ // Other settings of current component for AiMake studio.
+ settings: {
+ // The render type of current component in AiMake studio.
+ // can be:
+ // `element_inline` or `element_block` or `container`
+ type: 'element_inline',
+ // The insert mode of current component in AiMake studio.
+ // can be:
+ // one or combine of `t` and `b` and `r` and `l`
+ insertionModes: 'rl',
+ // The handle list of current component in AiMake studio.
+ // can be:
+ // an array contains one and more of ['cut', 'copy', 'paste', 'delete', 'duplicate']
+ handles: ['cut', 'copy', 'paste', 'delete', 'duplicate'],
+ // Whether the component can be actived.
+ shouldActive: true,
+ // Whether the component can be dragged.
+ shouldDrag: true,
+ // The props of current component in AiMake studio.
+ // Each property contains following keys:
+ // - `name`: string. required. The property's name
+ // - `label`: string. required. The property's name to display
+ // - `renderer`: string. required. The property's editor. can be: (@冰骊)
+ // - `defaultValue`: any. not required. The property's default value
+ // - `params`: any. not required. The parameters for property's editor
+ // - `placeholder`: string. not required. The placeholder for property's editor
+ // - `hint`: string. not required. The hint for property's editor
+ props: [{
+ name: 'margin',
+ label: '外边距',
+ renderer: 'Quadrant',
+ }, {
+ name: 'color',
+ label: '图标颜色',
+ renderer: 'Color',
+ defaultValue: '#333',
+ }, {
+ name: 'fontSize',
+ label: '图标大小',
+ renderer: 'FontSize',
+ defaultValue: '16px',
+ }, {
+ name: 'display',
+ label: '显示',
+ defaultValue: 'inline-block',
+ }, {
+ name: 'className',
+ label: '图标类型',
+ defaultValue: 'iconfont',
+ renderer: false,
+ params: {
+ placeholder: '请输入Iconfont名',
+ },
+ }],
+ },
+};
+export default manifest;
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/container.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/container.js
new file mode 100644
index 000000000..e272233de
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/container.js
@@ -0,0 +1,6 @@
+
+ import AIMakeIcon from './index.js';
+ import manifest from './manifest.js';
+
+ export default { origin: AIMakeIcon, manifest };
+
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/index.js
new file mode 100644
index 000000000..4007756a7
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/index.js
@@ -0,0 +1,71 @@
+import _extends from "@babel/runtime/helpers/extends";
+import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
+import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
+import _createClass from "@babel/runtime/helpers/createClass";
+import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
+import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
+import _inherits from "@babel/runtime/helpers/inherits";
+import _defineProperty from "@babel/runtime/helpers/defineProperty";
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import classNames from 'classnames';
+import createFromIconfont from './IconFont';
+
+const AIMakeIcon =
+/* #__PURE__ */
+function (_Component) {
+ _inherits(AIMakeIcon, _Component);
+
+ function AIMakeIcon() {
+ _classCallCheck(this, AIMakeIcon);
+
+ return _possibleConstructorReturn(this, _getPrototypeOf(AIMakeIcon).apply(this, arguments));
+ }
+
+ _createClass(AIMakeIcon, [{
+ key: "render",
+ value: function render() {
+ const _this$props = this.props;
+ const className = _this$props.className;
+ const iconClassName = _this$props.iconClassName;
+ const children = _this$props.children;
+ const styleBoxModel = _this$props.styleBoxModel;
+ const styleText = _this$props.styleText;
+ const styleBackground = _this$props.styleBackground;
+ const style = _this$props.style;
+ const otherProps = _objectWithoutProperties(_this$props, ["className", "iconClassName", "children", "styleBoxModel", "styleText", "styleBackground", "style"]);
+
+ const styles = { ...styleBoxModel,
+ ...styleText,
+ ...styleBackground,
+ ...style,
+ };
+ return React.createElement("i", _extends({}, otherProps, {
+ className: classNames(className, iconClassName),
+ style: styles,
+ }), children);
+ },
+ }]);
+
+ return AIMakeIcon;
+}(Component);
+
+_defineProperty(AIMakeIcon, "propTypes", {
+ className: PropTypes.string,
+ iconClassName: PropTypes.string,
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
+ styleBoxModel: PropTypes.object.isRequired,
+ styleText: PropTypes.object.isRequired,
+ styleBackground: PropTypes.object.isRequired,
+ style: PropTypes.object,
+});
+
+_defineProperty(AIMakeIcon, "defaultProps", {
+ className: '',
+ iconClassName: 'iconfont',
+ children: '',
+ style: {},
+});
+
+AIMakeIcon.createFromIconfont = createFromIconfont;
+export default AIMakeIcon;
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/manifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/manifest.js
new file mode 100644
index 000000000..cb0b26eab
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/manifest.js
@@ -0,0 +1 @@
+{"componentName":"AIMakeIcon","title":"","docUrl":"","screenshot":"","npm":{"package":"@ali/lowcode-engine-material-parser","version":"0.1.0","exportName":"AIMakeIcon","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[{"name":"className","propType":"string","description":""},{"name":"iconClassName","propType":"string","description":""},{"name":"children","propType":"oneOfType","description":""},{"name":"styleBoxModel","propType":"object","description":""},{"name":"styleText","propType":"object","description":""},{"name":"styleBackground","propType":"object","description":""},{"name":"style","propType":"object","description":"","defaultValue":"{}"}]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/manifest.json b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/manifest.json
new file mode 100644
index 000000000..13da88146
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/manifest.json
@@ -0,0 +1 @@
+{"title":"multiple-exported-component","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/amContainer.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/amContainer.js
new file mode 100644
index 000000000..45df1897e
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/amContainer.js
@@ -0,0 +1,11 @@
+import component from './index.js';
+import amManifest from './amManifest.js';
+
+const getComponent = function () {
+ return Promise.resolve(component);
+};
+
+export default {
+ getComponent,
+ manifest: amManifest,
+};
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/amManifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/amManifest.js
new file mode 100644
index 000000000..b5687bcf4
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/amManifest.js
@@ -0,0 +1,86 @@
+/**
+ * The template of manifest for AiMake studio.
+ */
+const manifest = {
+ // The name of current component.
+ name: 'AIMakeImage',
+ // The description of current component.
+ description: '图片',
+ // The coverimage's url of current component.
+ coverImage: 'https://img.alicdn.com/tfs/TB17gMFp1uSBuNjy1XcXXcYjFXa-172-120.png',
+ // The category of current component in AiMake studio.
+ // can be:
+ // `分栏` or `文本` or `按钮` or `标签` or `标签页` or `表格` or `单选` or `分割线`
+ // or `分页` or `复选` or `滑动条` or `进度条` or `卡片` or `开关` or `缺省状态`
+ // or `日期选择` or `输入框` or `搜索框` or `图表` or `图片` or `下拉选择` or `表单行`
+ // or `树控件` or `折叠面板` or `占位图`
+ category: '线条图像',
+ // The preview list of current component in AiMake studio.
+ // Each preset contains following keys:
+ // - `alias`: string. required. The previewing component's name to display
+ // - `thumbnail`: string. not required. The previewing component's thumbnail
+ // - `customProps`: object. not required.
+ // The previewing component's customize props, e.g. { [propName]: [propValue] }
+ // - `colSpan`: number. not required. default 24 (1~24). The previewing component's size when to display
+ presets: [{
+ alias: '图片',
+ thumbnail: 'https://img.alicdn.com/tfs/TB17gMFp1uSBuNjy1XcXXcYjFXa-172-120.png',
+ colSpan: 12,
+ customProps: {
+ width: '224px',
+ height: '126px',
+ src: 'https://img.alicdn.com/tfs/TB1RtEMGbSYBuNjSspfXXcZCpXa-448-252.png',
+ },
+ }],
+ // Other settings of current component for AiMake studio.
+ settings: {
+ // The render type of current component in AiMake studio.
+ // can be:
+ // `element_inline` or `element_block` or `container`
+ type: 'element_inline',
+ // The insert mode of current component in AiMake studio.
+ // can be:
+ // one or combine of `t` and `b` and `r` and `l`
+ insertionModes: 'rl',
+ // The handle list of current component in AiMake studio.
+ // can be:
+ // an array contains one and more of ['cut', 'copy', 'paste', 'delete', 'duplicate']
+ handles: ['cut', 'copy', 'paste', 'delete', 'duplicate'],
+ // Whether the component can be actived.
+ shouldActive: true,
+ // Whether the component can be dragged.
+ shouldDrag: true,
+ // The props of current component in AiMake studio.
+ // Each property contains following keys:
+ // - `name`: string. required. The property's name
+ // - `label`: string. required. The property's name to display
+ // - `renderer`: string. required. The property's editor. can be: (@冰骊)
+ // - `defaultValue`: any. not required. The property's default value
+ // - `params`: any. not required. The parameters for property's editor
+ // - `placeholder`: string. not required. The placeholder for property's editor
+ // - `hint`: string. not required. The hint for property's editor
+ props: [{
+ name: 'margin',
+ label: '外边距',
+ renderer: 'Quadrant',
+ }, {
+ name: 'width',
+ label: '宽度',
+ defaultValue: '224px',
+ renderer: 'Width',
+ }, {
+ name: 'height',
+ label: '高度',
+ defaultValue: '126px',
+ renderer: 'Height',
+ }, {
+ name: 'src',
+ label: '图片URL',
+ renderer: 'Uploader',
+ placeholder: 'eg: https://img.alicdn.com/tfs/TB1RtEMGbSYBuNjSspfXXcZCpXa-448-252.png',
+ hint: '请填入图片的URL',
+ defaultValue: 'https://img.alicdn.com/tfs/TB1RtEMGbSYBuNjSspfXXcZCpXa-448-252.png',
+ }],
+ },
+};
+export default manifest;
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/container.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/container.js
new file mode 100644
index 000000000..2c667964a
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/container.js
@@ -0,0 +1,6 @@
+
+ import AIMakeImage from './index.js';
+ import manifest from './manifest.js';
+
+ export default { origin: AIMakeImage, manifest };
+
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/index.js
new file mode 100644
index 000000000..8bf5ce2a8
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/index.js
@@ -0,0 +1,54 @@
+import _extends from "@babel/runtime/helpers/extends";
+import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
+import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
+import _createClass from "@babel/runtime/helpers/createClass";
+import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
+import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
+import _inherits from "@babel/runtime/helpers/inherits";
+import _defineProperty from "@babel/runtime/helpers/defineProperty";
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import HOCBoxModelProps from '../utils/HOCBoxModelProps';
+
+const AIMakeImage =
+/* #__PURE__ */
+function (_Component) {
+ _inherits(AIMakeImage, _Component);
+
+ function AIMakeImage() {
+ _classCallCheck(this, AIMakeImage);
+
+ return _possibleConstructorReturn(this, _getPrototypeOf(AIMakeImage).apply(this, arguments));
+ }
+
+ _createClass(AIMakeImage, [{
+ key: "render",
+ value: function render() {
+ const _this$props = this.props;
+ const styleBoxModel = _this$props.styleBoxModel;
+ const style = _this$props.style;
+ const otherProps = _objectWithoutProperties(_this$props, ["styleBoxModel", "style"]);
+
+ const styles = { ...styleBoxModel,
+ ...style,
+ };
+ return React.createElement("img", _extends({}, otherProps, {
+ style: styles,
+ alt: "AIMakeImage",
+ }));
+ },
+ }]);
+
+ return AIMakeImage;
+}(Component);
+
+_defineProperty(AIMakeImage, "propTypes", {
+ styleBoxModel: PropTypes.object.isRequired,
+ style: PropTypes.object,
+});
+
+_defineProperty(AIMakeImage, "defaultProps", {
+ style: {},
+});
+
+export default HOCBoxModelProps(AIMakeImage);
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/manifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/manifest.js
new file mode 100644
index 000000000..ea27808dc
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/manifest.js
@@ -0,0 +1 @@
+{"componentName":"AIMakeImage","title":"","docUrl":"","screenshot":"","npm":{"package":"@ali/lowcode-engine-material-parser","version":"0.1.0","exportName":"AIMakeImage","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[{"name":"styleBoxModel","propType":"object","description":""},{"name":"style","propType":"object","description":"","defaultValue":"{}"}]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/manifest.json b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/manifest.json
new file mode 100644
index 000000000..13da88146
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/manifest.json
@@ -0,0 +1 @@
+{"title":"multiple-exported-component","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/amContainer.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/amContainer.js
new file mode 100644
index 000000000..45df1897e
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/amContainer.js
@@ -0,0 +1,11 @@
+import component from './index.js';
+import amManifest from './amManifest.js';
+
+const getComponent = function () {
+ return Promise.resolve(component);
+};
+
+export default {
+ getComponent,
+ manifest: amManifest,
+};
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/amManifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/amManifest.js
new file mode 100644
index 000000000..c254b2cc4
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/amManifest.js
@@ -0,0 +1,102 @@
+/**
+ * The template of manifest for AiMake studio.
+ */
+const manifest = {
+ // The name of current component.
+ name: 'AIMakeLink',
+ // The description of current component.
+ description: '链接',
+ // The coverimage's url of current component.
+ coverImage: 'https://img.alicdn.com/tfs/TB1otbyVwTqK1RjSZPhXXXfOFXa-192-48.png',
+ // The category of current component in AiMake studio.
+ // can be:
+ // `分栏` or `文本` or `按钮` or `标签` or `标签页` or `表格` or `单选` or `分割线`
+ // or `分页` or `复选` or `滑动条` or `进度条` or `卡片` or `开关` or `缺省状态`
+ // or `日期选择` or `输入框` or `搜索框` or `图表` or `图片` or `下拉选择` or `表单行`
+ // or `树控件` or `折叠面板` or `占位图`
+ category: '文本',
+ // The preview list of current component in AiMake studio.
+ // Each preset contains following keys:
+ // - `alias`: string. required. The previewing component's name to display
+ // - `thumbnail`: string. not required. The previewing component's thumbnail
+ // - `customProps`: object. not required.
+ // The previewing component's customize props, e.g. { [propName]: [propValue] }
+ // - `colSpan`: number. not required. default 24 (1~24). The previewing component's size when to display
+ presets: [{
+ alias: '链接',
+ thumbnail: 'https://img.alicdn.com/tfs/TB1otbyVwTqK1RjSZPhXXXfOFXa-192-48.png',
+ colSpan: 12,
+ customProps: {
+ color: '#3788FF',
+ fontSize: '12px',
+ fontWeight: 'normal',
+ href: '#',
+ children: '链接',
+ },
+ }],
+ // Other settings of current component for AiMake studio.
+ settings: {
+ // The render type of current component in AiMake studio.
+ // can be:
+ // `element_inline` or `element_block` or `container`
+ type: 'element_inline',
+ // The insert mode of current component in AiMake studio.
+ // can be:
+ // one or combine of `t` and `b` and `r` and `l`
+ insertionModes: 'lrv',
+ // The handle list of current component in AiMake studio.
+ // can be:
+ // an array contains one and more of ['cut', 'copy', 'paste', 'delete', 'duplicate']
+ handles: ['cut', 'copy', 'paste', 'delete', 'duplicate'],
+ // Whether the component can be actived.
+ shouldActive: true,
+ // Whether the component can be dragged.
+ shouldDrag: true,
+ // The props of current component in AiMake studio.
+ // Each property contains following keys:
+ // - `name`: string. required. The property's name
+ // - `label`: string. required. The property's name to display
+ // - `renderer`: string. required. The property's editor. can be: (@冰骊)
+ // - `defaultValue`: any. not required. The property's default value
+ // - `params`: any. not required. The parameters for property's editor
+ // - `placeholder`: string. not required. The placeholder for property's editor
+ // - `hint`: string. not required. The hint for property's editor
+ props: [{
+ name: 'margin',
+ label: '外边距',
+ renderer: 'Quadrant',
+ }, {
+ name: 'color',
+ label: '文字颜色',
+ renderer: 'Color',
+ defaultValue: '#3788FF',
+ }, {
+ name: 'fontSize',
+ label: '字号',
+ renderer: 'FontSize',
+ defaultValue: '12px',
+ }, {
+ name: 'fontWeight',
+ label: '字重',
+ renderer: 'FontWeight',
+ defaultValue: 'normal',
+ }, {
+ name: 'lineHeight',
+ label: '行高',
+ defaultValue: undefined,
+ renderer: 'LineHeight',
+ }, {
+ name: 'href',
+ label: '链接URL',
+ renderer: 'Input',
+ placeholder: '请输入链接URL',
+ defaultValue: '#',
+ }, {
+ name: 'children',
+ label: '内容',
+ defaultValue: '链接',
+ renderer: 'TextArea',
+ }],
+ },
+};
+export default manifest;
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/container.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/container.js
new file mode 100644
index 000000000..472ec7f51
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/container.js
@@ -0,0 +1,6 @@
+
+ import AIMakeLink from './index.js';
+ import manifest from './manifest.js';
+
+ export default { origin: AIMakeLink, manifest };
+
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/index.js
new file mode 100644
index 000000000..ace8d9e94
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/index.js
@@ -0,0 +1,73 @@
+import _extends from "@babel/runtime/helpers/extends";
+import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
+import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
+import _createClass from "@babel/runtime/helpers/createClass";
+import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
+import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
+import _inherits from "@babel/runtime/helpers/inherits";
+import _defineProperty from "@babel/runtime/helpers/defineProperty";
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import HOCBoxModelProps from '../utils/HOCBoxModelProps';
+import HOCTextProps from '../utils/HOCTextProps';
+import HOCLayoutProps from '../utils/HOCLayoutProps';
+import HOCBackgroundProps from '../utils/HOCBackgroundProps';
+
+const AIMakeLink =
+/* #__PURE__ */
+function (_Component) {
+ _inherits(AIMakeLink, _Component);
+
+ function AIMakeLink() {
+ _classCallCheck(this, AIMakeLink);
+
+ return _possibleConstructorReturn(this, _getPrototypeOf(AIMakeLink).apply(this, arguments));
+ }
+
+ _createClass(AIMakeLink, [{
+ key: "render",
+ value: function render() {
+ const _this$props = this.props;
+ const children = _this$props.children;
+ const styleBoxModel = _this$props.styleBoxModel;
+ const styleText = _this$props.styleText;
+ const styleLayout = _this$props.styleLayout;
+ const styleBackground = _this$props.styleBackground;
+ const style = _this$props.style;
+ const otherProps = _objectWithoutProperties(_this$props, ["children", "styleBoxModel", "styleText", "styleLayout", "styleBackground", "style"]);
+
+ const styles = { ...styleBoxModel,
+ ...styleText,
+ ...styleLayout,
+ ...styleBackground,
+ ...style,
+ };
+
+ if (typeof children !== 'string') {
+ styles.display = 'inline-block';
+ }
+
+ return React.createElement("a", _extends({}, otherProps, {
+ style: styles,
+ }), [children]);
+ },
+ }]);
+
+ return AIMakeLink;
+}(Component);
+
+_defineProperty(AIMakeLink, "propTypes", {
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
+ styleBoxModel: PropTypes.object.isRequired,
+ styleText: PropTypes.object.isRequired,
+ styleLayout: PropTypes.object.isRequired,
+ styleBackground: PropTypes.object.isRequired,
+ style: PropTypes.object,
+});
+
+_defineProperty(AIMakeLink, "defaultProps", {
+ children: '',
+ style: {},
+});
+
+export default HOCBoxModelProps(HOCTextProps(HOCLayoutProps(HOCBackgroundProps(AIMakeLink))));
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/manifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/manifest.js
new file mode 100644
index 000000000..f5f08c322
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/manifest.js
@@ -0,0 +1 @@
+{"componentName":"AIMakeLink","title":"","docUrl":"","screenshot":"","npm":{"package":"@ali/lowcode-engine-material-parser","version":"0.1.0","exportName":"AIMakeLink","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[{"name":"children","propType":"oneOfType","description":""},{"name":"styleBoxModel","propType":"object","description":""},{"name":"styleText","propType":"object","description":""},{"name":"styleLayout","propType":"object","description":""},{"name":"styleBackground","propType":"object","description":""},{"name":"style","propType":"object","description":"","defaultValue":"{}"}]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/manifest.json b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/manifest.json
new file mode 100644
index 000000000..13da88146
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/manifest.json
@@ -0,0 +1 @@
+{"title":"multiple-exported-component","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/amContainer.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/amContainer.js
new file mode 100644
index 000000000..45df1897e
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/amContainer.js
@@ -0,0 +1,11 @@
+import component from './index.js';
+import amManifest from './amManifest.js';
+
+const getComponent = function () {
+ return Promise.resolve(component);
+};
+
+export default {
+ getComponent,
+ manifest: amManifest,
+};
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/amManifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/amManifest.js
new file mode 100644
index 000000000..bea679c5e
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/amManifest.js
@@ -0,0 +1,102 @@
+/**
+ * The template of manifest for AiMake studio.
+ */
+const manifest = {
+ // The name of current component.
+ name: 'AIMakePlaceholder',
+ // The description of current component.
+ description: '占位图',
+ // The coverimage's url of current component.
+ coverImage: 'https://img.alicdn.com/tfs/TB1RxDup3mTBuNjy1XbXXaMrVXa-362-120.png',
+ // The category of current component in AiMake studio.
+ // can be:
+ // `分栏` or `文本` or `按钮` or `标签` or `标签页` or `表格` or `单选` or `分割线`
+ // or `分页` or `复选` or `滑动条` or `进度条` or `卡片` or `开关` or `缺省状态`
+ // or `日期选择` or `输入框` or `搜索框` or `图表` or `图片` or `下拉选择` or `表单行`
+ // or `树控件` or `折叠面板` or `占位图`
+ category: '占位图',
+ // The preview list of current component in AiMake studio.
+ // Each preset contains following keys:
+ // - `alias`: string. required. The previewing component's name to display
+ // - `thumbnail`: string. not required. The previewing component's thumbnail
+ // - `customProps`: object. not required.
+ // The previewing component's customize props, e.g. { [propName]: [propValue] }
+ // - `colSpan`: number. not required. default 24 (1~24). The previewing component's size when to display
+ presets: [{
+ alias: '占位图',
+ thumbnail: 'https://img.alicdn.com/tfs/TB1RxDup3mTBuNjy1XbXXaMrVXa-362-120.png',
+ colSpan: 24,
+ customProps: {
+ width: '224px',
+ height: '126px',
+ backgroundColor: '#FFF6E0',
+ textAlign: 'center',
+ border: '1px dashed rgb(170, 170, 170)',
+ children: '暂不支持此组件',
+ },
+ }],
+ // Other settings of current component for AiMake studio.
+ settings: {
+ // The render type of current component in AiMake studio.
+ // can be:
+ // `element_inline` or `element_block` or `container`
+ type: 'element_inline',
+ // The insert mode of current component in AiMake studio.
+ // can be:
+ // one or combine of `t` and `b` and `r` and `l`
+ insertionModes: 'lr',
+ // The handle list of current component in AiMake studio.
+ // can be:
+ // an array contains one and more of ['cut', 'copy', 'paste', 'delete', 'duplicate']
+ handles: ['cut', 'copy', 'paste', 'delete', 'duplicate'],
+ // Whether the component can be actived.
+ shouldActive: true,
+ // Whether the component can be dragged.
+ shouldDrag: true,
+ // The props of current component in AiMake studio.
+ // Each property contains following keys:
+ // - `name`: string. required. The property's name
+ // - `label`: string. required. The property's name to display
+ // - `renderer`: string. required. The property's editor. can be: (@冰骊)
+ // - `defaultValue`: any. not required. The property's default value
+ // - `params`: any. not required. The parameters for property's editor
+ // - `placeholder`: string. not required. The placeholder for property's editor
+ // - `hint`: string. not required. The hint for property's editor
+ props: [{
+ name: 'margin',
+ label: '外边距',
+ renderer: 'Quadrant',
+ }, {
+ name: 'width',
+ label: '宽度',
+ defaultValue: '224px',
+ renderer: 'Width',
+ }, {
+ name: 'height',
+ label: '高度',
+ defaultValue: '126px',
+ renderer: 'Height',
+ }, {
+ name: 'backgroundColor',
+ label: '背景色',
+ defaultValue: '#FFF6E0',
+ renderer: false,
+ }, {
+ name: 'textAlign',
+ label: '对齐',
+ defaultValue: 'center',
+ renderer: false,
+ }, {
+ name: 'border',
+ label: '边框',
+ defaultValue: '1px dashed rgb(170, 170, 170)',
+ renderer: false,
+ }, {
+ name: 'children',
+ label: '内容',
+ defaultValue: '暂不支持此组件',
+ renderer: false,
+ }],
+ },
+};
+export default manifest;
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/container.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/container.js
new file mode 100644
index 000000000..58dfb2fc9
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/container.js
@@ -0,0 +1,6 @@
+
+ import AIMakePlaceholder from './index.js';
+ import manifest from './manifest.js';
+
+ export default { origin: AIMakePlaceholder, manifest };
+
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/index.js
new file mode 100644
index 000000000..509898874
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/index.js
@@ -0,0 +1,65 @@
+import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
+import _createClass from "@babel/runtime/helpers/createClass";
+import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
+import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
+import _inherits from "@babel/runtime/helpers/inherits";
+import _defineProperty from "@babel/runtime/helpers/defineProperty";
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import HOCBoxModelProps from '../utils/HOCBoxModelProps';
+import HOCLayoutProps from '../utils/HOCLayoutProps';
+
+const AIMakePlaceholder =
+/* #__PURE__ */
+function (_Component) {
+ _inherits(AIMakePlaceholder, _Component);
+
+ function AIMakePlaceholder() {
+ _classCallCheck(this, AIMakePlaceholder);
+
+ return _possibleConstructorReturn(this, _getPrototypeOf(AIMakePlaceholder).apply(this, arguments));
+ }
+
+ _createClass(AIMakePlaceholder, [{
+ key: "render",
+ value: function render() {
+ const _this$props = this.props;
+ const children = _this$props.children;
+ const styleBoxModel = _this$props.styleBoxModel;
+ const styleLayout = _this$props.styleLayout;
+ const style = _this$props.style;
+ const styles = { ...styleBoxModel,
+ ...styleLayout,
+ ...style,
+ };
+ const placeholderStyle = {
+ display: 'inline-block',
+ border: '1px dashed #aaa',
+ lineHeight: styles.height,
+ backgroundColor: '#F5E075',
+ overflow: 'hidden',
+ textAlign: 'center',
+ ...styles,
+ };
+ return React.createElement("div", {
+ style: placeholderStyle,
+ }, children);
+ },
+ }]);
+
+ return AIMakePlaceholder;
+}(Component);
+
+_defineProperty(AIMakePlaceholder, "propTypes", {
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
+ styleBoxModel: PropTypes.object.isRequired,
+ styleLayout: PropTypes.object.isRequired,
+ style: PropTypes.object,
+});
+
+_defineProperty(AIMakePlaceholder, "defaultProps", {
+ children: '',
+ style: {},
+});
+
+export default HOCBoxModelProps(HOCLayoutProps(AIMakePlaceholder));
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/manifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/manifest.js
new file mode 100644
index 000000000..022906cdd
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/manifest.js
@@ -0,0 +1 @@
+{"componentName":"AIMakePlaceholder","title":"","docUrl":"","screenshot":"","npm":{"package":"@ali/lowcode-engine-material-parser","version":"0.1.0","exportName":"AIMakePlaceholder","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[{"name":"children","propType":"oneOfType","description":""},{"name":"styleBoxModel","propType":"object","description":""},{"name":"styleLayout","propType":"object","description":""},{"name":"style","propType":"object","description":"","defaultValue":"{}"}]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/manifest.json b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/manifest.json
new file mode 100644
index 000000000..13da88146
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/manifest.json
@@ -0,0 +1 @@
+{"title":"multiple-exported-component","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/amContainer.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/amContainer.js
new file mode 100644
index 000000000..45df1897e
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/amContainer.js
@@ -0,0 +1,11 @@
+import component from './index.js';
+import amManifest from './amManifest.js';
+
+const getComponent = function () {
+ return Promise.resolve(component);
+};
+
+export default {
+ getComponent,
+ manifest: amManifest,
+};
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/amManifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/amManifest.js
new file mode 100644
index 000000000..96fb34d28
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/amManifest.js
@@ -0,0 +1,115 @@
+/**
+ * The template of manifest for AiMake studio.
+ */
+const manifest = {
+ // The name of current component.
+ name: 'AIMakeText',
+ // The description of current component.
+ description: '富文本',
+ // The coverimage's url of current component.
+ coverImage: 'https://img.alicdn.com/tfs/TB15R_xVzDpK1RjSZFrXXa78VXa-192-48.png',
+ // The category of current component in AiMake studio.
+ // can be:
+ // `分栏` or `文本` or `按钮` or `标签` or `标签页` or `表格` or `单选` or `分割线`
+ // or `分页` or `复选` or `滑动条` or `进度条` or `卡片` or `开关` or `缺省状态`
+ // or `日期选择` or `输入框` or `搜索框` or `图表` or `图片` or `下拉选择` or `表单行`
+ // or `树控件` or `折叠面板` or `占位图`
+ category: '文本',
+ // The preview list of current component in AiMake studio.
+ // Each preset contains following keys:
+ // - `alias`: string. required. The previewing component's name to display
+ // - `thumbnail`: string. not required. The previewing component's thumbnail
+ // - `customProps`: object. not required.
+ // The previewing component's customize props, e.g. { [propName]: [propValue] }
+ // - `colSpan`: number. not required. default 24 (1~24). The previewing component's size when to display
+ presets: [{
+ alias: '富文本',
+ thumbnail: 'https://img.alicdn.com/tfs/TB15R_xVzDpK1RjSZFrXXa78VXa-192-48.png',
+ colSpan: 12,
+ customProps: {
+ type: 'label',
+ fontSize: '12px',
+ fontWeight: 'normal',
+ children: '文本内容',
+ },
+ }],
+ // Other settings of current component for AiMake studio.
+ settings: {
+ // The render type of current component in AiMake studio.
+ // can be:
+ // `element_inline` or `element_block` or `container`
+ type: 'element_inline',
+ // The insert mode of current component in AiMake studio.
+ // can be:
+ // one or combine of `t` and `b` and `r` and `l`
+ insertionModes: 'tbrl',
+ // The handle list of current component in AiMake studio.
+ // can be:
+ // an array contains one and more of ['cut', 'copy', 'paste', 'delete', 'duplicate']
+ handles: ['cut', 'copy', 'paste', 'delete', 'duplicate'],
+ // Whether the component can be actived.
+ shouldActive: true,
+ // Whether the component can be dragged.
+ shouldDrag: true,
+ // The props of current component in AiMake studio.
+ // Each property contains following keys:
+ // - `name`: string. required. The property's name
+ // - `label`: string. required. The property's name to display
+ // - `renderer`: string. required. The property's editor. can be: (@冰骊)
+ // - `defaultValue`: any. not required. The property's default value
+ // - `params`: any. not required. The parameters for property's editor
+ // - `placeholder`: string. not required. The placeholder for property's editor
+ // - `hint`: string. not required. The hint for property's editor
+ props: [{
+ name: 'type',
+ label: '类型',
+ renderer: 'Select',
+ defaultValue: 'label',
+ params: [{
+ label: '一级标题',
+ value: 'h1',
+ }, {
+ label: '二级标题',
+ value: 'h2',
+ }, {
+ label: '三级标题',
+ value: 'h3',
+ }, {
+ label: '段落',
+ value: 'p',
+ }, {
+ label: '标签',
+ value: 'label',
+ }],
+ }, {
+ name: 'margin',
+ label: '外边距',
+ renderer: 'Quadrant',
+ }, {
+ name: 'color',
+ label: '文字颜色',
+ renderer: 'Color',
+ }, {
+ name: 'fontSize',
+ label: '字号',
+ renderer: 'FontSize',
+ defaultValue: '12px',
+ }, {
+ name: 'fontWeight',
+ label: '字重',
+ renderer: 'FontWeight',
+ defaultValue: 'normal',
+ }, {
+ name: 'lineHeight',
+ label: '行高',
+ defaultValue: undefined,
+ renderer: 'LineHeight',
+ }, {
+ name: 'children',
+ label: '内容',
+ defaultValue: '文本内容',
+ renderer: 'TextArea',
+ }],
+ },
+};
+export default manifest;
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/container.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/container.js
new file mode 100644
index 000000000..d93e430ad
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/container.js
@@ -0,0 +1,6 @@
+
+ import AIMakeText from './index.js';
+ import manifest from './manifest.js';
+
+ export default { origin: AIMakeText, manifest };
+
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/index.js
new file mode 100644
index 000000000..966b7c766
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/index.js
@@ -0,0 +1,95 @@
+import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
+import _createClass from "@babel/runtime/helpers/createClass";
+import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
+import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
+import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
+import _inherits from "@babel/runtime/helpers/inherits";
+import _defineProperty from "@babel/runtime/helpers/defineProperty";
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import HOCBoxModelProps from '../utils/HOCBoxModelProps';
+import HOCTextProps from '../utils/HOCTextProps';
+import HOCLayoutProps from '../utils/HOCLayoutProps';
+import HOCBackgroundProps from '../utils/HOCBackgroundProps';
+
+const AIMakeText =
+/* #__PURE__ */
+function (_Component) {
+ _inherits(AIMakeText, _Component);
+
+ function AIMakeText() {
+ let _this;
+
+ _classCallCheck(this, AIMakeText);
+
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ _this = _possibleConstructorReturn(this, _getPrototypeOf(AIMakeText).call(this, ...args));
+
+ _defineProperty(_assertThisInitialized(_this), "generateComponentType", function (componentType) {
+ const componentNameMap = {
+ h1: 'h1',
+ h2: 'h2',
+ h3: 'h3',
+ h4: 'h4',
+ h5: 'h5',
+ paragraph: 'p',
+ label: 'label',
+ };
+ return componentNameMap[componentType] || 'div';
+ });
+
+ return _this;
+ }
+
+ _createClass(AIMakeText, [{
+ key: "render",
+ value: function render() {
+ const _this$props = this.props;
+ const children = _this$props.children;
+ const type = _this$props.type;
+ const styleBoxModel = _this$props.styleBoxModel;
+ const styleText = _this$props.styleText;
+ const styleLayout = _this$props.styleLayout;
+ const styleBackground = _this$props.styleBackground;
+ const style = _this$props.style;
+ const styles = { ...styleBoxModel,
+ ...styleText,
+ ...styleLayout,
+ ...styleBackground,
+ ...style,
+ };
+ const Comp = this.generateComponentType(type);
+ const labelStyle = Comp === 'label' ? {
+ display: 'inline-block',
+ } : {};
+ return React.createElement(Comp, {
+ className: "AIMakeText",
+ style: Object.assign(labelStyle, styles),
+ }, [children]);
+ },
+ }]);
+
+ return AIMakeText;
+}(Component);
+
+_defineProperty(AIMakeText, "propTypes", {
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node, PropTypes.string]),
+ type: PropTypes.string,
+ styleBoxModel: PropTypes.object.isRequired,
+ styleText: PropTypes.object.isRequired,
+ styleLayout: PropTypes.object.isRequired,
+ styleBackground: PropTypes.object.isRequired,
+ style: PropTypes.object,
+});
+
+_defineProperty(AIMakeText, "defaultProps", {
+ children: '',
+ type: '',
+ // paragraph || label
+ style: {},
+});
+
+export default HOCBoxModelProps(HOCTextProps(HOCLayoutProps(HOCBackgroundProps(AIMakeText))));
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/manifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/manifest.js
new file mode 100644
index 000000000..d0d95a4d2
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/manifest.js
@@ -0,0 +1 @@
+{"componentName":"AIMakeText","title":"","docUrl":"","screenshot":"","npm":{"package":"@ali/lowcode-engine-material-parser","version":"0.1.0","exportName":"AIMakeText","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[{"name":"children","propType":"oneOfType","description":""},{"name":"type","propType":"string","description":""},{"name":"styleBoxModel","propType":"object","description":""},{"name":"styleText","propType":"object","description":""},{"name":"styleLayout","propType":"object","description":""},{"name":"styleBackground","propType":"object","description":""},{"name":"style","propType":"object","description":"","defaultValue":"{}"}]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/manifest.json b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/manifest.json
new file mode 100644
index 000000000..13da88146
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/manifest.json
@@ -0,0 +1 @@
+{"title":"multiple-exported-component","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/amContainer.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/amContainer.js
new file mode 100644
index 000000000..45df1897e
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/amContainer.js
@@ -0,0 +1,11 @@
+import component from './index.js';
+import amManifest from './amManifest.js';
+
+const getComponent = function () {
+ return Promise.resolve(component);
+};
+
+export default {
+ getComponent,
+ manifest: amManifest,
+};
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/amManifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/amManifest.js
new file mode 100644
index 000000000..8d79e974d
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/amManifest.js
@@ -0,0 +1,25 @@
+const manifest = {
+ name: 'Root',
+ description: '底板',
+ coverImage: '',
+ category: '',
+ presets: [],
+ settings: {
+ type: 'container',
+ insertionModes: 'v',
+ handles: ['paste'],
+ shouldActive: true,
+ shouldDrag: false,
+ props: [{
+ name: 'padding',
+ label: '内边距',
+ renderer: 'Quadrant',
+ }, {
+ name: 'backgroundColor',
+ label: '背景颜色',
+ defaultValue: '#F5F6FA',
+ renderer: 'Color',
+ }],
+ },
+};
+export default manifest;
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/container.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/container.js
new file mode 100644
index 000000000..8ee7fea70
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/container.js
@@ -0,0 +1,6 @@
+
+ import Root from './index.js';
+ import manifest from './manifest.js';
+
+ export default { origin: Root, manifest };
+
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/index.js
new file mode 100644
index 000000000..a86785522
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/index.js
@@ -0,0 +1,51 @@
+import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
+import _createClass from "@babel/runtime/helpers/createClass";
+import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
+import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
+import _inherits from "@babel/runtime/helpers/inherits";
+import _defineProperty from "@babel/runtime/helpers/defineProperty";
+import React from 'react';
+import PropTypes from 'prop-types';
+
+const Root =
+/* #__PURE__ */
+function (_React$Component) {
+ _inherits(Root, _React$Component);
+
+ function Root() {
+ _classCallCheck(this, Root);
+
+ return _possibleConstructorReturn(this, _getPrototypeOf(Root).apply(this, arguments));
+ }
+
+ _createClass(Root, [{
+ key: "render",
+ value: function render() {
+ const _this$props = this.props;
+ const style = _this$props.style;
+ const children = _this$props.children;
+ const newStyle = Object.assign({}, Root.defaultProps.style, style);
+ return React.createElement("div", {
+ style: newStyle,
+ }, children);
+ },
+ }]);
+
+ return Root;
+}(React.Component);
+
+_defineProperty(Root, "propTypes", {
+ style: PropTypes.object,
+ children: PropTypes.oneOfType([PropTypes.element, PropTypes.arrayOf(PropTypes.element)]),
+});
+
+_defineProperty(Root, "defaultProps", {
+ style: {
+ padding: 0,
+ backgroundColor: '#f0f2f5',
+ minHeight: '100%',
+ },
+ children: null,
+});
+
+export default Root;
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/manifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/manifest.js
new file mode 100644
index 000000000..756d388b2
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/manifest.js
@@ -0,0 +1 @@
+{"componentName":"Root","title":"","docUrl":"","screenshot":"","npm":{"package":"@ali/lowcode-engine-material-parser","version":"0.1.0","exportName":"Root","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[{"name":"style","propType":"object","description":"","defaultValue":"{\n padding: 0,\n backgroundColor: '#f0f2f5',\n minHeight: '100%'\n}"},{"name":"children","propType":"oneOfType","description":""}]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/manifest.json b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/manifest.json
new file mode 100644
index 000000000..13da88146
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/manifest.json
@@ -0,0 +1 @@
+{"title":"multiple-exported-component","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/style/index.css b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/style/index.css
new file mode 100644
index 000000000..8692a70c5
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/style/index.css
@@ -0,0 +1,15 @@
+.text-left {
+ text-align: left;
+}
+.text-right {
+ text-align: right;
+}
+.text-center {
+ text-align: center;
+}
+.text-justify {
+ text-align: justify;
+}
+.text-nowrap {
+ white-space: nowrap;
+}
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/style/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/style/index.js
new file mode 100644
index 000000000..4582418a4
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/style/index.js
@@ -0,0 +1 @@
+import "./index.css";
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/style/index.less b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/style/index.less
new file mode 100644
index 000000000..dc3680eb4
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/style/index.less
@@ -0,0 +1,8 @@
+// Alignment
+.text-left { text-align: left; }
+.text-right { text-align: right; }
+.text-center { text-align: center; }
+.text-justify { text-align: justify; }
+.text-nowrap { white-space: nowrap; }
+
+// BoxModel
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCBackgroundProps.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCBackgroundProps.js
new file mode 100644
index 000000000..6b4423a32
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCBackgroundProps.js
@@ -0,0 +1,74 @@
+import _extends from "@babel/runtime/helpers/extends";
+import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
+import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
+import _createClass from "@babel/runtime/helpers/createClass";
+import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
+import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
+import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
+import _inherits from "@babel/runtime/helpers/inherits";
+import _defineProperty from "@babel/runtime/helpers/defineProperty";
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+/**
+ * (HOC)注入背景相关属性配置
+ * 包含 'backgroundColor'
+ * @param {*} WrappedComponent
+ */
+
+const HOCBackgroundProps = function (WrappedComponent) {
+ let _class; let _temp;
+
+ const PROPS = {
+ backgroundColor: 'backgroundColor',
+ };
+ return _temp = _class =
+ /* #__PURE__ */
+ function (_Component) {
+ _inherits(_class, _Component);
+
+ function _class() {
+ let _this;
+
+ _classCallCheck(this, _class);
+
+ for (var _len = arguments.length, _args = new Array(_len), _key = 0; _key < _len; _key++) {
+ _args[_key] = arguments[_key];
+ }
+
+ _this = _possibleConstructorReturn(this, _getPrototypeOf(_class).call(this, ..._args));
+
+ _defineProperty(_assertThisInitialized(_this), "parseStyle", function (args) {
+ const style = {};
+ Object.keys(PROPS).forEach(function (item) {
+ // if props isn't false
+ if (!args[item]) return;
+ style[PROPS[item]] = args[item];
+ });
+ return style;
+ });
+
+ return _this;
+ }
+
+ _createClass(_class, [{
+ key: "render",
+ value: function render() {
+ const _this$props = this.props;
+ const backgroundColor = _this$props.backgroundColor;
+ const otherProps = _objectWithoutProperties(_this$props, ["backgroundColor"]);
+
+ return React.createElement(WrappedComponent, _extends({}, otherProps, {
+ styleBackground: this.parseStyle(this.props),
+ }));
+ },
+ }]);
+
+ return _class;
+ }(Component), _defineProperty(_class, "propTypes", {
+ backgroundColor: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ }), _defineProperty(_class, "defaultProps", {
+ backgroundColor: false,
+ }), _temp;
+};
+
+export default HOCBackgroundProps;
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCBoxModelProps.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCBoxModelProps.js
new file mode 100644
index 000000000..d710488e7
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCBoxModelProps.js
@@ -0,0 +1,103 @@
+import _extends from "@babel/runtime/helpers/extends";
+import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
+import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
+import _createClass from "@babel/runtime/helpers/createClass";
+import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
+import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
+import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
+import _inherits from "@babel/runtime/helpers/inherits";
+import _defineProperty from "@babel/runtime/helpers/defineProperty";
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+const parseJoin = function (value) {
+ return value.join(' ');
+};
+/**
+ * (HOC)注入盒子模型相关属性配置
+ * 包含 'display', 'margin', 'border', 'padding', 'width', 'height', 'borderRadius'
+ * @param {*} WrappedComponent
+ */
+
+
+const HOCBoxModelProps = function (WrappedComponent) {
+ let _class; let _temp;
+
+ const PROPS = {
+ display: 'display',
+ margin: 'margin',
+ border: 'border',
+ padding: 'padding',
+ width: 'width',
+ height: 'height',
+ borderRadius: 'borderRadius',
+ };
+ return _temp = _class =
+ /* #__PURE__ */
+ function (_Component) {
+ _inherits(_class, _Component);
+
+ function _class() {
+ let _this;
+
+ _classCallCheck(this, _class);
+
+ for (var _len = arguments.length, _args = new Array(_len), _key = 0; _key < _len; _key++) {
+ _args[_key] = arguments[_key];
+ }
+
+ _this = _possibleConstructorReturn(this, _getPrototypeOf(_class).call(this, ..._args));
+
+ _defineProperty(_assertThisInitialized(_this), "parseStyle", function (args) {
+ const style = {};
+ Object.keys(PROPS).forEach(function (item) {
+ // if props isn't false
+ if (!args[item]) return;
+ style[PROPS[item]] = Array.isArray(args[item]) ? parseJoin(args[item]) : args[item];
+ });
+ return style;
+ });
+
+ return _this;
+ }
+
+ _createClass(_class, [{
+ key: "render",
+ value: function render() {
+ const _this$props = this.props;
+ const display = _this$props.display;
+ const margin = _this$props.margin;
+ const border = _this$props.border;
+ const padding = _this$props.padding;
+ const width = _this$props.width;
+ const height = _this$props.height;
+ const borderRadius = _this$props.borderRadius;
+ const otherProps = _objectWithoutProperties(_this$props, ["display", "margin", "border", "padding", "width", "height", "borderRadius"]);
+
+ return React.createElement(WrappedComponent, _extends({}, otherProps, {
+ styleBoxModel: this.parseStyle(this.props),
+ }));
+ },
+ }]);
+
+ return _class;
+ }(Component), _defineProperty(_class, "propTypes", {
+ display: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ margin: PropTypes.oneOfType([PropTypes.array, PropTypes.bool]),
+ border: PropTypes.oneOfType([PropTypes.array, PropTypes.bool]),
+ padding: PropTypes.oneOfType([PropTypes.array, PropTypes.bool]),
+ width: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ height: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ borderRadius: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ }), _defineProperty(_class, "defaultProps", {
+ display: false,
+ margin: false,
+ border: false,
+ padding: false,
+ width: false,
+ height: false,
+ borderRadius: false,
+ }), _temp;
+};
+
+export default HOCBoxModelProps;
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCFlexLayoutProps.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCFlexLayoutProps.js
new file mode 100644
index 000000000..684a4f2f3
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCFlexLayoutProps.js
@@ -0,0 +1,90 @@
+import _extends from "@babel/runtime/helpers/extends";
+import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
+import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
+import _createClass from "@babel/runtime/helpers/createClass";
+import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
+import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
+import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
+import _inherits from "@babel/runtime/helpers/inherits";
+import _defineProperty from "@babel/runtime/helpers/defineProperty";
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+/**
+ * (HOC)注入flex布局相关属性配置
+ * 包含 'alignItems', 'justifyContent', 'flexDirection'
+ * @param {*} WrappedComponent
+ */
+
+const HOCFlexLayoutProps = function (WrappedComponent) {
+ let _class; let _temp;
+
+ const PROPS = {
+ alignItems: 'alignItems',
+ justifyContent: 'justifyContent',
+ flexDirection: 'flexDirection',
+ flexWrap: 'flexWrap',
+ };
+ return _temp = _class =
+ /* #__PURE__ */
+ function (_Component) {
+ _inherits(_class, _Component);
+
+ function _class() {
+ let _this;
+
+ _classCallCheck(this, _class);
+
+ for (var _len = arguments.length, _args = new Array(_len), _key = 0; _key < _len; _key++) {
+ _args[_key] = arguments[_key];
+ }
+
+ _this = _possibleConstructorReturn(this, _getPrototypeOf(_class).call(this, ..._args));
+
+ _defineProperty(_assertThisInitialized(_this), "parseStyle", function (args) {
+ const style = {};
+
+ if (args.style && args.style.display === 'flex') {
+ Object.keys(PROPS).forEach(function (item) {
+ // if props isn't false
+ if (!args[item]) return;
+ style[PROPS[item]] = args[item];
+ });
+ }
+
+ return style;
+ });
+
+ return _this;
+ }
+
+ _createClass(_class, [{
+ key: "render",
+ value: function render() {
+ const _this$props = this.props;
+ const alignItems = _this$props.alignItems;
+ const justifyContent = _this$props.justifyContent;
+ const flexDirection = _this$props.flexDirection;
+ const flexWrap = _this$props.flexWrap;
+ const otherProps = _objectWithoutProperties(_this$props, ["alignItems", "justifyContent", "flexDirection", "flexWrap"]);
+
+ return React.createElement(WrappedComponent, _extends({}, otherProps, {
+ styleFlexLayout: this.parseStyle(this.props),
+ }));
+ },
+ }]);
+
+ return _class;
+ }(Component), _defineProperty(_class, "propTypes", {
+ alignItems: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ justifyContent: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ flexDirection: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ flexWrap: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ }), _defineProperty(_class, "defaultProps", {
+ alignItems: false,
+ justifyContent: false,
+ flexDirection: false,
+ flexWrap: false,
+ }), _temp;
+};
+
+export default HOCFlexLayoutProps;
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCLayoutProps.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCLayoutProps.js
new file mode 100644
index 000000000..4710d093a
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCLayoutProps.js
@@ -0,0 +1,82 @@
+import _extends from "@babel/runtime/helpers/extends";
+import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
+import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
+import _createClass from "@babel/runtime/helpers/createClass";
+import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
+import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
+import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
+import _inherits from "@babel/runtime/helpers/inherits";
+import _defineProperty from "@babel/runtime/helpers/defineProperty";
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+/**
+ * (HOC)注入布局相关属性配置
+ * 包含 'align', 'lineHeight', 'verticalAlign'
+ * @param {*} WrappedComponent
+ */
+
+const HOCLayoutProps = function (WrappedComponent) {
+ let _class; let _temp;
+
+ const PROPS = {
+ align: 'textAlign',
+ lineHeight: 'lineHeight',
+ verticalAlign: 'verticalAlign',
+ };
+ return _temp = _class =
+ /* #__PURE__ */
+ function (_Component) {
+ _inherits(_class, _Component);
+
+ function _class() {
+ let _this;
+
+ _classCallCheck(this, _class);
+
+ for (var _len = arguments.length, _args = new Array(_len), _key = 0; _key < _len; _key++) {
+ _args[_key] = arguments[_key];
+ }
+
+ _this = _possibleConstructorReturn(this, _getPrototypeOf(_class).call(this, ..._args));
+
+ _defineProperty(_assertThisInitialized(_this), "parseStyle", function (args) {
+ const style = {};
+ Object.keys(PROPS).forEach(function (item) {
+ // if props isn't false
+ if (!args[item]) return;
+ style[PROPS[item]] = args[item];
+ });
+ return style;
+ });
+
+ return _this;
+ }
+
+ _createClass(_class, [{
+ key: "render",
+ value: function render() {
+ const _this$props = this.props;
+ const align = _this$props.align;
+ const lineHeight = _this$props.lineHeight;
+ const verticalAlign = _this$props.verticalAlign;
+ const otherProps = _objectWithoutProperties(_this$props, ["align", "lineHeight", "verticalAlign"]);
+
+ return React.createElement(WrappedComponent, _extends({}, otherProps, {
+ styleLayout: this.parseStyle(this.props),
+ }));
+ },
+ }]);
+
+ return _class;
+ }(Component), _defineProperty(_class, "propTypes", {
+ align: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ lineHeight: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ verticalAlign: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ }), _defineProperty(_class, "defaultProps", {
+ align: false,
+ lineHeight: false,
+ verticalAlign: false,
+ }), _temp;
+};
+
+export default HOCLayoutProps;
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCTextProps.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCTextProps.js
new file mode 100644
index 000000000..fb685d23a
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCTextProps.js
@@ -0,0 +1,82 @@
+import _extends from "@babel/runtime/helpers/extends";
+import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
+import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
+import _createClass from "@babel/runtime/helpers/createClass";
+import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
+import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
+import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
+import _inherits from "@babel/runtime/helpers/inherits";
+import _defineProperty from "@babel/runtime/helpers/defineProperty";
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+/**
+ * (HOC)注入文本相关属性配置
+ * 包含 'fontSize', 'fontWeight', 'color'
+ * @param {*} WrappedComponent
+ */
+
+const HOCTextProps = function (WrappedComponent) {
+ let _class; let _temp;
+
+ const PROPS = {
+ fontSize: 'fontSize',
+ fontWeight: 'fontWeight',
+ color: 'color',
+ };
+ return _temp = _class =
+ /* #__PURE__ */
+ function (_Component) {
+ _inherits(_class, _Component);
+
+ function _class() {
+ let _this;
+
+ _classCallCheck(this, _class);
+
+ for (var _len = arguments.length, _args = new Array(_len), _key = 0; _key < _len; _key++) {
+ _args[_key] = arguments[_key];
+ }
+
+ _this = _possibleConstructorReturn(this, _getPrototypeOf(_class).call(this, ..._args));
+
+ _defineProperty(_assertThisInitialized(_this), "parseStyle", function (args) {
+ const style = {};
+ Object.keys(PROPS).forEach(function (item) {
+ // if props isn't false
+ if (!args[item]) return;
+ style[PROPS[item]] = args[item];
+ });
+ return style;
+ });
+
+ return _this;
+ }
+
+ _createClass(_class, [{
+ key: "render",
+ value: function render() {
+ const _this$props = this.props;
+ const fontSize = _this$props.fontSize;
+ const fontWeight = _this$props.fontWeight;
+ const color = _this$props.color;
+ const otherProps = _objectWithoutProperties(_this$props, ["fontSize", "fontWeight", "color"]);
+
+ return React.createElement(WrappedComponent, _extends({}, otherProps, {
+ styleText: this.parseStyle(this.props),
+ }));
+ },
+ }]);
+
+ return _class;
+ }(Component), _defineProperty(_class, "propTypes", {
+ fontSize: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ fontWeight: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ color: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ }), _defineProperty(_class, "defaultProps", {
+ fontSize: false,
+ fontWeight: false,
+ color: false,
+ }), _temp;
+};
+
+export default HOCTextProps;
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js
new file mode 100644
index 000000000..aebb56067
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js
@@ -0,0 +1,9 @@
+import AIMakeBlank from './basic/AIMakeBlank';
+import AIMakeIcon from './basic/AIMakeIcon';
+import AIMakeImage from './basic/AIMakeImage';
+import AIMakeLink from './basic/AIMakeLink';
+import AIMakePlaceholder from './basic/AIMakePlaceholder';
+import AIMakeText from './basic/AIMakeText';
+import Root from './basic/Root';
+
+export { AIMakeBlank, AIMakeIcon, AIMakeImage, AIMakeLink, AIMakePlaceholder, AIMakeText, Root };
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/package.json b/packages/material-parser/test/fixtures/multiple-exported-component/package.json
new file mode 100644
index 000000000..e9e7c8b11
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "multiple-exported-component",
+ "description": "提供最基础、通用的物料组件",
+ "version": "1.0.0",
+ "main": "es/index.js",
+ "module": "es/index.js",
+ "dependencies": {
+ "classnames": "^2.2.6",
+ "prop-types": "^15.7.2",
+ "react": "^16.8.5",
+ "react-dom": "^16.8.5"
+ },
+ "devDependencies": {
+ "cross-spawn": "^6.0.5"
+ },
+ "peerDependencies": {
+ "react": "^16.8.6"
+ },
+ "publishConfig": {
+ "registry": "https://registry.npm.alibaba-inc.com"
+ }
+}
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/amContainer.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/amContainer.js
new file mode 100644
index 000000000..1eccfe080
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/amContainer.js
@@ -0,0 +1,6 @@
+import component from './index.js';
+import amManifest from './amManifest.js';
+
+const getComponent = () => Promise.resolve(component);
+
+export default { getComponent, manifest: amManifest };
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/amManifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/amManifest.js
new file mode 100644
index 000000000..66bb458d8
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/amManifest.js
@@ -0,0 +1,158 @@
+/**
+ * The template of manifest for AiMake studio.
+ */
+
+function _update(Nygma, node) {
+ const attributes = node.get();
+ const {
+ display,
+ flexDirection,
+ alignItems,
+ justifyContent,
+ flexWrap,
+ } = attributes;
+ const isFlex = display === 'flex';
+ node.set({
+ display,
+ flexDirection: isFlex ? flexDirection : undefined,
+ alignItems: isFlex ? alignItems : undefined,
+ justifyContent: isFlex ? justifyContent : undefined,
+ flexWrap: isFlex ? flexWrap : undefined,
+ });
+}
+
+const manifest = {
+ // The name of current component.
+ name: 'AIMakeBlank',
+ // The description of current component.
+ description: '空白卡片',
+ // The coverimage's url of current component.
+ coverImage:
+ 'https://img.alicdn.com/tfs/TB1un9tqntYBeNjy1XdXXXXyVXa-366-124.png',
+ // The category of current component in AiMake studio.
+ // can be:
+ // `分栏` or `文本` or `按钮` or `标签` or `标签页` or `表格` or `单选` or `分割线`
+ // or `分页` or `复选` or `滑动条` or `进度条` or `卡片` or `开关` or `缺省状态`
+ // or `日期选择` or `输入框` or `搜索框` or `图表` or `图片` or `下拉选择` or `表单行`
+ // or `树控件` or `折叠面板` or `占位图`
+ category: '布局', // card.blank
+ // The preview list of current component in AiMake studio.
+ // Each preset contains following keys:
+ // - `alias`: string. required. The previewing component's name to display
+ // - `thumbnail`: string. not required. The previewing component's thumbnail
+ // - `customProps`: object. not required.
+ // The previewing component's customize props, e.g. { [propName]: [propValue] }
+ // - `colSpan`: number. not required. default 24 (1~24). The previewing component's size when to display
+ presets: [
+ {
+ alias: '空白卡片',
+ thumbnail:
+ 'https://img.alicdn.com/tfs/TB1ucPNVsbpK1RjSZFyXXX_qFXa-198-120.png',
+ colSpan: 12,
+ customProps: {
+ id: '',
+ textAlign: 'left',
+ padding: '12px',
+ width: '100%',
+ backgroundColor: '#FFF',
+ },
+ },
+ ],
+ // Other settings of current component for AiMake studio.
+ settings: {
+ // The render type of current component in AiMake studio.
+ // can be:
+ // `element_inline` or `element_block` or `container`
+ type: 'container',
+ // The insert mode of current component in AiMake studio.
+ // can be:
+ // one or combine of `t` and `b` and `r` and `l`
+ insertionModes: 'tbrlv',
+ // The handle list of current component in AiMake studio.
+ // can be:
+ // an array contains one and more of ['cut', 'copy', 'paste', 'delete', 'duplicate']
+ handles: ['cut', 'copy', 'paste', 'delete', 'duplicate'],
+ // Whether the component can be actived.
+ shouldActive: true,
+ // Whether the component can be dragged.
+ shouldDrag: true,
+ lifeCycle: {
+ didMount: (props) => {
+ const { Nygma, dragInstance } = props;
+ const Drager = dragInstance.NygmaNode;
+ _update(Nygma, Drager);
+ },
+ didUpdate: (Nygma, node, args) => {
+ const newvalue = args[1];
+ const oldvalue = args[2];
+ if (JSON.stringify(newvalue) !== JSON.stringify(oldvalue)) {
+ _update(Nygma, node);
+ }
+ },
+ },
+ // The props of current component in AiMake studio.
+ // Each property contains following keys:
+ // - `name`: string. required. The property's name
+ // - `label`: string. required. The property's name to display
+ // - `renderer`: string. required. The property's editor. can be: (@冰骊)
+ // - `defaultValue`: any. not required. The property's default value
+ // - `params`: any. not required. The parameters for property's editor
+ // - `placeholder`: string. not required. The placeholder for property's editor
+ // - `hint`: string. not required. The hint for property's editor
+ props: [
+ {
+ name: 'id',
+ label: 'id',
+ defaultValue: '',
+ renderer: 'Input',
+ },
+ {
+ name: 'textAlign',
+ label: '水平对齐',
+ defaultValue: 'left',
+ renderer: 'TextAlign',
+ },
+ {
+ name: 'margin',
+ label: '外边距',
+ renderer: 'Quadrant',
+ },
+ {
+ name: 'padding',
+ label: '内边距',
+ renderer: 'Quadrant',
+ defaultValue: '12px',
+ },
+ {
+ name: 'width',
+ label: '宽度',
+ defaultValue: '100%',
+ renderer: 'Width',
+ },
+ {
+ name: 'height',
+ label: '高度',
+ renderer: 'Height',
+ defaultValue: undefined,
+ },
+ {
+ name: 'backgroundColor',
+ label: '背景颜色',
+ renderer: 'Color',
+ defaultValue: '#FFF',
+ },
+ {
+ name: 'border',
+ label: '边框',
+ renderer: 'BarBorder',
+ },
+ {
+ name: 'display',
+ label: '布局设置',
+ renderer: 'FlexLayout',
+ },
+ ],
+ },
+};
+
+export default manifest;
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/container.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/container.js
new file mode 100644
index 000000000..27019261b
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/container.js
@@ -0,0 +1,5 @@
+
+import AIMakeBlank from '../../../es/basic/AIMakeBlank/index.js';
+import manifest from './manifest.js';
+
+export default { origin: AIMakeBlank, manifest };
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/index.js
new file mode 100644
index 000000000..119989604
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/index.js
@@ -0,0 +1,61 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+import HOCBoxModelProps from '../utils/HOCBoxModelProps';
+import HOCLayoutProps from '../utils/HOCLayoutProps';
+import HOCBackgroundProps from '../utils/HOCBackgroundProps';
+import HOCFlexLayoutProps from '../utils/HOCFlexLayoutProps';
+
+class AIMakeBlank extends Component {
+ static propTypes = {
+ children: PropTypes.oneOfType([
+ PropTypes.arrayOf(PropTypes.node),
+ PropTypes.node,
+ ]),
+ styleBoxModel: PropTypes.object.isRequired,
+ styleLayout: PropTypes.object.isRequired,
+ styleBackground: PropTypes.object.isRequired,
+ styleFlexLayout: PropTypes.object.isRequired,
+ style: PropTypes.object,
+ id: PropTypes.string,
+ };
+
+ static defaultProps = {
+ children: [],
+ style: {},
+ id: '',
+ };
+
+ render() {
+ const merged = {};
+ const {
+ children,
+ styleBoxModel,
+ styleLayout,
+ styleBackground,
+ styleFlexLayout,
+ style,
+ id,
+ } = this.props;
+
+ const styles = {
+ ...styleBoxModel,
+ ...styleLayout,
+ ...styleBackground,
+ ...styleFlexLayout,
+ ...style,
+ };
+ if (id) {
+ merged.id = id;
+ }
+ return (
+
+ {children}
+
+ );
+ }
+}
+
+export default HOCBoxModelProps(
+ HOCLayoutProps(HOCBackgroundProps(HOCFlexLayoutProps(AIMakeBlank))),
+);
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/manifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/manifest.js
new file mode 100644
index 000000000..17c6c16d0
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/manifest.js
@@ -0,0 +1 @@
+{"componentName":"AIMakeBlank","title":"","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"AIMakeBlank","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[{"name":"children","propType":"oneOfType","description":""},{"name":"styleBoxModel","propType":"object","description":""},{"name":"styleLayout","propType":"object","description":""},{"name":"styleBackground","propType":"object","description":""},{"name":"styleFlexLayout","propType":"object","description":""},{"name":"style","propType":"object","description":"","defaultValue":"{}"},{"name":"id","propType":"string","description":""}]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/manifest.json b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/manifest.json
new file mode 100644
index 000000000..13da88146
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/manifest.json
@@ -0,0 +1 @@
+{"title":"multiple-exported-component","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/IconFont.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/IconFont.js
new file mode 100644
index 000000000..e0f766754
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/IconFont.js
@@ -0,0 +1,51 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+// 缓存已加载的字体文件
+const customCache = new Set();
+
+// 动态加载字体文件
+export default function createFromIconfont(options) {
+ const { scriptUrl } = options;
+ if (
+ typeof document !== 'undefined'
+ && typeof window !== 'undefined'
+ && typeof document.createElement === 'function'
+ && typeof scriptUrl === 'string'
+ && scriptUrl.length
+ && !customCache.has(scriptUrl)
+ ) {
+ const script = document.createElement('script');
+ script.setAttribute('src', scriptUrl);
+ script.setAttribute('data-namespace', scriptUrl);
+ customCache.add(scriptUrl);
+ document.body.appendChild(script);
+ }
+
+ class IconFont extends Component {
+ render() {
+ const { type, ...restProps } = this.props;
+ const innerSvgProps = {
+ width: '1em',
+ height: '1em',
+ fill: 'currentColor',
+ 'aria-hidden': 'true',
+ focusable: 'false',
+ };
+ // 引用指定svg
+ const content = ;
+
+ return (
+
+
+
+ );
+ }
+ }
+
+ IconFont.propTypes = {
+ type: PropTypes.string.isRequired, // icon
+ };
+
+ return IconFont;
+}
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/amContainer.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/amContainer.js
new file mode 100644
index 000000000..98b0a9687
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/amContainer.js
@@ -0,0 +1,7 @@
+import component from './index.js';
+import amManifest from './amManifest.js';
+import createFromIconfont from './IconFont';
+
+const getComponent = () => Promise.resolve(component);
+
+export default { getComponent, manifest: amManifest, createFromIconfont };
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/amManifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/amManifest.js
new file mode 100644
index 000000000..ae1354fc3
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/amManifest.js
@@ -0,0 +1,89 @@
+/**
+ * The template of manifest for AiMake studio.
+ */
+const manifest = {
+ // The name of current component.
+ name: 'AIMakeIcon',
+ // The description of current component.
+ description: '图标',
+ // The coverimage's url of current component.
+ coverImage: '',
+ // The category of current component in AiMake studio.
+ // can be:
+ // `分栏` or `文本` or `按钮` or `标签` or `标签页` or `表格` or `单选` or `分割线`
+ // or `分页` or `复选` or `滑动条` or `进度条` or `卡片` or `开关` or `缺省状态`
+ // or `日期选择` or `输入框` or `搜索框` or `图表` or `图片` or `下拉选择` or `表单行`
+ // or `树控件` or `折叠面板` or `占位图`
+ category: 'AIMakeIcon',
+ // The preview list of current component in AiMake studio.
+ // Each preset contains following keys:
+ // - `alias`: string. required. The previewing component's name to display
+ // - `thumbnail`: string. not required. The previewing component's thumbnail
+ // - `customProps`: object. not required.
+ // The previewing component's customize props, e.g. { [propName]: [propValue] }
+ // - `colSpan`: number. not required. default 24 (1~24). The previewing component's size when to display
+ presets: [],
+ // Other settings of current component for AiMake studio.
+ settings: {
+ // The render type of current component in AiMake studio.
+ // can be:
+ // `element_inline` or `element_block` or `container`
+ type: 'element_inline',
+ // The insert mode of current component in AiMake studio.
+ // can be:
+ // one or combine of `t` and `b` and `r` and `l`
+ insertionModes: 'rl',
+ // The handle list of current component in AiMake studio.
+ // can be:
+ // an array contains one and more of ['cut', 'copy', 'paste', 'delete', 'duplicate']
+ handles: ['cut', 'copy', 'paste', 'delete', 'duplicate'],
+ // Whether the component can be actived.
+ shouldActive: true,
+ // Whether the component can be dragged.
+ shouldDrag: true,
+ // The props of current component in AiMake studio.
+ // Each property contains following keys:
+ // - `name`: string. required. The property's name
+ // - `label`: string. required. The property's name to display
+ // - `renderer`: string. required. The property's editor. can be: (@冰骊)
+ // - `defaultValue`: any. not required. The property's default value
+ // - `params`: any. not required. The parameters for property's editor
+ // - `placeholder`: string. not required. The placeholder for property's editor
+ // - `hint`: string. not required. The hint for property's editor
+ props: [
+ {
+ name: 'margin',
+ label: '外边距',
+ renderer: 'Quadrant',
+ },
+ {
+ name: 'color',
+ label: '图标颜色',
+ renderer: 'Color',
+ defaultValue: '#333',
+ },
+ {
+ name: 'fontSize',
+ label: '图标大小',
+ renderer: 'FontSize',
+ defaultValue: '16px',
+ },
+ {
+ name: 'display',
+ label: '显示',
+ defaultValue: 'inline-block',
+ },
+ {
+ name: 'className',
+ label: '图标类型',
+ defaultValue: 'iconfont',
+ renderer: false,
+ params: {
+ placeholder: '请输入Iconfont名',
+ },
+ },
+ ],
+ },
+};
+
+export default manifest;
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/container.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/container.js
new file mode 100644
index 000000000..d626b63fe
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/container.js
@@ -0,0 +1,5 @@
+
+import AIMakeIcon from '../../../es/basic/AIMakeIcon/index.js';
+import manifest from './manifest.js';
+
+export default { origin: AIMakeIcon, manifest };
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/index.js
new file mode 100644
index 000000000..83dd1e910
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/index.js
@@ -0,0 +1,59 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import classNames from 'classnames';
+
+import createFromIconfont from './IconFont';
+
+class AIMakeIcon extends Component {
+ static propTypes = {
+ className: PropTypes.string,
+ iconClassName: PropTypes.string,
+ children: PropTypes.oneOfType([
+ PropTypes.arrayOf(PropTypes.node),
+ PropTypes.node,
+ ]),
+ styleBoxModel: PropTypes.object.isRequired,
+ styleText: PropTypes.object.isRequired,
+ styleBackground: PropTypes.object.isRequired,
+ style: PropTypes.object,
+ };
+
+ static defaultProps = {
+ className: '',
+ iconClassName: 'iconfont',
+ children: '',
+ style: {},
+ };
+
+ render() {
+ const {
+ className,
+ iconClassName,
+ children,
+ styleBoxModel,
+ styleText,
+ styleBackground,
+ style,
+ ...otherProps
+ } = this.props;
+ const styles = {
+ ...styleBoxModel,
+ ...styleText,
+ ...styleBackground,
+ ...style,
+ };
+ return (
+
+ {children}
+
+ );
+ }
+}
+
+AIMakeIcon.createFromIconfont = createFromIconfont;
+
+export default AIMakeIcon;
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/manifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/manifest.js
new file mode 100644
index 000000000..21824462a
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/manifest.js
@@ -0,0 +1 @@
+{"componentName":"AIMakeIcon","title":"","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"AIMakeIcon","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[{"name":"className","propType":"string","description":""},{"name":"iconClassName","propType":"string","description":""},{"name":"children","propType":"oneOfType","description":""},{"name":"styleBoxModel","propType":"object","description":""},{"name":"styleText","propType":"object","description":""},{"name":"styleBackground","propType":"object","description":""},{"name":"style","propType":"object","description":"","defaultValue":"{}"}]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/manifest.json b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/manifest.json
new file mode 100644
index 000000000..13da88146
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/manifest.json
@@ -0,0 +1 @@
+{"title":"multiple-exported-component","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/amContainer.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/amContainer.js
new file mode 100644
index 000000000..1eccfe080
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/amContainer.js
@@ -0,0 +1,6 @@
+import component from './index.js';
+import amManifest from './amManifest.js';
+
+const getComponent = () => Promise.resolve(component);
+
+export default { getComponent, manifest: amManifest };
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/amManifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/amManifest.js
new file mode 100644
index 000000000..8e0bbf38a
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/amManifest.js
@@ -0,0 +1,99 @@
+/**
+ * The template of manifest for AiMake studio.
+ */
+const manifest = {
+ // The name of current component.
+ name: 'AIMakeImage',
+ // The description of current component.
+ description: '图片',
+ // The coverimage's url of current component.
+ coverImage:
+ 'https://img.alicdn.com/tfs/TB17gMFp1uSBuNjy1XcXXcYjFXa-172-120.png',
+ // The category of current component in AiMake studio.
+ // can be:
+ // `分栏` or `文本` or `按钮` or `标签` or `标签页` or `表格` or `单选` or `分割线`
+ // or `分页` or `复选` or `滑动条` or `进度条` or `卡片` or `开关` or `缺省状态`
+ // or `日期选择` or `输入框` or `搜索框` or `图表` or `图片` or `下拉选择` or `表单行`
+ // or `树控件` or `折叠面板` or `占位图`
+ category: '线条图像',
+ // The preview list of current component in AiMake studio.
+ // Each preset contains following keys:
+ // - `alias`: string. required. The previewing component's name to display
+ // - `thumbnail`: string. not required. The previewing component's thumbnail
+ // - `customProps`: object. not required.
+ // The previewing component's customize props, e.g. { [propName]: [propValue] }
+ // - `colSpan`: number. not required. default 24 (1~24). The previewing component's size when to display
+ presets: [
+ {
+ alias: '图片',
+ thumbnail:
+ 'https://img.alicdn.com/tfs/TB17gMFp1uSBuNjy1XcXXcYjFXa-172-120.png',
+ colSpan: 12,
+ customProps: {
+ width: '224px',
+ height: '126px',
+ src:
+ 'https://img.alicdn.com/tfs/TB1RtEMGbSYBuNjSspfXXcZCpXa-448-252.png',
+ },
+ },
+ ],
+ // Other settings of current component for AiMake studio.
+ settings: {
+ // The render type of current component in AiMake studio.
+ // can be:
+ // `element_inline` or `element_block` or `container`
+ type: 'element_inline',
+ // The insert mode of current component in AiMake studio.
+ // can be:
+ // one or combine of `t` and `b` and `r` and `l`
+ insertionModes: 'rl',
+ // The handle list of current component in AiMake studio.
+ // can be:
+ // an array contains one and more of ['cut', 'copy', 'paste', 'delete', 'duplicate']
+ handles: ['cut', 'copy', 'paste', 'delete', 'duplicate'],
+ // Whether the component can be actived.
+ shouldActive: true,
+ // Whether the component can be dragged.
+ shouldDrag: true,
+ // The props of current component in AiMake studio.
+ // Each property contains following keys:
+ // - `name`: string. required. The property's name
+ // - `label`: string. required. The property's name to display
+ // - `renderer`: string. required. The property's editor. can be: (@冰骊)
+ // - `defaultValue`: any. not required. The property's default value
+ // - `params`: any. not required. The parameters for property's editor
+ // - `placeholder`: string. not required. The placeholder for property's editor
+ // - `hint`: string. not required. The hint for property's editor
+ props: [
+ {
+ name: 'margin',
+ label: '外边距',
+ renderer: 'Quadrant',
+ },
+ {
+ name: 'width',
+ label: '宽度',
+ defaultValue: '224px',
+ renderer: 'Width',
+ },
+ {
+ name: 'height',
+ label: '高度',
+ defaultValue: '126px',
+ renderer: 'Height',
+ },
+ {
+ name: 'src',
+ label: '图片URL',
+ renderer: 'Uploader',
+ placeholder:
+ 'eg: https://img.alicdn.com/tfs/TB1RtEMGbSYBuNjSspfXXcZCpXa-448-252.png',
+ hint: '请填入图片的URL',
+ defaultValue:
+ 'https://img.alicdn.com/tfs/TB1RtEMGbSYBuNjSspfXXcZCpXa-448-252.png',
+ },
+ ],
+ },
+};
+
+export default manifest;
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/container.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/container.js
new file mode 100644
index 000000000..20f8d5899
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/container.js
@@ -0,0 +1,5 @@
+
+import AIMakeImage from '../../../es/basic/AIMakeImage/index.js';
+import manifest from './manifest.js';
+
+export default { origin: AIMakeImage, manifest };
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/index.js
new file mode 100644
index 000000000..edb316342
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/index.js
@@ -0,0 +1,26 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+import HOCBoxModelProps from '../utils/HOCBoxModelProps';
+
+class AIMakeImage extends Component {
+ static propTypes = {
+ styleBoxModel: PropTypes.object.isRequired,
+ style: PropTypes.object,
+ };
+
+ static defaultProps = {
+ style: {},
+ };
+
+ render() {
+ const { styleBoxModel, style, ...otherProps } = this.props;
+ const styles = {
+ ...styleBoxModel,
+ ...style,
+ };
+ return
;
+ }
+}
+
+export default HOCBoxModelProps(AIMakeImage);
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/manifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/manifest.js
new file mode 100644
index 000000000..b5ffde284
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/manifest.js
@@ -0,0 +1 @@
+{"componentName":"AIMakeImage","title":"","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"AIMakeImage","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[{"name":"styleBoxModel","propType":"object","description":""},{"name":"style","propType":"object","description":"","defaultValue":"{}"}]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/manifest.json b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/manifest.json
new file mode 100644
index 000000000..13da88146
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/manifest.json
@@ -0,0 +1 @@
+{"title":"multiple-exported-component","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/amContainer.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/amContainer.js
new file mode 100644
index 000000000..1eccfe080
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/amContainer.js
@@ -0,0 +1,6 @@
+import component from './index.js';
+import amManifest from './amManifest.js';
+
+const getComponent = () => Promise.resolve(component);
+
+export default { getComponent, manifest: amManifest };
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/amManifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/amManifest.js
new file mode 100644
index 000000000..0797b0184
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/amManifest.js
@@ -0,0 +1,115 @@
+/**
+ * The template of manifest for AiMake studio.
+ */
+const manifest = {
+ // The name of current component.
+ name: 'AIMakeLink',
+ // The description of current component.
+ description: '链接',
+ // The coverimage's url of current component.
+ coverImage:
+ 'https://img.alicdn.com/tfs/TB1otbyVwTqK1RjSZPhXXXfOFXa-192-48.png',
+ // The category of current component in AiMake studio.
+ // can be:
+ // `分栏` or `文本` or `按钮` or `标签` or `标签页` or `表格` or `单选` or `分割线`
+ // or `分页` or `复选` or `滑动条` or `进度条` or `卡片` or `开关` or `缺省状态`
+ // or `日期选择` or `输入框` or `搜索框` or `图表` or `图片` or `下拉选择` or `表单行`
+ // or `树控件` or `折叠面板` or `占位图`
+ category: '文本',
+ // The preview list of current component in AiMake studio.
+ // Each preset contains following keys:
+ // - `alias`: string. required. The previewing component's name to display
+ // - `thumbnail`: string. not required. The previewing component's thumbnail
+ // - `customProps`: object. not required.
+ // The previewing component's customize props, e.g. { [propName]: [propValue] }
+ // - `colSpan`: number. not required. default 24 (1~24). The previewing component's size when to display
+ presets: [
+ {
+ alias: '链接',
+ thumbnail:
+ 'https://img.alicdn.com/tfs/TB1otbyVwTqK1RjSZPhXXXfOFXa-192-48.png',
+ colSpan: 12,
+ customProps: {
+ color: '#3788FF',
+ fontSize: '12px',
+ fontWeight: 'normal',
+ href: '#',
+ children: '链接',
+ },
+ },
+ ],
+ // Other settings of current component for AiMake studio.
+ settings: {
+ // The render type of current component in AiMake studio.
+ // can be:
+ // `element_inline` or `element_block` or `container`
+ type: 'element_inline',
+ // The insert mode of current component in AiMake studio.
+ // can be:
+ // one or combine of `t` and `b` and `r` and `l`
+ insertionModes: 'lrv',
+ // The handle list of current component in AiMake studio.
+ // can be:
+ // an array contains one and more of ['cut', 'copy', 'paste', 'delete', 'duplicate']
+ handles: ['cut', 'copy', 'paste', 'delete', 'duplicate'],
+ // Whether the component can be actived.
+ shouldActive: true,
+ // Whether the component can be dragged.
+ shouldDrag: true,
+ // The props of current component in AiMake studio.
+ // Each property contains following keys:
+ // - `name`: string. required. The property's name
+ // - `label`: string. required. The property's name to display
+ // - `renderer`: string. required. The property's editor. can be: (@冰骊)
+ // - `defaultValue`: any. not required. The property's default value
+ // - `params`: any. not required. The parameters for property's editor
+ // - `placeholder`: string. not required. The placeholder for property's editor
+ // - `hint`: string. not required. The hint for property's editor
+ props: [
+ {
+ name: 'margin',
+ label: '外边距',
+ renderer: 'Quadrant',
+ },
+ {
+ name: 'color',
+ label: '文字颜色',
+ renderer: 'Color',
+ defaultValue: '#3788FF',
+ },
+ {
+ name: 'fontSize',
+ label: '字号',
+ renderer: 'FontSize',
+ defaultValue: '12px',
+ },
+ {
+ name: 'fontWeight',
+ label: '字重',
+ renderer: 'FontWeight',
+ defaultValue: 'normal',
+ },
+ {
+ name: 'lineHeight',
+ label: '行高',
+ defaultValue: undefined,
+ renderer: 'LineHeight',
+ },
+ {
+ name: 'href',
+ label: '链接URL',
+ renderer: 'Input',
+ placeholder: '请输入链接URL',
+ defaultValue: '#',
+ },
+ {
+ name: 'children',
+ label: '内容',
+ defaultValue: '链接',
+ renderer: 'TextArea',
+ },
+ ],
+ },
+};
+
+export default manifest;
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/container.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/container.js
new file mode 100644
index 000000000..d927906be
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/container.js
@@ -0,0 +1,5 @@
+
+import AIMakeLink from '../../../es/basic/AIMakeLink/index.js';
+import manifest from './manifest.js';
+
+export default { origin: AIMakeLink, manifest };
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/index.js
new file mode 100644
index 000000000..eba2e5035
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/index.js
@@ -0,0 +1,57 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+import HOCBoxModelProps from '../utils/HOCBoxModelProps';
+import HOCTextProps from '../utils/HOCTextProps';
+import HOCLayoutProps from '../utils/HOCLayoutProps';
+import HOCBackgroundProps from '../utils/HOCBackgroundProps';
+
+class AIMakeLink extends Component {
+ static propTypes = {
+ children: PropTypes.oneOfType([
+ PropTypes.arrayOf(PropTypes.node),
+ PropTypes.node,
+ ]),
+ styleBoxModel: PropTypes.object.isRequired,
+ styleText: PropTypes.object.isRequired,
+ styleLayout: PropTypes.object.isRequired,
+ styleBackground: PropTypes.object.isRequired,
+ style: PropTypes.object,
+ };
+
+ static defaultProps = {
+ children: '',
+ style: {},
+ };
+
+ render() {
+ const {
+ children,
+ styleBoxModel,
+ styleText,
+ styleLayout,
+ styleBackground,
+ style,
+ ...otherProps
+ } = this.props;
+ const styles = {
+ ...styleBoxModel,
+ ...styleText,
+ ...styleLayout,
+ ...styleBackground,
+ ...style,
+ };
+ if (typeof children !== 'string') {
+ styles.display = 'inline-block';
+ }
+ return (
+
+ {[children]}
+
+ );
+ }
+}
+
+export default HOCBoxModelProps(
+ HOCTextProps(HOCLayoutProps(HOCBackgroundProps(AIMakeLink))),
+);
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/manifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/manifest.js
new file mode 100644
index 000000000..377983d6d
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/manifest.js
@@ -0,0 +1 @@
+{"componentName":"AIMakeLink","title":"","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"AIMakeLink","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[{"name":"children","propType":"oneOfType","description":""},{"name":"styleBoxModel","propType":"object","description":""},{"name":"styleText","propType":"object","description":""},{"name":"styleLayout","propType":"object","description":""},{"name":"styleBackground","propType":"object","description":""},{"name":"style","propType":"object","description":"","defaultValue":"{}"}]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/manifest.json b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/manifest.json
new file mode 100644
index 000000000..13da88146
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/manifest.json
@@ -0,0 +1 @@
+{"title":"multiple-exported-component","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/amContainer.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/amContainer.js
new file mode 100644
index 000000000..1eccfe080
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/amContainer.js
@@ -0,0 +1,6 @@
+import component from './index.js';
+import amManifest from './amManifest.js';
+
+const getComponent = () => Promise.resolve(component);
+
+export default { getComponent, manifest: amManifest };
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/amManifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/amManifest.js
new file mode 100644
index 000000000..e4cb0e8e1
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/amManifest.js
@@ -0,0 +1,115 @@
+/**
+ * The template of manifest for AiMake studio.
+ */
+const manifest = {
+ // The name of current component.
+ name: 'AIMakePlaceholder',
+ // The description of current component.
+ description: '占位图',
+ // The coverimage's url of current component.
+ coverImage:
+ 'https://img.alicdn.com/tfs/TB1RxDup3mTBuNjy1XbXXaMrVXa-362-120.png',
+ // The category of current component in AiMake studio.
+ // can be:
+ // `分栏` or `文本` or `按钮` or `标签` or `标签页` or `表格` or `单选` or `分割线`
+ // or `分页` or `复选` or `滑动条` or `进度条` or `卡片` or `开关` or `缺省状态`
+ // or `日期选择` or `输入框` or `搜索框` or `图表` or `图片` or `下拉选择` or `表单行`
+ // or `树控件` or `折叠面板` or `占位图`
+ category: '占位图',
+ // The preview list of current component in AiMake studio.
+ // Each preset contains following keys:
+ // - `alias`: string. required. The previewing component's name to display
+ // - `thumbnail`: string. not required. The previewing component's thumbnail
+ // - `customProps`: object. not required.
+ // The previewing component's customize props, e.g. { [propName]: [propValue] }
+ // - `colSpan`: number. not required. default 24 (1~24). The previewing component's size when to display
+ presets: [
+ {
+ alias: '占位图',
+ thumbnail:
+ 'https://img.alicdn.com/tfs/TB1RxDup3mTBuNjy1XbXXaMrVXa-362-120.png',
+ colSpan: 24,
+ customProps: {
+ width: '224px',
+ height: '126px',
+ backgroundColor: '#FFF6E0',
+ textAlign: 'center',
+ border: '1px dashed rgb(170, 170, 170)',
+ children: '暂不支持此组件',
+ },
+ },
+ ],
+ // Other settings of current component for AiMake studio.
+ settings: {
+ // The render type of current component in AiMake studio.
+ // can be:
+ // `element_inline` or `element_block` or `container`
+ type: 'element_inline',
+ // The insert mode of current component in AiMake studio.
+ // can be:
+ // one or combine of `t` and `b` and `r` and `l`
+ insertionModes: 'lr',
+ // The handle list of current component in AiMake studio.
+ // can be:
+ // an array contains one and more of ['cut', 'copy', 'paste', 'delete', 'duplicate']
+ handles: ['cut', 'copy', 'paste', 'delete', 'duplicate'],
+ // Whether the component can be actived.
+ shouldActive: true,
+ // Whether the component can be dragged.
+ shouldDrag: true,
+ // The props of current component in AiMake studio.
+ // Each property contains following keys:
+ // - `name`: string. required. The property's name
+ // - `label`: string. required. The property's name to display
+ // - `renderer`: string. required. The property's editor. can be: (@冰骊)
+ // - `defaultValue`: any. not required. The property's default value
+ // - `params`: any. not required. The parameters for property's editor
+ // - `placeholder`: string. not required. The placeholder for property's editor
+ // - `hint`: string. not required. The hint for property's editor
+ props: [
+ {
+ name: 'margin',
+ label: '外边距',
+ renderer: 'Quadrant',
+ },
+ {
+ name: 'width',
+ label: '宽度',
+ defaultValue: '224px',
+ renderer: 'Width',
+ },
+ {
+ name: 'height',
+ label: '高度',
+ defaultValue: '126px',
+ renderer: 'Height',
+ },
+ {
+ name: 'backgroundColor',
+ label: '背景色',
+ defaultValue: '#FFF6E0',
+ renderer: false,
+ },
+ {
+ name: 'textAlign',
+ label: '对齐',
+ defaultValue: 'center',
+ renderer: false,
+ },
+ {
+ name: 'border',
+ label: '边框',
+ defaultValue: '1px dashed rgb(170, 170, 170)',
+ renderer: false,
+ },
+ {
+ name: 'children',
+ label: '内容',
+ defaultValue: '暂不支持此组件',
+ renderer: false,
+ },
+ ],
+ },
+};
+
+export default manifest;
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/container.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/container.js
new file mode 100644
index 000000000..17f48df56
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/container.js
@@ -0,0 +1,5 @@
+
+import AIMakePlaceholder from '../../../es/basic/AIMakePlaceholder/index.js';
+import manifest from './manifest.js';
+
+export default { origin: AIMakePlaceholder, manifest };
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/index.js
new file mode 100644
index 000000000..60cdbb1dd
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/index.js
@@ -0,0 +1,45 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+import HOCBoxModelProps from '../utils/HOCBoxModelProps';
+import HOCLayoutProps from '../utils/HOCLayoutProps';
+
+class AIMakePlaceholder extends Component {
+ static propTypes = {
+ children: PropTypes.oneOfType([
+ PropTypes.arrayOf(PropTypes.node),
+ PropTypes.node,
+ ]),
+ styleBoxModel: PropTypes.object.isRequired,
+ styleLayout: PropTypes.object.isRequired,
+ style: PropTypes.object,
+ };
+
+ static defaultProps = {
+ children: '',
+ style: {},
+ };
+
+ render() {
+ const {
+ children, styleBoxModel, styleLayout, style,
+ } = this.props;
+ const styles = {
+ ...styleBoxModel,
+ ...styleLayout,
+ ...style,
+ };
+ const placeholderStyle = {
+ display: 'inline-block',
+ border: '1px dashed #aaa',
+ lineHeight: styles.height,
+ backgroundColor: '#F5E075',
+ overflow: 'hidden',
+ textAlign: 'center',
+ ...styles,
+ };
+ return {children}
;
+ }
+}
+
+export default HOCBoxModelProps(HOCLayoutProps(AIMakePlaceholder));
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/manifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/manifest.js
new file mode 100644
index 000000000..7456ed578
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/manifest.js
@@ -0,0 +1 @@
+{"componentName":"AIMakePlaceholder","title":"","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"AIMakePlaceholder","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[{"name":"children","propType":"oneOfType","description":""},{"name":"styleBoxModel","propType":"object","description":""},{"name":"styleLayout","propType":"object","description":""},{"name":"style","propType":"object","description":"","defaultValue":"{}"}]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/manifest.json b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/manifest.json
new file mode 100644
index 000000000..13da88146
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/manifest.json
@@ -0,0 +1 @@
+{"title":"multiple-exported-component","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/amContainer.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/amContainer.js
new file mode 100644
index 000000000..1eccfe080
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/amContainer.js
@@ -0,0 +1,6 @@
+import component from './index.js';
+import amManifest from './amManifest.js';
+
+const getComponent = () => Promise.resolve(component);
+
+export default { getComponent, manifest: amManifest };
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/amManifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/amManifest.js
new file mode 100644
index 000000000..b84fcba79
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/amManifest.js
@@ -0,0 +1,119 @@
+/**
+ * The template of manifest for AiMake studio.
+ */
+const manifest = {
+ // The name of current component.
+ name: 'AIMakeText',
+ // The description of current component.
+ description: '富文本',
+ // The coverimage's url of current component.
+ coverImage:
+ 'https://img.alicdn.com/tfs/TB15R_xVzDpK1RjSZFrXXa78VXa-192-48.png',
+ // The category of current component in AiMake studio.
+ // can be:
+ // `分栏` or `文本` or `按钮` or `标签` or `标签页` or `表格` or `单选` or `分割线`
+ // or `分页` or `复选` or `滑动条` or `进度条` or `卡片` or `开关` or `缺省状态`
+ // or `日期选择` or `输入框` or `搜索框` or `图表` or `图片` or `下拉选择` or `表单行`
+ // or `树控件` or `折叠面板` or `占位图`
+ category: '文本',
+ // The preview list of current component in AiMake studio.
+ // Each preset contains following keys:
+ // - `alias`: string. required. The previewing component's name to display
+ // - `thumbnail`: string. not required. The previewing component's thumbnail
+ // - `customProps`: object. not required.
+ // The previewing component's customize props, e.g. { [propName]: [propValue] }
+ // - `colSpan`: number. not required. default 24 (1~24). The previewing component's size when to display
+ presets: [
+ {
+ alias: '富文本',
+ thumbnail:
+ 'https://img.alicdn.com/tfs/TB15R_xVzDpK1RjSZFrXXa78VXa-192-48.png',
+ colSpan: 12,
+ customProps: {
+ type: 'label',
+ fontSize: '12px',
+ fontWeight: 'normal',
+ children: '文本内容',
+ },
+ },
+ ],
+ // Other settings of current component for AiMake studio.
+ settings: {
+ // The render type of current component in AiMake studio.
+ // can be:
+ // `element_inline` or `element_block` or `container`
+ type: 'element_inline',
+ // The insert mode of current component in AiMake studio.
+ // can be:
+ // one or combine of `t` and `b` and `r` and `l`
+ insertionModes: 'tbrl',
+ // The handle list of current component in AiMake studio.
+ // can be:
+ // an array contains one and more of ['cut', 'copy', 'paste', 'delete', 'duplicate']
+ handles: ['cut', 'copy', 'paste', 'delete', 'duplicate'],
+ // Whether the component can be actived.
+ shouldActive: true,
+ // Whether the component can be dragged.
+ shouldDrag: true,
+ // The props of current component in AiMake studio.
+ // Each property contains following keys:
+ // - `name`: string. required. The property's name
+ // - `label`: string. required. The property's name to display
+ // - `renderer`: string. required. The property's editor. can be: (@冰骊)
+ // - `defaultValue`: any. not required. The property's default value
+ // - `params`: any. not required. The parameters for property's editor
+ // - `placeholder`: string. not required. The placeholder for property's editor
+ // - `hint`: string. not required. The hint for property's editor
+ props: [
+ {
+ name: 'type',
+ label: '类型',
+ renderer: 'Select',
+ defaultValue: 'label',
+ params: [
+ { label: '一级标题', value: 'h1' },
+ { label: '二级标题', value: 'h2' },
+ { label: '三级标题', value: 'h3' },
+ { label: '段落', value: 'p' },
+ { label: '标签', value: 'label' },
+ ],
+ },
+ {
+ name: 'margin',
+ label: '外边距',
+ renderer: 'Quadrant',
+ },
+ {
+ name: 'color',
+ label: '文字颜色',
+ renderer: 'Color',
+ },
+ {
+ name: 'fontSize',
+ label: '字号',
+ renderer: 'FontSize',
+ defaultValue: '12px',
+ },
+ {
+ name: 'fontWeight',
+ label: '字重',
+ renderer: 'FontWeight',
+ defaultValue: 'normal',
+ },
+ {
+ name: 'lineHeight',
+ label: '行高',
+ defaultValue: undefined,
+ renderer: 'LineHeight',
+ },
+ {
+ name: 'children',
+ label: '内容',
+ defaultValue: '文本内容',
+ renderer: 'TextArea',
+ },
+ ],
+ },
+};
+
+export default manifest;
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/container.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/container.js
new file mode 100644
index 000000000..6bf3cca68
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/container.js
@@ -0,0 +1,5 @@
+
+import AIMakeText from '../../../es/basic/AIMakeText/index.js';
+import manifest from './manifest.js';
+
+export default { origin: AIMakeText, manifest };
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/index.js
new file mode 100644
index 000000000..133e940f4
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/index.js
@@ -0,0 +1,72 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+import HOCBoxModelProps from '../utils/HOCBoxModelProps';
+import HOCTextProps from '../utils/HOCTextProps';
+import HOCLayoutProps from '../utils/HOCLayoutProps';
+import HOCBackgroundProps from '../utils/HOCBackgroundProps';
+
+class AIMakeText extends Component {
+ static propTypes = {
+ children: PropTypes.oneOfType([
+ PropTypes.arrayOf(PropTypes.node),
+ PropTypes.node,
+ PropTypes.string,
+ ]),
+ type: PropTypes.string,
+ styleBoxModel: PropTypes.object.isRequired,
+ styleText: PropTypes.object.isRequired,
+ styleLayout: PropTypes.object.isRequired,
+ styleBackground: PropTypes.object.isRequired,
+ style: PropTypes.object,
+ };
+
+ static defaultProps = {
+ children: '',
+ type: '', // paragraph || label
+ style: {},
+ };
+
+ generateComponentType = (componentType) => {
+ const componentNameMap = {
+ h1: 'h1',
+ h2: 'h2',
+ h3: 'h3',
+ h4: 'h4',
+ h5: 'h5',
+ paragraph: 'p',
+ label: 'label',
+ };
+ return componentNameMap[componentType] || 'div';
+ };
+
+ render() {
+ const {
+ children,
+ type,
+ styleBoxModel,
+ styleText,
+ styleLayout,
+ styleBackground,
+ style,
+ } = this.props;
+ const styles = {
+ ...styleBoxModel,
+ ...styleText,
+ ...styleLayout,
+ ...styleBackground,
+ ...style,
+ };
+ const Comp = this.generateComponentType(type);
+ const labelStyle = Comp === 'label' ? { display: 'inline-block' } : {};
+ return (
+
+ {[children]}
+
+ );
+ }
+}
+
+export default HOCBoxModelProps(
+ HOCTextProps(HOCLayoutProps(HOCBackgroundProps(AIMakeText))),
+);
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/manifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/manifest.js
new file mode 100644
index 000000000..b275a1815
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/manifest.js
@@ -0,0 +1 @@
+{"componentName":"AIMakeText","title":"","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"AIMakeText","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[{"name":"children","propType":"oneOfType","description":""},{"name":"type","propType":"string","description":""},{"name":"styleBoxModel","propType":"object","description":""},{"name":"styleText","propType":"object","description":""},{"name":"styleLayout","propType":"object","description":""},{"name":"styleBackground","propType":"object","description":""},{"name":"style","propType":"object","description":"","defaultValue":"{}"}]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/manifest.json b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/manifest.json
new file mode 100644
index 000000000..13da88146
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/manifest.json
@@ -0,0 +1 @@
+{"title":"multiple-exported-component","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/amContainer.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/amContainer.js
new file mode 100644
index 000000000..1eccfe080
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/amContainer.js
@@ -0,0 +1,6 @@
+import component from './index.js';
+import amManifest from './amManifest.js';
+
+const getComponent = () => Promise.resolve(component);
+
+export default { getComponent, manifest: amManifest };
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/amManifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/amManifest.js
new file mode 100644
index 000000000..951356cd0
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/amManifest.js
@@ -0,0 +1,29 @@
+const manifest = {
+ name: 'Root',
+ description: '底板',
+ coverImage: '',
+ category: '',
+ presets: [],
+ settings: {
+ type: 'container',
+ insertionModes: 'v',
+ handles: ['paste'],
+ shouldActive: true,
+ shouldDrag: false,
+ props: [
+ {
+ name: 'padding',
+ label: '内边距',
+ renderer: 'Quadrant',
+ },
+ {
+ name: 'backgroundColor',
+ label: '背景颜色',
+ defaultValue: '#F5F6FA',
+ renderer: 'Color',
+ },
+ ],
+ },
+};
+
+export default manifest;
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/container.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/container.js
new file mode 100644
index 000000000..d3d95eef8
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/container.js
@@ -0,0 +1,5 @@
+
+import Root from '../../../es/basic/Root/index.js';
+import manifest from './manifest.js';
+
+export default { origin: Root, manifest };
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/index.js
new file mode 100644
index 000000000..86cc89915
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/index.js
@@ -0,0 +1,29 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+class Root extends React.Component {
+ static propTypes = {
+ style: PropTypes.object,
+ children: PropTypes.oneOfType([
+ PropTypes.element,
+ PropTypes.arrayOf(PropTypes.element),
+ ]),
+ };
+
+ static defaultProps = {
+ style: {
+ padding: 0,
+ backgroundColor: '#f0f2f5',
+ minHeight: '100%',
+ },
+ children: null,
+ };
+
+ render() {
+ const { style, children } = this.props;
+ const newStyle = Object.assign({}, Root.defaultProps.style, style);
+ return {children}
;
+ }
+}
+
+export default Root;
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/manifest.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/manifest.js
new file mode 100644
index 000000000..2ec2d9e3e
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/manifest.js
@@ -0,0 +1 @@
+{"componentName":"Root","title":"","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"Root","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[{"name":"style","propType":"object","description":"","defaultValue":"{\n padding: 0,\n backgroundColor: '#f0f2f5',\n minHeight: '100%'\n}"},{"name":"children","propType":"oneOfType","description":""}]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/manifest.json b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/manifest.json
new file mode 100644
index 000000000..13da88146
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/manifest.json
@@ -0,0 +1 @@
+{"title":"multiple-exported-component","docUrl":"","screenshot":"","npm":{"package":"multiple-exported-component","version":"1.0.0","exportName":"","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js","destructuring":false,"subName":""},"props":[]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/style/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/style/index.js
new file mode 100644
index 000000000..d74e52ee9
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/style/index.js
@@ -0,0 +1 @@
+import './index.less';
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/style/index.less b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/style/index.less
new file mode 100644
index 000000000..dc3680eb4
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/style/index.less
@@ -0,0 +1,8 @@
+// Alignment
+.text-left { text-align: left; }
+.text-right { text-align: right; }
+.text-center { text-align: center; }
+.text-justify { text-align: justify; }
+.text-nowrap { white-space: nowrap; }
+
+// BoxModel
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCBackgroundProps.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCBackgroundProps.js
new file mode 100644
index 000000000..012ade534
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCBackgroundProps.js
@@ -0,0 +1,44 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+/**
+ * (HOC)注入背景相关属性配置
+ * 包含 'backgroundColor'
+ * @param {*} WrappedComponent
+ */
+const HOCBackgroundProps = (WrappedComponent) => {
+ const PROPS = {
+ backgroundColor: 'backgroundColor',
+ };
+ return class extends Component {
+ static propTypes = {
+ backgroundColor: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ };
+
+ static defaultProps = {
+ backgroundColor: false,
+ };
+
+ parseStyle = (args) => {
+ const style = {};
+ Object.keys(PROPS).forEach((item) => {
+ // if props isn't false
+ if (!args[item]) return;
+ style[PROPS[item]] = args[item];
+ });
+ return style;
+ };
+
+ render() {
+ const { backgroundColor, ...otherProps } = this.props;
+ return (
+
+ );
+ }
+ };
+};
+
+export default HOCBackgroundProps;
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCBoxModelProps.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCBoxModelProps.js
new file mode 100644
index 000000000..9e879b652
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCBoxModelProps.js
@@ -0,0 +1,75 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+const parseJoin = value => value.join(' ');
+
+/**
+ * (HOC)注入盒子模型相关属性配置
+ * 包含 'display', 'margin', 'border', 'padding', 'width', 'height', 'borderRadius'
+ * @param {*} WrappedComponent
+ */
+const HOCBoxModelProps = (WrappedComponent) => {
+ const PROPS = {
+ display: 'display',
+ margin: 'margin',
+ border: 'border',
+ padding: 'padding',
+ width: 'width',
+ height: 'height',
+ borderRadius: 'borderRadius',
+ };
+ return class extends Component {
+ static propTypes = {
+ display: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ margin: PropTypes.oneOfType([PropTypes.array, PropTypes.bool]),
+ border: PropTypes.oneOfType([PropTypes.array, PropTypes.bool]),
+ padding: PropTypes.oneOfType([PropTypes.array, PropTypes.bool]),
+ width: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ height: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ borderRadius: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ };
+
+ static defaultProps = {
+ display: false,
+ margin: false,
+ border: false,
+ padding: false,
+ width: false,
+ height: false,
+ borderRadius: false,
+ };
+
+ parseStyle = (args) => {
+ const style = {};
+ Object.keys(PROPS).forEach((item) => {
+ // if props isn't false
+ if (!args[item]) return;
+ style[PROPS[item]] = Array.isArray(args[item])
+ ? parseJoin(args[item])
+ : args[item];
+ });
+ return style;
+ };
+
+ render() {
+ const {
+ display,
+ margin,
+ border,
+ padding,
+ width,
+ height,
+ borderRadius,
+ ...otherProps
+ } = this.props;
+ return (
+
+ );
+ }
+ };
+};
+
+export default HOCBoxModelProps;
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCFlexLayoutProps.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCFlexLayoutProps.js
new file mode 100644
index 000000000..eb1e1b31a
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCFlexLayoutProps.js
@@ -0,0 +1,61 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+/**
+ * (HOC)注入flex布局相关属性配置
+ * 包含 'alignItems', 'justifyContent', 'flexDirection'
+ * @param {*} WrappedComponent
+ */
+const HOCFlexLayoutProps = (WrappedComponent) => {
+ const PROPS = {
+ alignItems: 'alignItems',
+ justifyContent: 'justifyContent',
+ flexDirection: 'flexDirection',
+ flexWrap: 'flexWrap',
+ };
+ return class extends Component {
+ static propTypes = {
+ alignItems: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ justifyContent: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ flexDirection: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ flexWrap: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ };
+
+ static defaultProps = {
+ alignItems: false,
+ justifyContent: false,
+ flexDirection: false,
+ flexWrap: false,
+ };
+
+ parseStyle = (args) => {
+ const style = {};
+ if (args.style && args.style.display === 'flex') {
+ Object.keys(PROPS).forEach((item) => {
+ // if props isn't false
+ if (!args[item]) return;
+ style[PROPS[item]] = args[item];
+ });
+ }
+ return style;
+ };
+
+ render() {
+ const {
+ alignItems,
+ justifyContent,
+ flexDirection,
+ flexWrap,
+ ...otherProps
+ } = this.props;
+ return (
+
+ );
+ }
+ };
+};
+
+export default HOCFlexLayoutProps;
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCLayoutProps.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCLayoutProps.js
new file mode 100644
index 000000000..b16a8c162
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCLayoutProps.js
@@ -0,0 +1,52 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+/**
+ * (HOC)注入布局相关属性配置
+ * 包含 'align', 'lineHeight', 'verticalAlign'
+ * @param {*} WrappedComponent
+ */
+const HOCLayoutProps = (WrappedComponent) => {
+ const PROPS = {
+ align: 'textAlign',
+ lineHeight: 'lineHeight',
+ verticalAlign: 'verticalAlign',
+ };
+ return class extends Component {
+ static propTypes = {
+ align: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ lineHeight: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ verticalAlign: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ };
+
+ static defaultProps = {
+ align: false,
+ lineHeight: false,
+ verticalAlign: false,
+ };
+
+ parseStyle = (args) => {
+ const style = {};
+ Object.keys(PROPS).forEach((item) => {
+ // if props isn't false
+ if (!args[item]) return;
+ style[PROPS[item]] = args[item];
+ });
+ return style;
+ };
+
+ render() {
+ const {
+ align, lineHeight, verticalAlign, ...otherProps
+ } = this.props;
+ return (
+
+ );
+ }
+ };
+};
+
+export default HOCLayoutProps;
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCTextProps.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCTextProps.js
new file mode 100644
index 000000000..c34b18d37
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCTextProps.js
@@ -0,0 +1,52 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+/**
+ * (HOC)注入文本相关属性配置
+ * 包含 'fontSize', 'fontWeight', 'color'
+ * @param {*} WrappedComponent
+ */
+const HOCTextProps = (WrappedComponent) => {
+ const PROPS = {
+ fontSize: 'fontSize',
+ fontWeight: 'fontWeight',
+ color: 'color',
+ };
+ return class extends Component {
+ static propTypes = {
+ fontSize: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ fontWeight: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ color: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
+ };
+
+ static defaultProps = {
+ fontSize: false,
+ fontWeight: false,
+ color: false,
+ };
+
+ parseStyle = (args) => {
+ const style = {};
+ Object.keys(PROPS).forEach((item) => {
+ // if props isn't false
+ if (!args[item]) return;
+ style[PROPS[item]] = args[item];
+ });
+ return style;
+ };
+
+ render() {
+ const {
+ fontSize, fontWeight, color, ...otherProps
+ } = this.props;
+ return (
+
+ );
+ }
+ };
+};
+
+export default HOCTextProps;
diff --git a/packages/material-parser/test/fixtures/multiple-exported-component/src/index.js b/packages/material-parser/test/fixtures/multiple-exported-component/src/index.js
new file mode 100644
index 000000000..9ae1753f6
--- /dev/null
+++ b/packages/material-parser/test/fixtures/multiple-exported-component/src/index.js
@@ -0,0 +1,17 @@
+import AIMakeBlank from './basic/AIMakeBlank';
+import AIMakeIcon from './basic/AIMakeIcon';
+import AIMakeImage from './basic/AIMakeImage';
+import AIMakeLink from './basic/AIMakeLink';
+import AIMakePlaceholder from './basic/AIMakePlaceholder';
+import AIMakeText from './basic/AIMakeText';
+import Root from './basic/Root';
+
+export {
+ AIMakeBlank,
+ AIMakeIcon,
+ AIMakeImage,
+ AIMakeLink,
+ AIMakePlaceholder,
+ AIMakeText,
+ Root,
+};
diff --git a/packages/material-parser/test/fixtures/rax-component/package.json b/packages/material-parser/test/fixtures/rax-component/package.json
new file mode 100644
index 000000000..30fd28d51
--- /dev/null
+++ b/packages/material-parser/test/fixtures/rax-component/package.json
@@ -0,0 +1,65 @@
+{
+ "name": "@ali/chaoshi-meta-example",
+ "version": "1.0.0",
+ "description": "intro component",
+ "main": "lib/index.js",
+ "module": "es/index.js",
+ "miniappConfig": {
+ "main": "lib/miniapp/index",
+ "main:wechat": "lib/wechat-miniprogram/index"
+ },
+ "files": [
+ "build",
+ "dist",
+ "es",
+ "lib",
+ "material-meta.json"
+ ],
+ "keywords": [
+ "Rax",
+ "rax-component"
+ ],
+ "engines": {
+ "npm": ">=3.0.0"
+ },
+ "scripts": {
+ "start": "build-scripts start",
+ "build": "build-scripts build",
+ "eslint": "eslint --ext .js,.jsx,.ts,.tsx ./",
+ "eslint:fix": "npm run eslint -- --fix",
+ "stylelint": "stylelint \"**/*.{css,scss,less}\"",
+ "lint": "npm run eslint && npm run stylelint",
+ "prepublishOnly": "npm run build"
+ },
+ "dependencies": {
+ "@ali/pcom-chaoshi-meta-design": "^1.1.5",
+ "rax-text": "^2.0.0",
+ "rax-view": "^2.0.0"
+ },
+ "peerDependencies": {
+ "rax": "^1.1.0"
+ },
+ "devDependencies": {
+ "@alib/build-scripts": "^0.1.0",
+ "@alife/build-plugin-lowcode": "^1.0.17",
+ "@iceworks/spec": "^1.0.0",
+ "@types/rax": "^1.0.0",
+ "build-plugin-component": "^1.0.0",
+ "driver-universal": "^3.1.0",
+ "eslint": "^6.8.0",
+ "rax": "^1.1.0",
+ "rax-test-renderer": "^1.0.0",
+ "stylelint": "^13.7.2",
+ "typescript": "^3.7.3"
+ },
+ "componentConfig": {
+ "name": "ChaoshiMetaExample",
+ "title": "ChaoshiMetaExample",
+ "category": "Information"
+ },
+ "publishConfig": {
+ "registry": "https://registry.npm.alibaba-inc.com"
+ },
+ "license": "MIT",
+ "homepage": "https://unpkg.alibaba-inc.com/@ali/chaoshi-meta-example@1.0.0/build/index.html"
+}
diff --git a/packages/material-parser/test/fixtures/rax-component/src/index.css b/packages/material-parser/test/fixtures/rax-component/src/index.css
new file mode 100644
index 000000000..41a09e7fe
--- /dev/null
+++ b/packages/material-parser/test/fixtures/rax-component/src/index.css
@@ -0,0 +1,5 @@
+.rax-demo-title {
+ font-size: 45rpx;
+ font-weight: bold;
+ margin: 20rpx 0;
+}
diff --git a/packages/material-parser/test/fixtures/rax-component/src/index.tsx b/packages/material-parser/test/fixtures/rax-component/src/index.tsx
new file mode 100644
index 000000000..bb498cd70
--- /dev/null
+++ b/packages/material-parser/test/fixtures/rax-component/src/index.tsx
@@ -0,0 +1,22 @@
+import { createElement, forwardRef } from 'rax';
+import { Price as _Price, Title as _Title } from '@ali/pcom-chaoshi-meta-design';
+import View from 'rax-view';
+import Text from 'rax-text';
+import './index.css';
+
+interface Props {
+ a: string;
+}
+
+const MyComponent = forwardRef((props: Props, ref: any) => {
+ return (
+
+ Hello World!
+
+ );
+});
+
+export default MyComponent;
+
+export const Price = _Price;
+export const Title = _Title;
diff --git a/packages/material-parser/test/fixtures/single-exported-component/es/container.js b/packages/material-parser/test/fixtures/single-exported-component/es/container.js
new file mode 100644
index 000000000..3ab0a3fb6
--- /dev/null
+++ b/packages/material-parser/test/fixtures/single-exported-component/es/container.js
@@ -0,0 +1,6 @@
+
+ import Demo from './index.js';
+ import manifest from './manifest.js';
+
+ export default { origin: Demo, manifest };
+
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/single-exported-component/es/index.js b/packages/material-parser/test/fixtures/single-exported-component/es/index.js
new file mode 100644
index 000000000..c5b8d35bc
--- /dev/null
+++ b/packages/material-parser/test/fixtures/single-exported-component/es/index.js
@@ -0,0 +1,97 @@
+import _classCallCheck from '@babel/runtime/helpers/classCallCheck';
+import _createClass from '@babel/runtime/helpers/createClass';
+import _possibleConstructorReturn from '@babel/runtime/helpers/possibleConstructorReturn';
+import _getPrototypeOf from '@babel/runtime/helpers/getPrototypeOf';
+import _inherits from '@babel/runtime/helpers/inherits';
+
+/* eslint-disable react/no-unused-prop-types */
+
+/* eslint-disable react/require-default-props */
+import React from 'react';
+import PropTypes from 'prop-types';
+import './main.css';
+
+const Demo =
+ /* #__PURE__ */
+ (function(_React$Component) {
+ _inherits(Demo, _React$Component);
+
+ function Demo() {
+ _classCallCheck(this, Demo);
+
+ return _possibleConstructorReturn(this, _getPrototypeOf(Demo).apply(this, arguments));
+ }
+
+ _createClass(Demo, [
+ {
+ key: 'render',
+ value: function render() {
+ return React.createElement('div', null, ' Test ');
+ },
+ },
+ ]);
+
+ return Demo;
+ })(React.Component);
+
+Demo.propTypes = {
+ optionalArray: PropTypes.array,
+ optionalBool: PropTypes.bool,
+ /**
+ * desc
+ * @param {string} title - The title of the book.
+ * @param {string} author - The author of the book.
+ * @returns {any}
+ */
+ optionalFunc: PropTypes.func,
+ optionalNumber: PropTypes.number,
+ optionalObject: PropTypes.object,
+ optionalString: PropTypes.string,
+ optionalSymbol: PropTypes.symbol,
+ // Anything that can be rendered: numbers, strings, elements or an array
+ // (or fragment) containing these types.
+ optionalNode: PropTypes.node,
+ // A React element (ie. ).
+ optionalElement: PropTypes.element,
+ // A React element type (ie. MyComponent).
+ optionalElementType: PropTypes.elementType,
+ // You can also declare that a prop is an instance of a class. This uses
+ // JS's instanceof operator.
+ optionalMessage: PropTypes.instanceOf(Demo),
+ // You can ensure that your prop is limited to specific values by treating
+ // it as an enum.
+ optionalEnum: PropTypes.oneOf(['News', 'Photos']),
+ // An object that could be one of many types
+ optionalUnion: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.instanceOf(Demo),
+ ]),
+ // An array of a certain type
+ optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
+ // An object with property values of a certain type
+ optionalObjectOf: PropTypes.objectOf(PropTypes.number),
+ // You can chain any of the above with `isRequired` to make sure a warning
+ // is shown if the prop isn't provided.
+ // An object taking on a particular shape
+ optionalObjectWithShape: PropTypes.shape({
+ optionalProperty: PropTypes.string,
+ requiredProperty: PropTypes.number.isRequired,
+ }),
+ optionalObjectWithShape2: PropTypes.shape({
+ optionalProperty: PropTypes.string,
+ requiredProperty: PropTypes.number.isRequired,
+ }).isRequired,
+ // An object with warnings on extra properties
+ optionalObjectWithStrictShape: PropTypes.exact({
+ optionalProperty: PropTypes.string,
+ requiredProperty: PropTypes.number.isRequired,
+ }),
+ requiredFunc: PropTypes.func.isRequired,
+ // A value of any data type
+ requiredAny: PropTypes.any.isRequired,
+};
+Demo.defaultProps = {
+ optionalNumber: 123,
+};
+export default Demo;
diff --git a/packages/material-parser/test/fixtures/single-exported-component/es/main.css b/packages/material-parser/test/fixtures/single-exported-component/es/main.css
new file mode 100644
index 000000000..620f1985f
--- /dev/null
+++ b/packages/material-parser/test/fixtures/single-exported-component/es/main.css
@@ -0,0 +1,6 @@
+@charset "UTF-8";
+/* 不引入依赖组件的样式,比如组件 import { Button } from '@alife/next'; */
+/* 不需要在main.scss中引入 @import '~@alife/next/lib/button/index.scss'; */
+/* 但是在lib/index.scss中需要引入 @import '~@alife/next/lib/button/index.scss'; */
+/* 如果需要引入主题变量引入此段 */
+/* 组件自身样式 */
diff --git a/packages/material-parser/test/fixtures/single-exported-component/es/main.scss b/packages/material-parser/test/fixtures/single-exported-component/es/main.scss
new file mode 100644
index 000000000..ac45616a5
--- /dev/null
+++ b/packages/material-parser/test/fixtures/single-exported-component/es/main.scss
@@ -0,0 +1,11 @@
+/* 不引入依赖组件的样式,比如组件 import { Button } from '@alife/next'; */
+/* 不需要在main.scss中引入 @import '~@alife/next/lib/button/index.scss'; */
+/* 但是在lib/index.scss中需要引入 @import '~@alife/next/lib/button/index.scss'; */
+
+/* 如果需要引入主题变量引入此段 */
+// @import '~@alife/next/variables.scss';
+
+/* 组件自身样式 */
+// .custom-component {
+// color: $color-brand1-1;
+// }
diff --git a/packages/material-parser/test/fixtures/single-exported-component/es/manifest.js b/packages/material-parser/test/fixtures/single-exported-component/es/manifest.js
new file mode 100644
index 000000000..98cfde9b0
--- /dev/null
+++ b/packages/material-parser/test/fixtures/single-exported-component/es/manifest.js
@@ -0,0 +1 @@
+{"componentName":"Demo","title":"","docUrl":"","screenshot":"","npm":{"package":"single-exported-component","version":"1.0.0","exportName":"Demo","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/es/index.js","destructuring":false,"subName":""},"props":[{"name":"optionalArray","propType":"array","description":""},{"name":"optionalBool","propType":"bool","description":""},{"name":"optionalFunc","propType":"func","description":""},{"name":"optionalNumber","propType":"number","description":""},{"name":"optionalObject","propType":"object","description":""},{"name":"optionalString","propType":"string","description":""},{"name":"optionalSymbol","propType":"symbol","description":""},{"name":"optionalNode","propType":"node","description":""},{"name":"optionalElement","propType":"element","description":""},{"name":"optionalElementType","propType":"elementType","description":""},{"name":"optionalMessage","propType":"instanceOf","description":""},{"name":"optionalEnum","propType":"oneOf","description":""},{"name":"optionalUnion","propType":"oneOfType","description":""},{"name":"optionalArrayOf","propType":"arrayOf","description":""},{"name":"optionalObjectOf","propType":"objectOf","description":""},{"name":"optionalObjectWithShape","propType":"shape","description":""},{"name":"optionalObjectWithShape2","propType":"shape","description":""},{"name":"optionalObjectWithStrictShape","propType":"exact","description":""},{"name":"requiredFunc","propType":"func","description":""},{"name":"requiredAny","propType":"any","description":""}]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/single-exported-component/es/manifest.json b/packages/material-parser/test/fixtures/single-exported-component/es/manifest.json
new file mode 100644
index 000000000..32d6f59dd
--- /dev/null
+++ b/packages/material-parser/test/fixtures/single-exported-component/es/manifest.json
@@ -0,0 +1 @@
+{"title":"single-exported-component","docUrl":"","screenshot":"","npm":{"package":"single-exported-component","version":"1.0.0","exportName":"","main":"/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/es/index.js","destructuring":false,"subName":""},"props":[]}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/single-exported-component/package.json b/packages/material-parser/test/fixtures/single-exported-component/package.json
new file mode 100644
index 000000000..d1c283cd3
--- /dev/null
+++ b/packages/material-parser/test/fixtures/single-exported-component/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "single-exported-component",
+ "description": "",
+ "version": "1.0.0",
+ "main": "src/index.js",
+ "module": "es/index.js",
+ "files": [
+ "demo/",
+ "lib/",
+ "es/",
+ "build/"
+ ],
+ "scripts": {
+ "postversion": "node ./scripts/postversion.js"
+ },
+ "dependencies": {
+ "prop-types": "^15.7.2",
+ "react": "^16.8.5",
+ "react-dom": "^16.8.5"
+ },
+ "devDependencies": {
+ "cross-spawn": "^6.0.5"
+ },
+ "peerDependencies": {
+ "react": "^16.8.6"
+ },
+ "publishConfig": {
+ "registry": "https://registry.npm.alibaba-inc.com"
+ }
+}
diff --git a/packages/material-parser/test/fixtures/single-exported-component/src/index.js b/packages/material-parser/test/fixtures/single-exported-component/src/index.js
new file mode 100644
index 000000000..e075c0fd1
--- /dev/null
+++ b/packages/material-parser/test/fixtures/single-exported-component/src/index.js
@@ -0,0 +1,90 @@
+/* eslint-disable react/no-unused-prop-types */
+/* eslint-disable react/require-default-props */
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import './main.scss';
+
+const a = 1, Demo = (props) => {
+ return Test
;
+}
+
+Demo.staticMethod = () => {
+ console.log('static method');
+}
+
+Demo.propTypes = {
+ optionalArray: PropTypes.array,
+ optionalBool: PropTypes.bool,
+ /**
+ * desc
+ * @param {string} title - The title of the book.
+ * @param {string} author - The author of the book.
+ * @returns {any}
+ */
+ optionalFunc: PropTypes.func,
+ optionalNumber: PropTypes.number,
+ optionalObject: PropTypes.object,
+ optionalString: PropTypes.string,
+ optionalSymbol: PropTypes.symbol,
+
+ // Anything that can be rendered: numbers, strings, elements or an array
+ // (or fragment) containing these types.
+ optionalNode: PropTypes.node,
+
+ // A React element (ie. ).
+ optionalElement: PropTypes.element,
+
+ // A React element type (ie. MyComponent).
+ optionalElementType: PropTypes.elementType,
+
+ // You can also declare that a prop is an instance of a class. This uses
+ // JS's instanceof operator.
+ optionalMessage: PropTypes.instanceOf(Demo),
+
+ // You can ensure that your prop is limited to specific values by treating
+ // it as an enum.
+ optionalEnum: PropTypes.oneOf(['News', 'Photos']),
+
+ // An object that could be one of many types
+ optionalUnion: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.instanceOf(Demo),
+ ]),
+
+ // An array of a certain type
+ optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
+
+ // An object with property values of a certain type
+ optionalObjectOf: PropTypes.objectOf(PropTypes.number),
+
+ // You can chain any of the above with `isRequired` to make sure a warning
+ // is shown if the prop isn't provided.
+
+ // An object taking on a particular shape
+ optionalObjectWithShape: PropTypes.shape({
+ optionalProperty: PropTypes.string,
+ requiredProperty: PropTypes.number.isRequired,
+ }),
+
+ optionalObjectWithShape2: PropTypes.shape({
+ optionalProperty: PropTypes.string,
+ requiredProperty: PropTypes.number.isRequired,
+ }).isRequired,
+
+ // An object with warnings on extra properties
+ optionalObjectWithStrictShape: PropTypes.exact({
+ optionalProperty: PropTypes.string,
+ requiredProperty: PropTypes.number.isRequired,
+ }),
+
+ requiredFunc: PropTypes.func.isRequired,
+
+ // A value of any data type
+ requiredAny: PropTypes.any.isRequired,
+};
+
+Demo.defaultProps = {};
+
+export default Demo;
diff --git a/packages/material-parser/test/fixtures/single-exported-component/src/main.scss b/packages/material-parser/test/fixtures/single-exported-component/src/main.scss
new file mode 100644
index 000000000..ac45616a5
--- /dev/null
+++ b/packages/material-parser/test/fixtures/single-exported-component/src/main.scss
@@ -0,0 +1,11 @@
+/* 不引入依赖组件的样式,比如组件 import { Button } from '@alife/next'; */
+/* 不需要在main.scss中引入 @import '~@alife/next/lib/button/index.scss'; */
+/* 但是在lib/index.scss中需要引入 @import '~@alife/next/lib/button/index.scss'; */
+
+/* 如果需要引入主题变量引入此段 */
+// @import '~@alife/next/variables.scss';
+
+/* 组件自身样式 */
+// .custom-component {
+// color: $color-brand1-1;
+// }
diff --git a/packages/material-parser/test/fixtures/transpiled-component/package.json b/packages/material-parser/test/fixtures/transpiled-component/package.json
new file mode 100644
index 000000000..f718be664
--- /dev/null
+++ b/packages/material-parser/test/fixtures/transpiled-component/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "transpiled-component",
+ "version": "1.0.0",
+ "main": "lib/index.js",
+ "dependencies": {
+ "react": "^16.0.0"
+ }
+}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/ts-component/package.json b/packages/material-parser/test/fixtures/ts-component/package.json
new file mode 100644
index 000000000..dd2cf3c82
--- /dev/null
+++ b/packages/material-parser/test/fixtures/ts-component/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "ts-component",
+ "description": "",
+ "version": "1.0.0",
+ "module": "src/index.tsx",
+ "main": "src/index.tsx",
+ "files": [
+ "demo/",
+ "lib/",
+ "es/",
+ "build/"
+ ],
+ "scripts": {
+ "postversion": "node ./scripts/postversion.js"
+ },
+ "dependencies": {
+ "prop-types": "^15.7.2",
+ "react": "^16.8.5",
+ "react-dom": "^16.8.5"
+ },
+ "devDependencies": {
+ "@types/cross-spawn": "^6.0.2",
+ "@types/prop-types": "^15.7.3",
+ "@types/react": "^16.9.46",
+ "@types/react-dom": "^16.9.8",
+ "cross-spawn": "^6.0.5"
+ },
+ "peerDependencies": {
+ "react": "^16.8.6"
+ },
+ "publishConfig": {
+ "registry": "https://registry.npm.alibaba-inc.com"
+ }
+}
diff --git a/packages/material-parser/test/fixtures/ts-component/src/index.tsx b/packages/material-parser/test/fixtures/ts-component/src/index.tsx
new file mode 100644
index 000000000..71540c1f8
--- /dev/null
+++ b/packages/material-parser/test/fixtures/ts-component/src/index.tsx
@@ -0,0 +1,9 @@
+import App from './main-module';
+import SubModule from './sub-module';
+
+App.SubModule = SubModule;
+App.defaultProps = {
+ str: 'str2',
+};
+
+export default App;
diff --git a/packages/material-parser/test/fixtures/ts-component/src/main-module.tsx b/packages/material-parser/test/fixtures/ts-component/src/main-module.tsx
new file mode 100644
index 000000000..48ea734b9
--- /dev/null
+++ b/packages/material-parser/test/fixtures/ts-component/src/main-module.tsx
@@ -0,0 +1,104 @@
+/* eslint-disable @typescript-eslint/ban-types */
+/* eslint-disable @typescript-eslint/indent */
+/* eslint-disable @typescript-eslint/no-unused-vars */
+/* eslint-disable @typescript-eslint/member-ordering */
+import * as React from 'react';
+import SubModule from './sub-module';
+
+enum Gender {
+ MALE,
+ FEMALE,
+}
+
+interface Obj {
+ s: string;
+ n: number;
+}
+
+type Func = (a: string) => JSX.Element;
+type Union =
+ | string
+ | number
+ | {
+ a: string;
+ };
+
+interface Props {
+ error(a: string): number;
+ void: void;
+ object: Object;
+ trigger?: Array<'click' | 'hover' | 'contextMenu'>;
+ str?: string;
+ num: number;
+ gender: Gender;
+ any: any;
+ bool: boolean;
+ tuple: [number, string, true];
+ enum: 'red' | 'yellow' | 'green';
+ arr: number[];
+ halfEmptyObj: {
+ [k: string]: any;
+ fun(a: string[]): void;
+ };
+ // eslint-disable-next-line @typescript-eslint/ban-types
+ emptyObj: {};
+ func(arg: string): number;
+ funcs: {
+ n(): number;
+ a(arg: string, num: number): void;
+ };
+ fuzzy:
+ | boolean
+ | 'object'
+ | number
+ | 'number'
+ | 'test'
+ | {
+ a: any;
+ sa: string[];
+ };
+ oneOf: boolean | 'test' | Obj;
+ refFunc(p: Props): void;
+ elementOrOther: JSX.Element | Func;
+ obj: {
+ a: number;
+ arrOfStr: string[];
+ arrOfObj: Obj[];
+ func: () => void;
+ };
+ objOf: {
+ [k: string]: number;
+ };
+ exact: {
+ a: number;
+ };
+ node?: React.ReactNode;
+ element?: JSX.Element;
+ elementType?: React.ElementType;
+ union: Union;
+ // eslint-disable-next-line @typescript-eslint/adjacent-overload-signatures
+ func2: Func;
+ html: HTMLBaseElement;
+ loading?: boolean | { delay?: number };
+}
+
+interface AppProps extends React.FC {
+ SubModule?: typeof SubModule;
+}
+
+const App: AppProps = React.forwardRef((props, ref: React.Ref) => {
+ return {props.str}
;
+});
+
+App.defaultProps = {
+ object: {
+ a: '1',
+ b: '2',
+ },
+ func(a: string) {
+ return 123;
+ },
+ str: 'str',
+};
+
+export default App;
diff --git a/packages/material-parser/test/fixtures/ts-component/src/sub-module.tsx b/packages/material-parser/test/fixtures/ts-component/src/sub-module.tsx
new file mode 100644
index 000000000..acea70b08
--- /dev/null
+++ b/packages/material-parser/test/fixtures/ts-component/src/sub-module.tsx
@@ -0,0 +1,22 @@
+import * as React from 'react';
+
+interface Props {
+ name: string;
+}
+
+class SubModule extends React.Component {
+ static defaultProps = {
+ name: 'abc',
+ };
+
+ render() {
+ const { name } = this.props;
+ return hello, {name}
;
+ }
+}
+
+SubModule.defaultProps = {
+ name: 'abc',
+};
+
+export default SubModule;
diff --git a/packages/material-parser/test/fixtures/ts-component2/package.json b/packages/material-parser/test/fixtures/ts-component2/package.json
new file mode 100644
index 000000000..95bb4bd8d
--- /dev/null
+++ b/packages/material-parser/test/fixtures/ts-component2/package.json
@@ -0,0 +1,63 @@
+{
+ "name": "@alife/empty",
+ "version": "1.0.1",
+ "description": "空组件",
+ "files": [
+ "demo/",
+ "es/",
+ "lib/",
+ "build/",
+ "dist",
+ "material-meta.json"
+ ],
+ "main": "src/index.tsx",
+ "module": "src/index.tsx",
+ "stylePath": "style.js",
+ "scripts": {
+ "start": "build-scripts start",
+ "build": "build-scripts build",
+ "test": "build-scripts test",
+ "prepublishOnly": "npm run build",
+ "doc": "react-doc-gen",
+ "lint": "eslint --cache --ext .js,.jsx ./"
+ },
+ "keywords": [
+ "ice",
+ "react",
+ "component"
+ ],
+ "dependencies": {
+ "classnames": "^2.2.6",
+ "prop-types": "^15.5.8"
+ },
+ "devDependencies": {
+ "@alife/build-plugin-lowcode": "^1.0.7",
+ "@alib/build-scripts": "^0.1.3",
+ "@alifd/adaptor-generate": "^0.1.3",
+ "build-plugin-component": "^0.2.0",
+ "build-plugin-fusion": "^0.1.0",
+ "build-plugin-fusion-cool": "^0.1.0",
+ "build-plugin-moment-locales": "^0.1.0",
+ "react": "^16.3.0",
+ "react-dom": "^16.3.0",
+ "@ice/spec": "^1.0.0",
+ "eslint": "^6.0.1",
+ "@alifd/next": "1.x",
+ "@types/react": "^16.9.13",
+ "@types/react-dom": "^16.9.4"
+ },
+ "peerDependencies": {
+ "react": "^16.3.0",
+ "@alifd/next": "1.x"
+ },
+ "componentConfig": {
+ "name": "Empty",
+ "title": "empty",
+ "category": "DataDisplay"
+ },
+ "publishConfig": {
+ "registry": "https://registry.npm.alibaba-inc.com"
+ },
+ "license": "MIT",
+ "homepage": "https://unpkg.alibaba-inc.com/@alife/empty@1.0.1/build/index.html"
+}
diff --git a/packages/material-parser/test/fixtures/ts-component2/src/empty.tsx b/packages/material-parser/test/fixtures/ts-component2/src/empty.tsx
new file mode 100644
index 000000000..f355d8e95
--- /dev/null
+++ b/packages/material-parser/test/fixtures/ts-component2/src/empty.tsx
@@ -0,0 +1,22 @@
+import * as React from 'react';
+import classNames from 'classnames';
+import './index';
+interface DefaultEmptyImg {
+ className?: string;
+ imageStyle?: React.CSSProperties;
+}
+
+export const DefaultEmptyImg = (props: DefaultEmptyImg) => {
+ const { className, imageStyle, ...restProps } = props;
+ const prefixCls = 'design-empty-default';
+ const alt = 'empty';
+
+ return (
+
+
+

+
+
暂时没有数据
+
+ );
+};
diff --git a/packages/material-parser/test/fixtures/ts-component2/src/index.scss b/packages/material-parser/test/fixtures/ts-component2/src/index.scss
new file mode 100644
index 000000000..e833d2c72
--- /dev/null
+++ b/packages/material-parser/test/fixtures/ts-component2/src/index.scss
@@ -0,0 +1,49 @@
+.design-empty {
+ margin: 0 8px;
+ font-size: 14px;
+ line-height: 1.5715;
+ text-align: center;
+
+ &-image {
+ height: 200px;
+ margin-bottom: 4px;
+
+ img {
+ height: 100%;
+ }
+
+ svg {
+ height: 100%;
+ margin: auto;
+ }
+ }
+
+ &-description {
+ margin: 0;
+ }
+
+ &-footer {
+ margin-top: 16px;
+ }
+}
+
+.design-empty-default {
+ margin: 0 8px;
+ font-size: 14px;
+ line-height: 1.5715;
+ text-align: center;
+
+ &-image {
+ height: 54px;
+ margin-bottom: 8px;
+
+ img {
+ height: 100%;
+ }
+ }
+
+ &-description {
+ font-size: 14px;
+ color: #c2c2c2;
+ }
+}
diff --git a/packages/material-parser/test/fixtures/ts-component2/src/index.tsx b/packages/material-parser/test/fixtures/ts-component2/src/index.tsx
new file mode 100644
index 000000000..64cf75b10
--- /dev/null
+++ b/packages/material-parser/test/fixtures/ts-component2/src/index.tsx
@@ -0,0 +1,71 @@
+import * as React from 'react';
+import classNames from 'classnames';
+import { DefaultEmptyImg } from './empty';
+
+export interface EmptyProps extends React.HTMLAttributes {
+ className?: string;
+ style?: React.CSSProperties;
+ imageStyle?: React.CSSProperties;
+ image?: React.ReactNode | string;
+ description?: React.ReactNode;
+ children?: React.ReactNode;
+ type?: 'default' | 'custom'; // default 默认, custom 表示自定义
+}
+
+const prefixCls = 'design-empty';
+interface EmptyType extends React.FC {
+ IMAGE_TYPE_SERVERBUSY: string; //服务器繁忙
+ IMAGE_TYPE_SERVERNOFOUND: string; // 404
+ IMAGE_TYPE_FILENOFOUND: string; //文件不存在
+ IMAGE_TYPE_PROJECTNOFOUND: string; // 项目不存在
+ IMAGE_TYPE_EMPTY: string; //空
+}
+
+const Empty: EmptyType = (props: EmptyProps) => {
+ const {
+ className,
+ image = 'Empty.IMAGE_TYPE_EMPTY',
+ description,
+ children,
+ imageStyle,
+ type = 'custom',
+ ...restProps
+ } = props;
+
+ if (type === 'default') {
+ return ;
+ }
+
+ let imageNode: React.ReactNode = null;
+ const alt = typeof description === 'string' ? description : 'empty';
+
+ if (typeof image === 'string') {
+ imageNode =
;
+ } else {
+ imageNode = image;
+ }
+
+ return (
+
+
+ {imageNode}
+
+ {description &&
{description}
}
+ {children &&
{children}
}
+
+ );
+};
+
+//服务器繁忙
+Empty.IMAGE_TYPE_SERVERBUSY = 'https://img.alicdn.com/tfs/TB1qPJvTFY7gK0jSZKzXXaikpXa-400-400.png';
+//404
+Empty.IMAGE_TYPE_SERVERNOFOUND =
+ 'https://img.alicdn.com/tfs/TB18gVGTUH1gK0jSZSyXXXtlpXa-400-400.png';
+//文件不存在
+Empty.IMAGE_TYPE_FILENOFOUND = 'https://img.alicdn.com/tfs/TB1.ClQTUT1gK0jSZFrXXcNCXXa-400-400.png';
+//项目不存在
+Empty.IMAGE_TYPE_PROJECTNOFOUND =
+ 'https://img.alicdn.com/tfs/TB1ZWumfcieb18jSZFvXXaI3FXa-400-400.png';
+//空
+Empty.IMAGE_TYPE_EMPTY = 'https://img.alicdn.com/tfs/TB13G0LTNv1gK0jSZFFXXb0sXXa-54-54.svg';
+export default Empty;
diff --git a/packages/material-parser/test/fixtures/without-display-name/index.js b/packages/material-parser/test/fixtures/without-display-name/index.js
new file mode 100644
index 000000000..986775591
--- /dev/null
+++ b/packages/material-parser/test/fixtures/without-display-name/index.js
@@ -0,0 +1,12 @@
+var React = require('react');
+var PropTypes = require('prop-types');
+
+module.exports = class extends React.Component {
+ static propTypes = {
+ name: PropTypes.string
+ }
+
+ render() {
+ return {this.props.name}
+ }
+}
\ No newline at end of file
diff --git a/packages/material-parser/test/fixtures/without-display-name/package.json b/packages/material-parser/test/fixtures/without-display-name/package.json
new file mode 100644
index 000000000..c02728ebe
--- /dev/null
+++ b/packages/material-parser/test/fixtures/without-display-name/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "without-display-name",
+ "version": "1.0.0",
+ "main": "index.js",
+ "dependencies": {
+ "react": "^16.0.0",
+ "prop-types": "latest"
+ }
+}
\ No newline at end of file
diff --git a/packages/material-parser/test/helpers/index.ts b/packages/material-parser/test/helpers/index.ts
new file mode 100644
index 000000000..2b0c7e70b
--- /dev/null
+++ b/packages/material-parser/test/helpers/index.ts
@@ -0,0 +1,10 @@
+import { join } from 'path';
+
+const baseDir = join(__dirname, '../fixtures');
+
+/**
+ * 从 fixtures 下获取文件完整路径
+ */
+export const getFromFixtures = (...args: string[]) => {
+ return join(baseDir, ...args);
+};
diff --git a/packages/material-parser/test/index.test.ts b/packages/material-parser/test/index.test.ts
new file mode 100644
index 000000000..7f4c03a43
--- /dev/null
+++ b/packages/material-parser/test/index.test.ts
@@ -0,0 +1,110 @@
+import { join } from 'path';
+import parse from '../src';
+import { IMaterializeOptions } from '../src/types';
+import { getFromFixtures } from './helpers';
+
+const multiExportedComptPath = getFromFixtures('multiple-exported-component');
+const singleExportedComptPath = getFromFixtures('single-exported-component');
+const tsComponent = getFromFixtures('ts-component');
+const tsComponent2 = getFromFixtures('ts-component2');
+const dtsComponent = getFromFixtures('dts-component');
+const transpiledComponent = getFromFixtures('transpiled-component');
+const withoutDisplayName = getFromFixtures('without-display-name');
+
+test('materialize single exported component by local', async done => {
+ const options: IMaterializeOptions = {
+ entry: singleExportedComptPath,
+ accesser: 'local',
+ };
+
+ const actual = await parse(options);
+
+ expect(actual).toMatchSnapshot();
+ done();
+});
+
+test('materialize multiple exported component by local', async done => {
+ const options: IMaterializeOptions = {
+ entry: multiExportedComptPath,
+ accesser: 'local',
+ };
+
+ const actual = await parse(options);
+
+ expect(actual).toMatchSnapshot();
+ done();
+});
+
+test('ts component by local', async done => {
+ const options: IMaterializeOptions = {
+ entry: tsComponent,
+ accesser: 'local',
+ };
+
+ const actual = await parse(options);
+
+ expect(actual).toMatchSnapshot();
+ done();
+});
+
+test('ts component 2 by local', async done => {
+ const options: IMaterializeOptions = {
+ entry: tsComponent2,
+ accesser: 'local',
+ };
+
+ const actual = await parse(options);
+
+ expect(actual).toMatchSnapshot();
+ done();
+});
+
+test('rax component by local', async done => {
+ const options: IMaterializeOptions = {
+ entry: 'src/index.tsx',
+ root: getFromFixtures('rax-component'),
+ accesser: 'local',
+ };
+
+ const actual = await parse(options);
+
+ expect(actual).toMatchSnapshot();
+ done();
+});
+
+test('d.ts component by local', async done => {
+ const options: IMaterializeOptions = {
+ entry: join(dtsComponent, 'src/index.jsx'),
+ root: dtsComponent,
+ accesser: 'local',
+ };
+
+ const actual = await parse(options);
+
+ expect(actual).toMatchSnapshot();
+ done();
+});
+
+test('transpiled component by local', async done => {
+ const options: IMaterializeOptions = {
+ entry: transpiledComponent,
+ accesser: 'local',
+ };
+
+ const actual = await parse(options);
+
+ expect(actual).toMatchSnapshot();
+ done();
+});
+
+test('without display name by local', async done => {
+ const options: IMaterializeOptions = {
+ entry: withoutDisplayName,
+ accesser: 'local',
+ };
+
+ const actual = await parse(options);
+
+ expect(actual).toMatchSnapshot();
+ done();
+});
diff --git a/packages/material-parser/test/localize.test.ts b/packages/material-parser/test/localize.test.ts
new file mode 100644
index 000000000..bd6ceb634
--- /dev/null
+++ b/packages/material-parser/test/localize.test.ts
@@ -0,0 +1,6 @@
+import {getPkgNameAndVersion} from '../src/localize';
+
+test('getPkgNameAndVersion from string', () => {
+ const result = getPkgNameAndVersion('react');
+ expect(result).toEqual({"name": "react"});
+});
\ No newline at end of file
diff --git a/packages/material-parser/test/online.test.ts b/packages/material-parser/test/online.test.ts
new file mode 100644
index 000000000..8a67f1975
--- /dev/null
+++ b/packages/material-parser/test/online.test.ts
@@ -0,0 +1,53 @@
+import { remove } from 'fs-extra';
+import parse from '../src';
+import { IMaterializeOptions } from '../src/types';
+
+test('materialize react-color by online', async (done) => {
+ const options: IMaterializeOptions = {
+ entry: 'react-color@2.19.3',
+ accesser: 'online',
+ };
+
+ const actual = await parse(options);
+ expect(actual).toMatchSnapshot();
+ done();
+});
+
+test('materialize mc-hello by online', async (done) => {
+ const options: IMaterializeOptions = {
+ entry: 'mc-hello@1.0.1',
+ accesser: 'online',
+ };
+
+ const actual = await parse(options);
+ expect(actual).toMatchSnapshot();
+ done();
+});
+
+test('materialize rc-picker by online', async (done) => {
+ const options: IMaterializeOptions = {
+ entry: 'rc-picker@2.4.3',
+ accesser: 'online',
+ };
+
+ const actual = await parse(options);
+ expect(actual).toMatchSnapshot();
+ done();
+});
+
+test('materialize online rax module by path & specify workDir', async (done) => {
+ const tempDir = './test/temp';
+ const options: IMaterializeOptions = {
+ name: 'rax-view',
+ version: '2.2.1',
+ entry: './es/common/index.d.ts',
+ accesser: 'online',
+ dslType: 'rax',
+ tempDir,
+ };
+
+ const actual = await parse(options);
+ await remove(tempDir);
+ expect(actual).toMatchSnapshot();
+ done();
+});
diff --git a/packages/material-parser/test/validate/__snapshots__/index.test.ts.snap b/packages/material-parser/test/validate/__snapshots__/index.test.ts.snap
new file mode 100644
index 000000000..00fbd81fe
--- /dev/null
+++ b/packages/material-parser/test/validate/__snapshots__/index.test.ts.snap
@@ -0,0 +1,23 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should be right in dir basic-error 1`] = `
+"[
+ {
+ \\"keyword\\": \\"required\\",
+ \\"dataPath\\": \\"\\",
+ \\"schemaPath\\": \\"#/required\\",
+ \\"params\\": {
+ \\"missingProperty\\": \\"props\\"
+ },
+ \\"message\\": \\"should have required property 'props'\\"
+ }
+]"
+`;
+
+exports[`should be right in dir basic-success 1`] = `true`;
+
+exports[`should be right in dir configure 1`] = `true`;
+
+exports[`should be right in dir props-basic-type 1`] = `true`;
+
+exports[`should be right in dir props-complex-type 1`] = `true`;
diff --git a/packages/material-parser/test/validate/fixtures/basic-error/schema.json b/packages/material-parser/test/validate/fixtures/basic-error/schema.json
new file mode 100644
index 000000000..d1c6f5d8d
--- /dev/null
+++ b/packages/material-parser/test/validate/fixtures/basic-error/schema.json
@@ -0,0 +1,18 @@
+{
+ "componentName": "Select",
+ "title": "下拉选择器",
+ "description": "适用于下拉选择,下拉多选等场景",
+ "tags": ["xx", "yy"],
+ "docUrl": "https://fusion-demo.alibaba-inc.com/demos/next/select",
+ "screenshot": "https://img.alicdn.com/tfs/TB1osvGNXzqK1RjSZFoXXbfcXXa-1149-854.png",
+ "icon": "url/fsdfasdfa.svg",
+ "devMode": "proCode",
+ "npm": {
+ "package": "@ali/deep",
+ "exportName": "Button",
+ "subName": "Icon.Option",
+ "main": "",
+ "destructuring": true,
+ "version": "0.1.13"
+ }
+}
\ No newline at end of file
diff --git a/packages/material-parser/test/validate/fixtures/basic-success/schema.json b/packages/material-parser/test/validate/fixtures/basic-success/schema.json
new file mode 100644
index 000000000..3b0f63b83
--- /dev/null
+++ b/packages/material-parser/test/validate/fixtures/basic-success/schema.json
@@ -0,0 +1,19 @@
+{
+ "componentName": "Select",
+ "title": "下拉选择器",
+ "description": "适用于下拉选择,下拉多选等场景",
+ "tags": ["xx", "yy"],
+ "docUrl": "https://fusion-demo.alibaba-inc.com/demos/next/select",
+ "screenshot": "https://img.alicdn.com/tfs/TB1osvGNXzqK1RjSZFoXXbfcXXa-1149-854.png",
+ "icon": "url/fsdfasdfa.svg",
+ "devMode": "proCode",
+ "npm": {
+ "package": "@ali/deep",
+ "exportName": "Button",
+ "subName": "Icon.Option",
+ "main": "",
+ "destructuring": true,
+ "version": "0.1.13"
+ },
+ "props": []
+}
diff --git a/packages/material-parser/test/validate/fixtures/configure/schema.json b/packages/material-parser/test/validate/fixtures/configure/schema.json
new file mode 100644
index 000000000..0bdce1623
--- /dev/null
+++ b/packages/material-parser/test/validate/fixtures/configure/schema.json
@@ -0,0 +1,68 @@
+{
+ "componentName": "Select",
+ "title": "下拉选择器",
+ "description": "适用于下拉选择,下拉多选等场景",
+ "tags": ["xx", "yy"],
+ "docUrl": "https://fusion-demo.alibaba-inc.com/demos/next/select",
+ "screenshot": "https://img.alicdn.com/tfs/TB1osvGNXzqK1RjSZFoXXbfcXXa-1149-854.png",
+ "icon": "url/fsdfasdfa.svg",
+ "devMode": "proCode",
+ "npm": {
+ "package": "@ali/deep",
+ "exportName": "Button",
+ "subName": "Icon.Option",
+ "main": "",
+ "destructuring": true,
+ "version": "0.1.13"
+ },
+ "props": [],
+ "configure": {
+ "props": [
+ {
+ "type": "field",
+ "title": "field",
+ "name": "field",
+ "setter": {
+ "componentName": "Mixin",
+ "props": {
+ "onlyChangeType": false,
+ "defaultType": "Input",
+ "typeMap": {
+ "Input": {},
+ "Select": {}
+ }
+ }
+ }
+ },
+ {
+ "type": "group",
+ "title": "group",
+ "items": [
+ {
+ "type": "field",
+ "componentName": "Function",
+ "props": {
+ "defaultValue": "function(){ console.log('aloha') }"
+ }
+ },
+ {
+ "type": "field",
+ "componentName": "Number",
+ "props": {
+ "value": 123
+ }
+ }
+ ]
+ }
+ ],
+ "component": {
+ "isContainer": true,
+ "isModal": false,
+ "descriptor": "title",
+ "nestingRule": {
+ "childWhitelist": ["SelectOption"],
+ "parentWhitelist": ["Select", "Table"]
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/material-parser/test/validate/fixtures/props-basic-type/schema.json b/packages/material-parser/test/validate/fixtures/props-basic-type/schema.json
new file mode 100644
index 000000000..e8fecb328
--- /dev/null
+++ b/packages/material-parser/test/validate/fixtures/props-basic-type/schema.json
@@ -0,0 +1,71 @@
+{
+ "componentName": "Select",
+ "title": "下拉选择器",
+ "description": "适用于下拉选择,下拉多选等场景",
+ "tags": ["xx", "yy"],
+ "docUrl": "https://fusion-demo.alibaba-inc.com/demos/next/select",
+ "screenshot": "https://img.alicdn.com/tfs/TB1osvGNXzqK1RjSZFoXXbfcXXa-1149-854.png",
+ "icon": "url/fsdfasdfa.svg",
+ "devMode": "proCode",
+ "npm": {
+ "package": "@ali/deep",
+ "exportName": "Button",
+ "subName": "Icon.Option",
+ "main": "",
+ "destructuring": true,
+ "version": "0.1.13"
+ },
+ "props": [
+ {
+ "name": "placeholder",
+ "propType": "string",
+ "description": "占位提示",
+ "defaultValue": "请输入..."
+ },
+ {
+ "name": "disabled",
+ "propType": "bool",
+ "description": "disabled",
+ "defaultValue": false
+ },
+ {
+ "name": "size",
+ "propType": "number",
+ "description": "尺寸",
+ "defaultValue": 10
+ },
+ {
+ "name": "dataSource",
+ "propType": "array",
+ "description": "下拉选项配置",
+ "defaultValue": []
+ },
+ {
+ "name": "object",
+ "propType": "object",
+ "description": "object",
+ "defaultValue": {
+ "a": 123,
+ "b": 234
+ }
+ },
+ {
+ "name": "node",
+ "propType": "node",
+ "description": "node"
+ },
+ {
+ "name": "element",
+ "propType": "element",
+ "description": "element"
+ },
+ {
+ "name": "onClick",
+ "propType": {
+ "type": "func",
+ "isRequired": true
+ },
+ "description": "下拉选项配置"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/material-parser/test/validate/fixtures/props-complex-type/schema.json b/packages/material-parser/test/validate/fixtures/props-complex-type/schema.json
new file mode 100644
index 000000000..fdb40a5af
--- /dev/null
+++ b/packages/material-parser/test/validate/fixtures/props-complex-type/schema.json
@@ -0,0 +1,95 @@
+{
+ "componentName": "Select",
+ "title": "下拉选择器",
+ "description": "适用于下拉选择,下拉多选等场景",
+ "tags": ["xx", "yy"],
+ "docUrl": "https://fusion-demo.alibaba-inc.com/demos/next/select",
+ "screenshot": "https://img.alicdn.com/tfs/TB1osvGNXzqK1RjSZFoXXbfcXXa-1149-854.png",
+ "icon": "url/fsdfasdfa.svg",
+ "devMode": "proCode",
+ "npm": {
+ "package": "@ali/deep",
+ "exportName": "Button",
+ "subName": "Icon.Option",
+ "main": "",
+ "destructuring": true,
+ "version": "0.1.13"
+ },
+ "props": [
+ {
+ "name": "oneOf",
+ "propType": {
+ "type": "oneOf",
+ "value": ["a", "b", "c"]
+ }
+ },
+ {
+ "name": "oneOfType",
+ "propType": {
+ "type": "oneOfType",
+ "value": ["string", "number", {
+ "type": "array",
+ "isRequired": true
+ }]
+ }
+ },
+ {
+ "name": "arrayOf",
+ "propType": "number"
+ },
+ {
+ "name": "objectOf",
+ "propType": "number"
+ },
+ {
+ "name": "size",
+ "propType": "number",
+ "description": "尺寸",
+ "defaultValue": 10
+ },
+ {
+ "name": "dataSource",
+ "propType": "array",
+ "description": "下拉选项配置",
+ "defaultValue": []
+ },
+ {
+ "name": "shape",
+ "propType": {
+ "type": "shape",
+ "value": [
+ {
+ "name": "color",
+ "propType": "string"
+ },
+ {
+ "name": "fontSize",
+ "propType": {
+ "type": "number",
+ "isRequired": true
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "exact",
+ "propType": {
+ "type": "exact",
+ "value": [
+ {
+ "name": "name",
+ "propType": "string"
+ },
+ {
+ "name": "quantity",
+ "propType": {
+ "type": "number",
+ "isRequired": true
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/material-parser/test/validate/index.test.ts b/packages/material-parser/test/validate/index.test.ts
new file mode 100644
index 000000000..68bb5dc1b
--- /dev/null
+++ b/packages/material-parser/test/validate/index.test.ts
@@ -0,0 +1,25 @@
+import * as fs from 'fs';
+import yaml = require('js-yaml');
+import path = require('path');
+import {validate} from '../../src'
+
+let fixtures = fs.readdirSync(path.join(__dirname, 'fixtures'));
+fixtures = fixtures.filter(item => !item.includes('.skip'));
+if (fixtures.find(item => item.includes('.only'))) {
+ fixtures = fixtures.filter(item => item.includes('.only'));
+}
+
+for (const dir of fixtures) {
+ const fullPath = path.join(__dirname, 'fixtures', dir);
+ test(`should be right in dir ${dir}`, async (done) => {
+ const json: any = yaml.safeLoad(fs.readFileSync(path.resolve(fullPath, 'schema.json'), 'utf-8'));
+ let validateResult: any;
+ try {
+ validateResult = validate(json)
+ } catch (e) {
+ validateResult = e.message;
+ }
+ expect(validateResult).toMatchSnapshot();
+ done();
+ });
+}
diff --git a/packages/material-parser/tsconfig.json b/packages/material-parser/tsconfig.json
new file mode 100644
index 000000000..d47e50fd1
--- /dev/null
+++ b/packages/material-parser/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ // Enable strictest settings like strictNullChecks & noImplicitAny.
+ "strict": false,
+ // Allow json import
+ "resolveJsonModule": true,
+ // skip type checking of declaration files
+ "skipLibCheck": true,
+ "baseUrl": "./packages",
+ "allowJs": true
+ },
+ "exclude": ["**/test", "**/lib", "**/dist", "**/es", "node_modules", "schemas"],
+ "include": ["src/**/*"]
+}
diff --git a/packages/material-parser/webpack.config.js b/packages/material-parser/webpack.config.js
new file mode 100644
index 000000000..5132d598e
--- /dev/null
+++ b/packages/material-parser/webpack.config.js
@@ -0,0 +1,40 @@
+const path = require('path');
+const nodeExternals = require('webpack-node-externals');
+const CopyPlugin = require('copy-webpack-plugin');
+
+module.exports = {
+ entry: './src/index.ts',
+ target: 'node',
+ output: {
+ path: path.resolve(__dirname, 'dist'),
+ filename: 'index.js',
+ library: {
+ type: 'commonjs2',
+ },
+ },
+ mode: 'production',
+ module: {
+ rules: [
+ {
+ test: /\.tsx?$/,
+ use: 'ts-loader',
+ exclude: /node_modules/,
+ },
+ ],
+ },
+ externalsPresets: { node: true }, // in order to ignore built-in modules like path, fs, etc.
+ externals: [nodeExternals()], // in order to ignore all modules in node_modules folder
+ resolve: {
+ extensions: ['.tsx', '.ts', '.js'],
+ },
+ plugins: [
+ new CopyPlugin({
+ patterns: [
+ {
+ from: path.resolve(__dirname, 'src/parse/ts/tsconfig.json'),
+ to: path.resolve(__dirname, 'dist/tsconfig.json'),
+ },
+ ],
+ }),
+ ],
+};