From a802418d65013c2cc8317d10e65a0314ed9c0e63 Mon Sep 17 00:00:00 2001 From: "gengyang.gy" Date: Wed, 29 Dec 2021 20:52:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20material-parser=20?= =?UTF-8?q?=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/material-parser/CHANGELOG.md | 370 ++ packages/material-parser/README.md | 16 + packages/material-parser/build.test.json | 5 + packages/material-parser/demo/component.jsx | 81 + packages/material-parser/demo/index.js | 11 + packages/material-parser/jest.config.js | 20 + packages/material-parser/package.json | 65 + packages/material-parser/schemas/schema.json | 537 ++ packages/material-parser/schemas/schema.yml | 351 + packages/material-parser/scripts/transform.js | 27 + packages/material-parser/src/core/index.ts | 10 + .../material-parser/src/core/schema/types.ts | 163 + packages/material-parser/src/generate.ts | 65 + packages/material-parser/src/index.ts | 70 + packages/material-parser/src/localize.ts | 126 + .../src/parse/dynamic/index.ts | 121 + .../src/parse/dynamic/requireInSandbox.ts | 37 + packages/material-parser/src/parse/index.ts | 80 + .../parse/js/handlers/defaultPropsHandler.ts | 138 + .../src/parse/js/handlers/index.ts | 22 + .../parse/js/handlers/preProcessHandler.ts | 3 + .../src/parse/js/handlers/propTypeHandler.ts | 139 + .../parse/js/handlers/propTypeJsDocHandler.ts | 64 + .../material-parser/src/parse/js/index.ts | 42 + .../src/parse/js/resolver/checkIsIIFE.ts | 8 + .../parse/js/resolver/findAssignedMethods.ts | 37 + .../src/parse/js/resolver/index.ts | 393 ++ .../resolver/isReactComponentStaticMember.ts | 14 + .../src/parse/js/resolver/isStaticMethod.ts | 15 + .../js/resolver/resolveExportDeclaration.ts | 53 + .../src/parse/js/resolver/resolveHOC.ts | 42 + .../src/parse/js/resolver/resolveIIFE.ts | 20 + .../src/parse/js/resolver/resolveImport.ts | 178 + .../js/resolver/resolveTranspiledClass.ts | 31 + .../src/parse/js/utils/cache.ts | 18 + .../src/parse/js/utils/evaluate.ts | 103 + .../src/parse/js/utils/findJSFilePath.ts | 15 + .../src/parse/js/utils/getComposedPath.ts | 51 + .../src/parse/js/utils/getName.ts | 13 + .../src/parse/js/utils/getRoot.ts | 7 + .../src/parse/js/utils/makeProxy.ts | 23 + .../material-parser/src/parse/transform.ts | 306 + .../src/parse/ts/generateDTS.ts | 56 + .../material-parser/src/parse/ts/index.ts | 611 ++ .../src/parse/ts/tsconfig.json | 11 + packages/material-parser/src/scan.ts | 78 + packages/material-parser/src/types/Basic.ts | 5 + .../material-parser/src/types/ChannelType.ts | 9 + packages/material-parser/src/types/DSLType.ts | 4 + .../material-parser/src/types/IAccesser.ts | 14 + .../src/types/IExtensionConfigManifest.ts | 13 + .../src/types/IMaterialParsedModel.ts | 22 + .../src/types/IMaterialScanModel.ts | 23 + .../src/types/IMaterializeOptions.ts | 117 + packages/material-parser/src/types/Meta.ts | 14 + packages/material-parser/src/types/index.ts | 8 + packages/material-parser/src/utils.ts | 129 + .../material-parser/src/validate/index.ts | 14 + .../material-parser/src/validate/schema.json | 548 ++ .../test/__snapshots__/dynamic.test.ts.snap | 27 + .../test/__snapshots__/index.test.ts.snap | 1753 +++++ .../test/__snapshots__/online.test.ts.snap | 5780 +++++++++++++++++ packages/material-parser/test/dynamic.test.ts | 14 + .../test/fixtures/dts-component/index.d.ts | 168 + .../test/fixtures/dts-component/package.json | 5 + .../test/fixtures/dts-component/src/data.js | 1264 ++++ .../test/fixtures/dts-component/src/i18n.js | 27 + .../test/fixtures/dts-component/src/index.jsx | 142 + .../test/fixtures/dts-component/src/main.scss | 40 + .../dts-component/src/scss/variable.scss | 12 + .../es/basic/AIMakeBlank/amContainer.js | 11 + .../es/basic/AIMakeBlank/amManifest.js | 144 + .../es/basic/AIMakeBlank/container.js | 6 + .../es/basic/AIMakeBlank/index.js | 74 + .../es/basic/AIMakeBlank/manifest.js | 1 + .../es/basic/AIMakeBlank/manifest.json | 1 + .../es/basic/AIMakeIcon/IconFont.js | 67 + .../es/basic/AIMakeIcon/amContainer.js | 13 + .../es/basic/AIMakeIcon/amManifest.js | 82 + .../es/basic/AIMakeIcon/container.js | 6 + .../es/basic/AIMakeIcon/index.js | 71 + .../es/basic/AIMakeIcon/manifest.js | 1 + .../es/basic/AIMakeIcon/manifest.json | 1 + .../es/basic/AIMakeImage/amContainer.js | 11 + .../es/basic/AIMakeImage/amManifest.js | 86 + .../es/basic/AIMakeImage/container.js | 6 + .../es/basic/AIMakeImage/index.js | 54 + .../es/basic/AIMakeImage/manifest.js | 1 + .../es/basic/AIMakeImage/manifest.json | 1 + .../es/basic/AIMakeLink/amContainer.js | 11 + .../es/basic/AIMakeLink/amManifest.js | 102 + .../es/basic/AIMakeLink/container.js | 6 + .../es/basic/AIMakeLink/index.js | 73 + .../es/basic/AIMakeLink/manifest.js | 1 + .../es/basic/AIMakeLink/manifest.json | 1 + .../es/basic/AIMakePlaceholder/amContainer.js | 11 + .../es/basic/AIMakePlaceholder/amManifest.js | 102 + .../es/basic/AIMakePlaceholder/container.js | 6 + .../es/basic/AIMakePlaceholder/index.js | 65 + .../es/basic/AIMakePlaceholder/manifest.js | 1 + .../es/basic/AIMakePlaceholder/manifest.json | 1 + .../es/basic/AIMakeText/amContainer.js | 11 + .../es/basic/AIMakeText/amManifest.js | 115 + .../es/basic/AIMakeText/container.js | 6 + .../es/basic/AIMakeText/index.js | 95 + .../es/basic/AIMakeText/manifest.js | 1 + .../es/basic/AIMakeText/manifest.json | 1 + .../es/basic/Root/amContainer.js | 11 + .../es/basic/Root/amManifest.js | 25 + .../es/basic/Root/container.js | 6 + .../es/basic/Root/index.js | 51 + .../es/basic/Root/manifest.js | 1 + .../es/basic/Root/manifest.json | 1 + .../es/basic/style/index.css | 15 + .../es/basic/style/index.js | 1 + .../es/basic/style/index.less | 8 + .../es/basic/utils/HOCBackgroundProps.js | 74 + .../es/basic/utils/HOCBoxModelProps.js | 103 + .../es/basic/utils/HOCFlexLayoutProps.js | 90 + .../es/basic/utils/HOCLayoutProps.js | 82 + .../es/basic/utils/HOCTextProps.js | 82 + .../multiple-exported-component/es/index.js | 9 + .../multiple-exported-component/package.json | 22 + .../src/basic/AIMakeBlank/amContainer.js | 6 + .../src/basic/AIMakeBlank/amManifest.js | 158 + .../src/basic/AIMakeBlank/container.js | 5 + .../src/basic/AIMakeBlank/index.js | 61 + .../src/basic/AIMakeBlank/manifest.js | 1 + .../src/basic/AIMakeBlank/manifest.json | 1 + .../src/basic/AIMakeIcon/IconFont.js | 51 + .../src/basic/AIMakeIcon/amContainer.js | 7 + .../src/basic/AIMakeIcon/amManifest.js | 89 + .../src/basic/AIMakeIcon/container.js | 5 + .../src/basic/AIMakeIcon/index.js | 59 + .../src/basic/AIMakeIcon/manifest.js | 1 + .../src/basic/AIMakeIcon/manifest.json | 1 + .../src/basic/AIMakeImage/amContainer.js | 6 + .../src/basic/AIMakeImage/amManifest.js | 99 + .../src/basic/AIMakeImage/container.js | 5 + .../src/basic/AIMakeImage/index.js | 26 + .../src/basic/AIMakeImage/manifest.js | 1 + .../src/basic/AIMakeImage/manifest.json | 1 + .../src/basic/AIMakeLink/amContainer.js | 6 + .../src/basic/AIMakeLink/amManifest.js | 115 + .../src/basic/AIMakeLink/container.js | 5 + .../src/basic/AIMakeLink/index.js | 57 + .../src/basic/AIMakeLink/manifest.js | 1 + .../src/basic/AIMakeLink/manifest.json | 1 + .../basic/AIMakePlaceholder/amContainer.js | 6 + .../src/basic/AIMakePlaceholder/amManifest.js | 115 + .../src/basic/AIMakePlaceholder/container.js | 5 + .../src/basic/AIMakePlaceholder/index.js | 45 + .../src/basic/AIMakePlaceholder/manifest.js | 1 + .../src/basic/AIMakePlaceholder/manifest.json | 1 + .../src/basic/AIMakeText/amContainer.js | 6 + .../src/basic/AIMakeText/amManifest.js | 119 + .../src/basic/AIMakeText/container.js | 5 + .../src/basic/AIMakeText/index.js | 72 + .../src/basic/AIMakeText/manifest.js | 1 + .../src/basic/AIMakeText/manifest.json | 1 + .../src/basic/Root/amContainer.js | 6 + .../src/basic/Root/amManifest.js | 29 + .../src/basic/Root/container.js | 5 + .../src/basic/Root/index.js | 29 + .../src/basic/Root/manifest.js | 1 + .../src/basic/Root/manifest.json | 1 + .../src/basic/style/index.js | 1 + .../src/basic/style/index.less | 8 + .../src/basic/utils/HOCBackgroundProps.js | 44 + .../src/basic/utils/HOCBoxModelProps.js | 75 + .../src/basic/utils/HOCFlexLayoutProps.js | 61 + .../src/basic/utils/HOCLayoutProps.js | 52 + .../src/basic/utils/HOCTextProps.js | 52 + .../multiple-exported-component/src/index.js | 17 + .../test/fixtures/rax-component/package.json | 65 + .../test/fixtures/rax-component/src/index.css | 5 + .../test/fixtures/rax-component/src/index.tsx | 22 + .../single-exported-component/es/container.js | 6 + .../single-exported-component/es/index.js | 97 + .../single-exported-component/es/main.css | 6 + .../single-exported-component/es/main.scss | 11 + .../single-exported-component/es/manifest.js | 1 + .../es/manifest.json | 1 + .../single-exported-component/package.json | 30 + .../single-exported-component/src/index.js | 90 + .../single-exported-component/src/main.scss | 11 + .../transpiled-component/package.json | 8 + .../test/fixtures/ts-component/package.json | 34 + .../test/fixtures/ts-component/src/index.tsx | 9 + .../fixtures/ts-component/src/main-module.tsx | 104 + .../fixtures/ts-component/src/sub-module.tsx | 22 + .../test/fixtures/ts-component2/package.json | 63 + .../test/fixtures/ts-component2/src/empty.tsx | 22 + .../fixtures/ts-component2/src/index.scss | 49 + .../test/fixtures/ts-component2/src/index.tsx | 71 + .../fixtures/without-display-name/index.js | 12 + .../without-display-name/package.json | 9 + .../material-parser/test/helpers/index.ts | 10 + packages/material-parser/test/index.test.ts | 110 + .../material-parser/test/localize.test.ts | 6 + packages/material-parser/test/online.test.ts | 53 + .../validate/__snapshots__/index.test.ts.snap | 23 + .../validate/fixtures/basic-error/schema.json | 18 + .../fixtures/basic-success/schema.json | 19 + .../validate/fixtures/configure/schema.json | 68 + .../fixtures/props-basic-type/schema.json | 71 + .../fixtures/props-complex-type/schema.json | 95 + .../test/validate/index.test.ts | 25 + packages/material-parser/tsconfig.json | 15 + packages/material-parser/webpack.config.js | 40 + 210 files changed, 19452 insertions(+) create mode 100644 packages/material-parser/CHANGELOG.md create mode 100644 packages/material-parser/README.md create mode 100644 packages/material-parser/build.test.json create mode 100644 packages/material-parser/demo/component.jsx create mode 100644 packages/material-parser/demo/index.js create mode 100644 packages/material-parser/jest.config.js create mode 100644 packages/material-parser/package.json create mode 100644 packages/material-parser/schemas/schema.json create mode 100644 packages/material-parser/schemas/schema.yml create mode 100644 packages/material-parser/scripts/transform.js create mode 100644 packages/material-parser/src/core/index.ts create mode 100644 packages/material-parser/src/core/schema/types.ts create mode 100644 packages/material-parser/src/generate.ts create mode 100644 packages/material-parser/src/index.ts create mode 100644 packages/material-parser/src/localize.ts create mode 100644 packages/material-parser/src/parse/dynamic/index.ts create mode 100644 packages/material-parser/src/parse/dynamic/requireInSandbox.ts create mode 100644 packages/material-parser/src/parse/index.ts create mode 100644 packages/material-parser/src/parse/js/handlers/defaultPropsHandler.ts create mode 100644 packages/material-parser/src/parse/js/handlers/index.ts create mode 100644 packages/material-parser/src/parse/js/handlers/preProcessHandler.ts create mode 100644 packages/material-parser/src/parse/js/handlers/propTypeHandler.ts create mode 100644 packages/material-parser/src/parse/js/handlers/propTypeJsDocHandler.ts create mode 100644 packages/material-parser/src/parse/js/index.ts create mode 100644 packages/material-parser/src/parse/js/resolver/checkIsIIFE.ts create mode 100644 packages/material-parser/src/parse/js/resolver/findAssignedMethods.ts create mode 100644 packages/material-parser/src/parse/js/resolver/index.ts create mode 100644 packages/material-parser/src/parse/js/resolver/isReactComponentStaticMember.ts create mode 100644 packages/material-parser/src/parse/js/resolver/isStaticMethod.ts create mode 100644 packages/material-parser/src/parse/js/resolver/resolveExportDeclaration.ts create mode 100644 packages/material-parser/src/parse/js/resolver/resolveHOC.ts create mode 100644 packages/material-parser/src/parse/js/resolver/resolveIIFE.ts create mode 100644 packages/material-parser/src/parse/js/resolver/resolveImport.ts create mode 100644 packages/material-parser/src/parse/js/resolver/resolveTranspiledClass.ts create mode 100644 packages/material-parser/src/parse/js/utils/cache.ts create mode 100644 packages/material-parser/src/parse/js/utils/evaluate.ts create mode 100644 packages/material-parser/src/parse/js/utils/findJSFilePath.ts create mode 100644 packages/material-parser/src/parse/js/utils/getComposedPath.ts create mode 100644 packages/material-parser/src/parse/js/utils/getName.ts create mode 100644 packages/material-parser/src/parse/js/utils/getRoot.ts create mode 100644 packages/material-parser/src/parse/js/utils/makeProxy.ts create mode 100644 packages/material-parser/src/parse/transform.ts create mode 100644 packages/material-parser/src/parse/ts/generateDTS.ts create mode 100644 packages/material-parser/src/parse/ts/index.ts create mode 100644 packages/material-parser/src/parse/ts/tsconfig.json create mode 100644 packages/material-parser/src/scan.ts create mode 100644 packages/material-parser/src/types/Basic.ts create mode 100644 packages/material-parser/src/types/ChannelType.ts create mode 100644 packages/material-parser/src/types/DSLType.ts create mode 100644 packages/material-parser/src/types/IAccesser.ts create mode 100644 packages/material-parser/src/types/IExtensionConfigManifest.ts create mode 100644 packages/material-parser/src/types/IMaterialParsedModel.ts create mode 100644 packages/material-parser/src/types/IMaterialScanModel.ts create mode 100644 packages/material-parser/src/types/IMaterializeOptions.ts create mode 100644 packages/material-parser/src/types/Meta.ts create mode 100644 packages/material-parser/src/types/index.ts create mode 100644 packages/material-parser/src/utils.ts create mode 100644 packages/material-parser/src/validate/index.ts create mode 100644 packages/material-parser/src/validate/schema.json create mode 100644 packages/material-parser/test/__snapshots__/dynamic.test.ts.snap create mode 100644 packages/material-parser/test/__snapshots__/index.test.ts.snap create mode 100644 packages/material-parser/test/__snapshots__/online.test.ts.snap create mode 100644 packages/material-parser/test/dynamic.test.ts create mode 100644 packages/material-parser/test/fixtures/dts-component/index.d.ts create mode 100644 packages/material-parser/test/fixtures/dts-component/package.json create mode 100644 packages/material-parser/test/fixtures/dts-component/src/data.js create mode 100644 packages/material-parser/test/fixtures/dts-component/src/i18n.js create mode 100644 packages/material-parser/test/fixtures/dts-component/src/index.jsx create mode 100644 packages/material-parser/test/fixtures/dts-component/src/main.scss create mode 100644 packages/material-parser/test/fixtures/dts-component/src/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/amContainer.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/amManifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/container.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/manifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/manifest.json create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/IconFont.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/amContainer.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/amManifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/container.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/manifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/manifest.json create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/amContainer.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/amManifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/container.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/manifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/manifest.json create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/amContainer.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/amManifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/container.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/manifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/manifest.json create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/amContainer.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/amManifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/container.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/manifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/manifest.json create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/amContainer.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/amManifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/container.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/manifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/manifest.json create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/amContainer.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/amManifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/container.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/manifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/manifest.json create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/style/index.css create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/style/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/style/index.less create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCBackgroundProps.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCBoxModelProps.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCFlexLayoutProps.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCLayoutProps.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCTextProps.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/es/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/package.json create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/amContainer.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/amManifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/container.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/manifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/manifest.json create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/IconFont.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/amContainer.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/amManifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/container.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/manifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/manifest.json create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/amContainer.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/amManifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/container.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/manifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/manifest.json create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/amContainer.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/amManifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/container.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/manifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/manifest.json create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/amContainer.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/amManifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/container.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/manifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/manifest.json create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/amContainer.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/amManifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/container.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/manifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/manifest.json create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/amContainer.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/amManifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/container.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/manifest.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/manifest.json create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/style/index.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/style/index.less create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCBackgroundProps.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCBoxModelProps.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCFlexLayoutProps.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCLayoutProps.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCTextProps.js create mode 100644 packages/material-parser/test/fixtures/multiple-exported-component/src/index.js create mode 100644 packages/material-parser/test/fixtures/rax-component/package.json create mode 100644 packages/material-parser/test/fixtures/rax-component/src/index.css create mode 100644 packages/material-parser/test/fixtures/rax-component/src/index.tsx create mode 100644 packages/material-parser/test/fixtures/single-exported-component/es/container.js create mode 100644 packages/material-parser/test/fixtures/single-exported-component/es/index.js create mode 100644 packages/material-parser/test/fixtures/single-exported-component/es/main.css create mode 100644 packages/material-parser/test/fixtures/single-exported-component/es/main.scss create mode 100644 packages/material-parser/test/fixtures/single-exported-component/es/manifest.js create mode 100644 packages/material-parser/test/fixtures/single-exported-component/es/manifest.json create mode 100644 packages/material-parser/test/fixtures/single-exported-component/package.json create mode 100644 packages/material-parser/test/fixtures/single-exported-component/src/index.js create mode 100644 packages/material-parser/test/fixtures/single-exported-component/src/main.scss create mode 100644 packages/material-parser/test/fixtures/transpiled-component/package.json create mode 100644 packages/material-parser/test/fixtures/ts-component/package.json create mode 100644 packages/material-parser/test/fixtures/ts-component/src/index.tsx create mode 100644 packages/material-parser/test/fixtures/ts-component/src/main-module.tsx create mode 100644 packages/material-parser/test/fixtures/ts-component/src/sub-module.tsx create mode 100644 packages/material-parser/test/fixtures/ts-component2/package.json create mode 100644 packages/material-parser/test/fixtures/ts-component2/src/empty.tsx create mode 100644 packages/material-parser/test/fixtures/ts-component2/src/index.scss create mode 100644 packages/material-parser/test/fixtures/ts-component2/src/index.tsx create mode 100644 packages/material-parser/test/fixtures/without-display-name/index.js create mode 100644 packages/material-parser/test/fixtures/without-display-name/package.json create mode 100644 packages/material-parser/test/helpers/index.ts create mode 100644 packages/material-parser/test/index.test.ts create mode 100644 packages/material-parser/test/localize.test.ts create mode 100644 packages/material-parser/test/online.test.ts create mode 100644 packages/material-parser/test/validate/__snapshots__/index.test.ts.snap create mode 100644 packages/material-parser/test/validate/fixtures/basic-error/schema.json create mode 100644 packages/material-parser/test/validate/fixtures/basic-success/schema.json create mode 100644 packages/material-parser/test/validate/fixtures/configure/schema.json create mode 100644 packages/material-parser/test/validate/fixtures/props-basic-type/schema.json create mode 100644 packages/material-parser/test/validate/fixtures/props-complex-type/schema.json create mode 100644 packages/material-parser/test/validate/index.test.ts create mode 100644 packages/material-parser/tsconfig.json create mode 100644 packages/material-parser/webpack.config.js 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 ( + + {content} + + ); + } + } + + 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 AIMakeImage; + } +} + +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 ( +
+
+ {alt} +
+

暂时没有数据

+
+ ); +}; 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 = {alt}; + } 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'), + }, + ], + }), + ], +};