From 9943b910d67c3622f4ec7a5404efa5333cdc0a9b Mon Sep 17 00:00:00 2001 From: mazhaobo Date: Mon, 11 Nov 2024 16:01:53 +0800 Subject: [PATCH 01/15] chore: init modules --- modules/code-generator/.gitignore | 122 + modules/code-generator/.prettierrc.js | 7 + modules/code-generator/.versionrc | 3 + modules/code-generator/CHANGELOG.md | 266 + modules/code-generator/CONTRIBUTING.md | 40 + modules/code-generator/README.md | 123 + modules/code-generator/babel.config.js | 1 + .../bin/lowcode-code-generator.js | 52 + modules/code-generator/example-schema.json | 276 + modules/code-generator/example-schema.json5 | 276 + modules/code-generator/jest.config.js | 10 + modules/code-generator/jest.setup.js | 12 + modules/code-generator/package.json | 155 + modules/code-generator/scripts/build-cli.js | 56 + .../scripts/build-standalone-loader.js | 73 + .../scripts/build-standalone-worker.js | 107 + .../scripts/build-standalone.js | 135 + .../scripts/build-template-static-files.js | 125 + modules/code-generator/scripts/build-types | 10 + modules/code-generator/scripts/build.js | 75 + .../scripts/move-files-to-build-dest.js | 24 + .../code-generator/scripts/run-demo-project | 55 + .../code-generator/scripts/test-standalone.js | 17 + .../src/analyzer/componentAnalyzer.ts | 35 + modules/code-generator/src/cli/index.ts | 2 + .../code-generator/src/cli/init-solution.ts | 65 + modules/code-generator/src/cli/run.ts | 146 + .../src/cli/solutions/example-solution.ts | 795 +++ modules/code-generator/src/config/env.ts | 3 + modules/code-generator/src/const/file.ts | 3 + modules/code-generator/src/const/generator.ts | 129 + modules/code-generator/src/const/index.ts | 33 + .../jsx/handlers/transformJsExpression.ts | 49 + .../jsx/handlers/transformThis2Context.ts | 29 + .../src/core/jsx/util/isLiteralAtomicExpr.ts | 12 + .../core/jsx/util/isSimpleStraightLiteral.ts | 17 + .../src/generator/ChunkBuilder.ts | 123 + .../src/generator/CodeBuilder.ts | 103 + .../src/generator/ModuleBuilder.ts | 118 + .../src/generator/ProjectBuilder.ts | 372 ++ modules/code-generator/src/index.ts | 121 + .../code-generator/src/parser/SchemaParser.ts | 394 ++ .../src/plugins/common/esmodule.ts | 479 ++ .../src/plugins/common/requireUtils.ts | 25 + .../src/plugins/common/styleImport.ts | 64 + .../src/plugins/component/rax/commonDeps.ts | 35 + .../src/plugins/component/rax/const.ts | 18 + .../plugins/component/rax/containerClass.ts | 157 + .../component/rax/containerInitState.ts | 66 + .../component/rax/containerInjectContext.ts | 145 + .../rax/containerInjectDataSourceEngine.ts | 196 + .../component/rax/containerInjectUtils.ts | 69 + .../component/rax/containerLifeCycle.ts | 146 + .../plugins/component/rax/containerMethods.ts | 84 + .../src/plugins/component/rax/jsx.ts | 327 + .../src/plugins/component/react/const.ts | 9 + .../plugins/component/react/containerClass.ts | 145 + .../component/react/containerInitState.ts | 63 + .../react/containerInjectConstants.ts | 55 + .../component/react/containerInjectContext.ts | 91 + .../react/containerInjectDataSourceEngine.ts | 206 + .../component/react/containerInjectI18n.ts | 56 + .../component/react/containerInjectUtils.ts | 125 + .../component/react/containerLifeCycle.ts | 117 + .../component/react/containerMethod.ts | 70 + .../src/plugins/component/react/jsx.ts | 153 + .../component/react/reactCommonDeps.ts | 33 + .../src/plugins/component/style/css.ts | 52 + .../src/plugins/project/constants.ts | 59 + .../plugins/project/framework/icejs/index.ts | 17 + .../project/framework/icejs/plugins/entry.ts | 56 + .../framework/icejs/plugins/entryHtml.ts | 46 + .../framework/icejs/plugins/globalStyle.ts | 56 + .../framework/icejs/plugins/packageJSON.ts | 125 + .../project/framework/icejs/plugins/router.ts | 84 + .../icejs/template/files/README.md.ts | 73 + .../icejs/template/files/abc.json.ts | 17 + .../icejs/template/files/build.json.ts | 32 + .../icejs/template/files/editorconfig.ts | 25 + .../icejs/template/files/eslintignore.ts | 28 + .../icejs/template/files/eslintrc.js.ts | 16 + .../icejs/template/files/gitignore.ts | 36 + .../icejs/template/files/jsconfig.json.ts | 24 + .../icejs/template/files/prettierignore.ts | 22 + .../icejs/template/files/prettierrc.js.ts | 16 + .../components/Footer/index.jsx.ts | 25 + .../components/Footer/index.style.ts | 26 + .../BasicLayout/components/Logo/index.jsx.ts | 27 + .../components/Logo/index.style.ts | 31 + .../components/PageNav/index.jsx.ts | 81 + .../src/layouts/BasicLayout/index.jsx.ts | 92 + .../src/layouts/BasicLayout/menuConfig.js.ts | 22 + .../icejs/template/files/stylelintignore.ts | 20 + .../icejs/template/files/stylelintrc.js.ts | 16 + .../icejs/template/files/tsconfig.json.ts | 46 + .../project/framework/icejs/template/index.ts | 52 + .../framework/icejs/template/static-files.ts | 50 + .../plugins/project/framework/icejs3/index.ts | 17 + .../framework/icejs3/plugins/appConfig.ts | 50 + .../framework/icejs3/plugins/buildConfig.ts | 165 + .../framework/icejs3/plugins/globalStyle.ts | 56 + .../framework/icejs3/plugins/layout.ts | 41 + .../framework/icejs3/plugins/packageJSON.ts | 117 + .../icejs3/template/files/README.md.ts | 12 + .../icejs3/template/files/browserslistrc.ts | 14 + .../icejs3/template/files/document.ts | 41 + .../icejs3/template/files/gitignore.ts | 36 + .../components/Footer/index.jsx.ts | 25 + .../components/Footer/index.style.ts | 26 + .../BasicLayout/components/Logo/index.jsx.ts | 27 + .../components/Logo/index.style.ts | 31 + .../components/PageNav/index.jsx.ts | 79 + .../src/layouts/BasicLayout/index.jsx.ts | 92 + .../src/layouts/BasicLayout/menuConfig.js.ts | 22 + .../icejs3/template/files/tsconfig.ts | 38 + .../icejs3/template/files/typings.ts | 20 + .../framework/icejs3/template/index.ts | 57 + .../framework/icejs3/template/static-files.ts | 33 + .../plugins/project/framework/rax/index.ts | 19 + .../framework/rax/plugins/appConfig.ts | 50 + .../framework/rax/plugins/buildConfig.ts | 51 + .../project/framework/rax/plugins/entry.ts | 61 + .../framework/rax/plugins/entryDocument.ts | 63 + .../framework/rax/plugins/globalStyle.ts | 64 + .../framework/rax/plugins/packageJSON.ts | 120 + .../rax/template/files/.eslintignore.ts | 15 + .../rax/template/files/.eslintrc.js.ts | 16 + .../rax/template/files/.gitignore.ts | 16 + .../rax/template/files/.prettierignore.ts | 15 + .../rax/template/files/.prettierrc.js.ts | 16 + .../rax/template/files/.stylelintignore.ts | 15 + .../rax/template/files/.stylelintrc.js.ts | 16 + .../framework/rax/template/files/README.md.ts | 16 + .../rax/template/files/jsconfig.json.ts | 16 + .../rax/template/files/tsconfig.json.ts | 16 + .../project/framework/rax/template/index.ts | 60 + .../framework/rax/template/static-files.ts | 29 + .../rax/types/RaxFrameworkOptions.ts | 81 + .../src/plugins/project/i18n.ts | 132 + .../src/plugins/project/utils.ts | 155 + .../code-generator/src/polyfills/buffer.ts | 9 + .../code-generator/src/postprocessor/index.ts | 3 + .../src/postprocessor/prettier/index.ts | 46 + .../src/publisher/disk/index.ts | 72 + .../src/publisher/disk/utils.ts | 78 + .../code-generator/src/publisher/zip/index.ts | 72 + .../code-generator/src/publisher/zip/utils.ts | 63 + modules/code-generator/src/solutions/icejs.ts | 117 + .../code-generator/src/solutions/icejs3.ts | 113 + .../code-generator/src/solutions/rax-app.ts | 89 + .../code-generator/src/standalone-loader.ts | 133 + .../code-generator/src/standalone-worker.ts | 81 + modules/code-generator/src/standalone.ts | 120 + modules/code-generator/src/types/analyze.ts | 7 + modules/code-generator/src/types/core.ts | 255 + modules/code-generator/src/types/deps.ts | 38 + modules/code-generator/src/types/error.ts | 17 + modules/code-generator/src/types/file.ts | 14 + modules/code-generator/src/types/index.ts | 7 + .../code-generator/src/types/intermediate.ts | 83 + modules/code-generator/src/types/jsx.ts | 40 + modules/code-generator/src/types/publisher.ts | 17 + modules/code-generator/src/typings.d.ts | 1 + .../code-generator/src/utils/OrderedSet.ts | 33 + modules/code-generator/src/utils/Scope.ts | 28 + .../code-generator/src/utils/ScopeBindings.ts | 56 + modules/code-generator/src/utils/aopHelper.ts | 27 + modules/code-generator/src/utils/common.ts | 55 + .../code-generator/src/utils/compositeType.ts | 232 + .../code-generator/src/utils/dataSource.ts | 47 + modules/code-generator/src/utils/debug.ts | 3 + .../src/utils/encodeJsxAttrString.ts | 18 + modules/code-generator/src/utils/errors.ts | 26 + .../src/utils/expressionParser.ts | 386 ++ modules/code-generator/src/utils/format.ts | 12 + modules/code-generator/src/utils/index.ts | 32 + .../code-generator/src/utils/jsExpression.ts | 151 + modules/code-generator/src/utils/jsSlot.ts | 69 + .../code-generator/src/utils/jsxHelpers.ts | 11 + modules/code-generator/src/utils/nodeToJSX.ts | 416 ++ .../code-generator/src/utils/pathHelper.ts | 41 + .../code-generator/src/utils/resultHelper.ts | 251 + modules/code-generator/src/utils/schema.ts | 152 + .../src/utils/templateHelper.ts | 30 + modules/code-generator/src/utils/theme.ts | 20 + modules/code-generator/src/utils/validate.ts | 14 + modules/code-generator/src/utils/version.ts | 29 + .../code-generator/standalone-loader/index.js | 2 + .../standalone-loader/package.json | 6 + .../code-generator/standalone-worker/index.js | 6 + .../standalone-worker/package.json | 5 + modules/code-generator/standalone/index.js | 6 + .../code-generator/standalone/package.json | 5 + .../static-files/rax/.eslintignore.template | 8 + .../static-files/rax/.eslintrc.js.template | 15 + .../static-files/rax/.gitignore.template | 18 + .../static-files/rax/.prettierignore.template | 8 + .../static-files/rax/.prettierrc.js.template | 3 + .../rax/.stylelintignore.template | 8 + .../static-files/rax/.stylelintrc.js.template | 3 + .../static-files/rax/README.md.template | 15 + .../static-files/rax/jsconfig.json.template | 10 + .../static-files/rax/tsconfig.json.template | 33 + .../code-generator/tests/bugfix/.gitignore | 1 + .../tests/bugfix/i18n-with-params.schema.json | 52 + .../tests/bugfix/i18n-with-params.test.ts | 54 + .../icejs-import-wrong-naming.schema.json | 34 + .../bugfix/icejs-import-wrong-naming.test.ts | 222 + .../bugfix/icejs-js-function1.schema.json | 1308 ++++ .../tests/bugfix/icejs-js-function1.test.ts | 44 + .../icejs-missing-imports-1.schema.json | 903 +++ .../bugfix/icejs-missing-imports-1.test.ts | 44 + ...cejs-package-json-dependencies.schema.json | 57 + .../icejs-package-json-dependencies.test.ts | 50 + .../tests/bugfix/icejs-page-map1.schema.json | 47 + .../tests/bugfix/icejs-page-map1.test.ts | 38 + .../tests/bugfix/page-element1.schema.json | 844 +++ .../tests/bugfix/page-element1.test.ts | 80 + .../tests/bugfix/page-element2.schema.json | 844 +++ .../tests/bugfix/page-element2.test.ts | 80 + .../bugfix/strict-mode-context-1.schema.json | 677 ++ .../bugfix/strict-mode-context-1.test.ts | 57 + .../tolerate-eval-errors-1-loop.schema.json | 58 + .../tolerate-eval-errors-1-loop.test.ts | 52 + ...rate-eval-errors-2-nested-loop.schema.json | 70 + ...tolerate-eval-errors-2-nested-loop.test.ts | 56 + modules/code-generator/tests/cli.test.ts | 43 + .../tests/fixtures/test-cases/.gitignore | 1 + .../expected/demo-project/.browserslistrc | 3 + .../demo1/expected/demo-project/.gitignore | 25 + .../demo1/expected/demo-project/README.md | 1 + .../expected/demo-project/ice.config.mts | 89 + .../demo1/expected/demo-project/package.json | 44 + .../demo1/expected/demo-project/src/app.ts | 13 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/document.tsx | 29 + .../expected/demo-project/src/global.scss | 13 + .../demo1/expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 68 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 0 .../demo-project/src/pages/Test/index.jsx | 205 + .../demo-project/src/pages/layout.jsx | 10 + .../expected/demo-project/src/typings.d.ts | 9 + .../demo1/expected/demo-project/src/utils.js | 47 + .../test-cases/icejs3-app/demo1/schema.json5 | 276 + .../expected/demo-project/.browserslistrc | 3 + .../expected/demo-project/.gitignore | 25 + .../expected/demo-project/README.md | 1 + .../expected/demo-project/ice.config.mts | 89 + .../expected/demo-project/package.json | 48 + .../expected/demo-project/src/app.ts | 13 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/document.tsx | 29 + .../expected/demo-project/src/global.scss | 6 + .../expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 68 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Aaaa/index.css | 0 .../demo-project/src/pages/Aaaa/index.jsx | 118 + .../demo-project/src/pages/layout.jsx | 10 + .../expected/demo-project/src/typings.d.ts | 9 + .../expected/demo-project/src/utils.js | 61 + .../demo2-utils-name-alias/schema.json5 | 123 + .../expected/demo-project/.browserslistrc | 3 + .../demo2/expected/demo-project/.gitignore | 25 + .../demo2/expected/demo-project/README.md | 1 + .../expected/demo-project/ice.config.mts | 89 + .../demo2/expected/demo-project/package.json | 42 + .../demo2/expected/demo-project/src/app.ts | 13 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/document.tsx | 29 + .../expected/demo-project/src/global.scss | 13 + .../demo2/expected/demo-project/src/i18n.js | 86 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 68 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 0 .../demo-project/src/pages/Test/index.jsx | 129 + .../demo-project/src/pages/layout.jsx | 10 + .../expected/demo-project/src/typings.d.ts | 9 + .../demo2/expected/demo-project/src/utils.js | 47 + .../test-cases/icejs3-app/demo2/schema.json5 | 256 + .../expected/demo-project/.browserslistrc | 3 + .../demo3/expected/demo-project/.gitignore | 25 + .../demo3/expected/demo-project/README.md | 1 + .../expected/demo-project/ice.config.mts | 89 + .../demo3/expected/demo-project/package.json | 42 + .../demo3/expected/demo-project/src/app.ts | 13 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/document.tsx | 29 + .../expected/demo-project/src/global.scss | 13 + .../demo3/expected/demo-project/src/i18n.js | 86 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 68 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 0 .../demo-project/src/pages/Test/index.jsx | 107 + .../demo-project/src/pages/layout.jsx | 10 + .../expected/demo-project/src/typings.d.ts | 9 + .../demo3/expected/demo-project/src/utils.js | 47 + .../test-cases/icejs3-app/demo3/schema.json5 | 159 + .../expected/demo-project/.browserslistrc | 3 + .../demo4/expected/demo-project/.gitignore | 25 + .../demo4/expected/demo-project/README.md | 1 + .../expected/demo-project/ice.config.mts | 89 + .../demo4/expected/demo-project/package.json | 45 + .../demo4/expected/demo-project/src/app.ts | 13 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/document.tsx | 29 + .../expected/demo-project/src/global.scss | 6 + .../demo4/expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 68 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 8 + .../demo-project/src/pages/Test/index.jsx | 292 + .../demo-project/src/pages/layout.jsx | 10 + .../expected/demo-project/src/typings.d.ts | 9 + .../demo4/expected/demo-project/src/utils.js | 47 + .../test-cases/icejs3-app/demo4/schema.json5 | 353 + .../expected/demo-project/.browserslistrc | 3 + .../demo5/expected/demo-project/.gitignore | 25 + .../demo5/expected/demo-project/README.md | 1 + .../expected/demo-project/ice.config.mts | 89 + .../demo5/expected/demo-project/package.json | 46 + .../demo5/expected/demo-project/src/app.ts | 13 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/document.tsx | 29 + .../expected/demo-project/src/global.scss | 6 + .../demo5/expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 68 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 8 + .../demo-project/src/pages/Test/index.jsx | 389 ++ .../demo-project/src/pages/layout.jsx | 10 + .../expected/demo-project/src/typings.d.ts | 9 + .../demo5/expected/demo-project/src/utils.js | 47 + .../test-cases/icejs3-app/demo5/schema.json5 | 677 ++ .../expected/demo-project/.browserslistrc | 3 + .../expected/demo-project/.gitignore | 25 + .../expected/demo-project/README.md | 1 + .../expected/demo-project/ice.config.mts | 89 + .../expected/demo-project/package.json | 44 + .../expected/demo-project/src/app.ts | 13 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/document.tsx | 29 + .../expected/demo-project/src/global.scss | 13 + .../expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 68 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 0 .../demo-project/src/pages/Test/index.jsx | 205 + .../demo-project/src/pages/layout.jsx | 10 + .../expected/demo-project/src/typings.d.ts | 9 + .../expected/demo-project/src/utils.js | 47 + .../demo6-literal-condition/schema.json5 | 273 + .../expected/demo-project/.browserslistrc | 3 + .../expected/demo-project/.gitignore | 25 + .../expected/demo-project/README.md | 1 + .../expected/demo-project/ice.config.mts | 89 + .../expected/demo-project/package.json | 45 + .../expected/demo-project/src/app.ts | 13 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/document.tsx | 29 + .../expected/demo-project/src/global.scss | 6 + .../expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 68 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 8 + .../demo-project/src/pages/Test/index.jsx | 1076 +++ .../demo-project/src/pages/layout.jsx | 10 + .../expected/demo-project/src/typings.d.ts | 9 + .../expected/demo-project/src/utils.js | 47 + .../demo7-literal-condition2/schema.json5 | 1703 +++++ .../expected/demo-project/.browserslistrc | 3 + .../expected/demo-project/.gitignore | 25 + .../expected/demo-project/README.md | 1 + .../expected/demo-project/ice.config.mts | 89 + .../expected/demo-project/package.json | 44 + .../expected/demo-project/src/app.ts | 13 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/document.tsx | 29 + .../expected/demo-project/src/global.scss | 6 + .../expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 68 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Example/index.css | 0 .../demo-project/src/pages/Example/index.jsx | 116 + .../demo-project/src/pages/layout.jsx | 10 + .../expected/demo-project/src/typings.d.ts | 9 + .../expected/demo-project/src/utils.js | 47 + .../demo8-datasource-prop/schema.json5 | 65 + .../expected/demo-project/.browserslistrc | 3 + .../expected/demo-project/.gitignore | 25 + .../expected/demo-project/README.md | 1 + .../expected/demo-project/ice.config.mts | 89 + .../expected/demo-project/package.json | 43 + .../expected/demo-project/src/app.ts | 13 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/document.tsx | 29 + .../expected/demo-project/src/global.scss | 6 + .../expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 68 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/$/index.css | 0 .../demo-project/src/pages/$/index.jsx | 125 + .../demo-project/src/pages/layout.jsx | 10 + .../expected/demo-project/src/typings.d.ts | 9 + .../expected/demo-project/src/utils.js | 47 + .../demo9-datasource-engine/schema.json5 | 59 + .../expected/demo-project/.browserslistrc | 3 + .../expected/demo-project/.gitignore | 25 + .../expected/demo-project/README.md | 1 + .../expected/demo-project/ice.config.mts | 89 + .../expected/demo-project/package.json | 46 + .../expected/demo-project/src/app.ts | 13 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/document.tsx | 29 + .../expected/demo-project/src/global.scss | 6 + .../expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 68 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 8 + .../demo-project/src/pages/Test/index.jsx | 822 +++ .../demo-project/src/pages/layout.jsx | 10 + .../expected/demo-project/src/typings.d.ts | 9 + .../expected/demo-project/src/utils.js | 47 + .../icejs3-app/demo_10-jsslot/schema.json5 | 1206 ++++ .../expected/demo-project/.browserslistrc | 3 + .../expected/demo-project/.gitignore | 25 + .../expected/demo-project/README.md | 1 + .../expected/demo-project/ice.config.mts | 89 + .../expected/demo-project/package.json | 46 + .../expected/demo-project/src/app.ts | 13 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/document.tsx | 29 + .../expected/demo-project/src/global.scss | 6 + .../expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 68 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 8 + .../demo-project/src/pages/Test/index.jsx | 976 +++ .../demo-project/src/pages/layout.jsx | 10 + .../expected/demo-project/src/typings.d.ts | 9 + .../expected/demo-project/src/utils.js | 47 + .../icejs3-app/demo_11-jsslot-2/schema.json5 | 1457 +++++ .../expected/demo-project/.eslintignore | 8 + .../demo01/expected/demo-project/.eslintrc.js | 15 + .../demo01/expected/demo-project/.gitignore | 18 + .../expected/demo-project/.prettierignore | 8 + .../expected/demo-project/.prettierrc.js | 3 + .../expected/demo-project/.stylelintignore | 8 + .../expected/demo-project/.stylelintrc.js | 3 + .../demo01/expected/demo-project/README.md | 15 + .../demo01/expected/demo-project/build.json | 5 + .../expected/demo-project/jsconfig.json | 10 + .../demo01/expected/demo-project/package.json | 29 + .../demo01/expected/demo-project/src/app.js | 9 + .../demo01/expected/demo-project/src/app.json | 11 + .../expected/demo-project/src/constants.js | 3 + .../demo-project/src/document/index.jsx | 25 + .../expected/demo-project/src/global.css | 3 + .../demo01/expected/demo-project/src/i18n.js | 68 + .../demo-project/src/pages/Home/index.css | 0 .../demo-project/src/pages/Home/index.jsx | 142 + .../demo01/expected/demo-project/src/utils.js | 45 + .../expected/demo-project/tsconfig.json | 33 + .../test-cases/rax-app/demo01/schema.json5 | 54 + .../expected/demo-project/.eslintignore | 8 + .../demo02/expected/demo-project/.eslintrc.js | 15 + .../demo02/expected/demo-project/.gitignore | 18 + .../expected/demo-project/.prettierignore | 8 + .../expected/demo-project/.prettierrc.js | 3 + .../expected/demo-project/.stylelintignore | 8 + .../expected/demo-project/.stylelintrc.js | 3 + .../demo02/expected/demo-project/README.md | 15 + .../demo02/expected/demo-project/build.json | 5 + .../expected/demo-project/jsconfig.json | 10 + .../demo02/expected/demo-project/package.json | 35 + .../demo02/expected/demo-project/src/app.js | 9 + .../demo02/expected/demo-project/src/app.json | 11 + .../expected/demo-project/src/constants.js | 3 + .../demo-project/src/document/index.jsx | 25 + .../expected/demo-project/src/global.css | 9 + .../demo02/expected/demo-project/src/i18n.js | 68 + .../demo-project/src/pages/Home/index.css | 0 .../demo-project/src/pages/Home/index.jsx | 347 + .../demo02/expected/demo-project/src/utils.js | 70 + .../expected/demo-project/tsconfig.json | 33 + .../test-cases/rax-app/demo02/schema.json5 | 374 ++ .../expected/demo-project/.eslintignore | 8 + .../demo03/expected/demo-project/.eslintrc.js | 15 + .../demo03/expected/demo-project/.gitignore | 18 + .../expected/demo-project/.prettierignore | 8 + .../expected/demo-project/.prettierrc.js | 3 + .../expected/demo-project/.stylelintignore | 8 + .../expected/demo-project/.stylelintrc.js | 3 + .../demo03/expected/demo-project/README.md | 15 + .../demo03/expected/demo-project/build.json | 5 + .../expected/demo-project/jsconfig.json | 10 + .../demo03/expected/demo-project/package.json | 30 + .../demo03/expected/demo-project/src/app.js | 9 + .../demo03/expected/demo-project/src/app.json | 19 + .../expected/demo-project/src/constants.js | 3 + .../demo-project/src/document/index.jsx | 25 + .../expected/demo-project/src/global.css | 9 + .../demo03/expected/demo-project/src/i18n.js | 68 + .../demo-project/src/pages/Detail/index.css | 0 .../demo-project/src/pages/Detail/index.jsx | 151 + .../demo-project/src/pages/Home/index.css | 0 .../demo-project/src/pages/Home/index.jsx | 151 + .../demo-project/src/pages/List/index.css | 0 .../demo-project/src/pages/List/index.jsx | 154 + .../demo03/expected/demo-project/src/utils.js | 45 + .../expected/demo-project/tsconfig.json | 33 + .../test-cases/rax-app/demo03/schema.json5 | 175 + .../test-cases/rax-app/demo04/README.md | 1 + .../expected/demo-project/.eslintignore | 8 + .../demo04/expected/demo-project/.eslintrc.js | 15 + .../demo04/expected/demo-project/.gitignore | 18 + .../expected/demo-project/.prettierignore | 8 + .../expected/demo-project/.prettierrc.js | 3 + .../expected/demo-project/.stylelintignore | 8 + .../expected/demo-project/.stylelintrc.js | 3 + .../demo04/expected/demo-project/README.md | 15 + .../demo04/expected/demo-project/build.json | 8 + .../expected/demo-project/jsconfig.json | 10 + .../demo04/expected/demo-project/package.json | 30 + .../demo04/expected/demo-project/src/app.js | 9 + .../demo04/expected/demo-project/src/app.json | 11 + .../expected/demo-project/src/constants.js | 3 + .../demo-project/src/document/index.jsx | 25 + .../expected/demo-project/src/global.css | 9 + .../demo04/expected/demo-project/src/i18n.js | 68 + .../demo-project/src/pages/Home/index.css | 0 .../demo-project/src/pages/Home/index.jsx | 146 + .../demo04/expected/demo-project/src/utils.js | 45 + .../expected/demo-project/tsconfig.json | 33 + .../test-cases/rax-app/demo04/schema.json5 | 85 + .../expected/demo-project/.eslintignore | 8 + .../demo05/expected/demo-project/.eslintrc.js | 15 + .../demo05/expected/demo-project/.gitignore | 18 + .../expected/demo-project/.prettierignore | 8 + .../expected/demo-project/.prettierrc.js | 3 + .../expected/demo-project/.stylelintignore | 8 + .../expected/demo-project/.stylelintrc.js | 3 + .../demo05/expected/demo-project/README.md | 15 + .../demo05/expected/demo-project/build.json | 5 + .../expected/demo-project/jsconfig.json | 10 + .../demo05/expected/demo-project/package.json | 29 + .../demo05/expected/demo-project/src/app.js | 9 + .../demo05/expected/demo-project/src/app.json | 11 + .../expected/demo-project/src/constants.js | 3 + .../demo-project/src/document/index.jsx | 25 + .../expected/demo-project/src/global.css | 3 + .../demo05/expected/demo-project/src/i18n.js | 75 + .../demo-project/src/pages/Home/index.css | 0 .../demo-project/src/pages/Home/index.jsx | 148 + .../demo05/expected/demo-project/src/utils.js | 45 + .../expected/demo-project/tsconfig.json | 33 + .../test-cases/rax-app/demo05/schema.json5 | 72 + .../expected/demo-project/.eslintignore | 8 + .../expected/demo-project/.eslintrc.js | 15 + .../expected/demo-project/.gitignore | 18 + .../expected/demo-project/.prettierignore | 8 + .../expected/demo-project/.prettierrc.js | 3 + .../expected/demo-project/.stylelintignore | 8 + .../expected/demo-project/.stylelintrc.js | 3 + .../expected/demo-project/README.md | 15 + .../expected/demo-project/build.json | 5 + .../expected/demo-project/jsconfig.json | 10 + .../expected/demo-project/package.json | 30 + .../expected/demo-project/src/app.js | 9 + .../expected/demo-project/src/app.json | 11 + .../expected/demo-project/src/constants.js | 3 + .../demo-project/src/document/index.jsx | 25 + .../expected/demo-project/src/global.css | 3 + .../expected/demo-project/src/i18n.js | 75 + .../demo-project/src/pages/Home/index.css | 0 .../demo-project/src/pages/Home/index.jsx | 154 + .../expected/demo-project/src/utils.js | 45 + .../expected/demo-project/tsconfig.json | 33 + .../rax-app/demo06-jsslot/schema.json5 | 84 + .../expected/demo-project/.eslintignore | 8 + .../expected/demo-project/.eslintrc.js | 15 + .../expected/demo-project/.gitignore | 18 + .../expected/demo-project/.prettierignore | 8 + .../expected/demo-project/.prettierrc.js | 3 + .../expected/demo-project/.stylelintignore | 8 + .../expected/demo-project/.stylelintrc.js | 3 + .../expected/demo-project/README.md | 15 + .../expected/demo-project/build.json | 5 + .../expected/demo-project/jsconfig.json | 10 + .../expected/demo-project/package.json | 29 + .../expected/demo-project/src/app.js | 9 + .../expected/demo-project/src/app.json | 11 + .../expected/demo-project/src/constants.js | 3 + .../demo-project/src/document/index.jsx | 25 + .../expected/demo-project/src/global.css | 3 + .../expected/demo-project/src/i18n.js | 75 + .../demo-project/src/pages/Home/index.css | 0 .../demo-project/src/pages/Home/index.jsx | 148 + .../expected/demo-project/src/utils.js | 45 + .../expected/demo-project/tsconfig.json | 33 + .../demo07-newline-in-props/schema.json5 | 78 + .../expected/demo-project/.eslintignore | 8 + .../expected/demo-project/.eslintrc.js | 15 + .../expected/demo-project/.gitignore | 18 + .../expected/demo-project/.prettierignore | 8 + .../expected/demo-project/.prettierrc.js | 3 + .../expected/demo-project/.stylelintignore | 8 + .../expected/demo-project/.stylelintrc.js | 3 + .../expected/demo-project/README.md | 15 + .../expected/demo-project/build.json | 5 + .../expected/demo-project/jsconfig.json | 10 + .../expected/demo-project/package.json | 30 + .../expected/demo-project/src/app.js | 9 + .../expected/demo-project/src/app.json | 11 + .../expected/demo-project/src/constants.js | 3 + .../demo-project/src/document/index.jsx | 25 + .../expected/demo-project/src/global.css | 3 + .../expected/demo-project/src/i18n.js | 75 + .../demo-project/src/pages/Home/index.css | 0 .../demo-project/src/pages/Home/index.jsx | 154 + .../expected/demo-project/src/utils.js | 45 + .../expected/demo-project/tsconfig.json | 33 + .../schema.json5 | 90 + .../expected/demo-project/.eslintignore | 8 + .../expected/demo-project/.eslintrc.js | 15 + .../expected/demo-project/.gitignore | 18 + .../expected/demo-project/.prettierignore | 8 + .../expected/demo-project/.prettierrc.js | 3 + .../expected/demo-project/.stylelintignore | 8 + .../expected/demo-project/.stylelintrc.js | 3 + .../expected/demo-project/README.md | 15 + .../expected/demo-project/build.json | 5 + .../expected/demo-project/jsconfig.json | 10 + .../expected/demo-project/package.json | 30 + .../expected/demo-project/src/app.js | 9 + .../expected/demo-project/src/app.json | 11 + .../expected/demo-project/src/constants.js | 3 + .../demo-project/src/document/index.jsx | 25 + .../expected/demo-project/src/global.css | 3 + .../expected/demo-project/src/i18n.js | 75 + .../demo-project/src/pages/Home/index.css | 0 .../demo-project/src/pages/Home/index.jsx | 157 + .../expected/demo-project/src/utils.js | 45 + .../expected/demo-project/tsconfig.json | 33 + .../schema.json5 | 94 + .../expected/demo-project/.eslintignore | 8 + .../expected/demo-project/.eslintrc.js | 15 + .../expected/demo-project/.gitignore | 18 + .../expected/demo-project/.prettierignore | 8 + .../expected/demo-project/.prettierrc.js | 3 + .../expected/demo-project/.stylelintignore | 8 + .../expected/demo-project/.stylelintrc.js | 3 + .../expected/demo-project/README.md | 15 + .../expected/demo-project/build.json | 5 + .../expected/demo-project/jsconfig.json | 10 + .../expected/demo-project/package.json | 30 + .../expected/demo-project/src/app.js | 9 + .../expected/demo-project/src/app.json | 11 + .../expected/demo-project/src/constants.js | 3 + .../demo-project/src/document/index.jsx | 25 + .../expected/demo-project/src/global.css | 3 + .../expected/demo-project/src/i18n.js | 75 + .../demo-project/src/pages/Home/index.css | 0 .../demo-project/src/pages/Home/index.jsx | 159 + .../expected/demo-project/src/utils.js | 45 + .../expected/demo-project/tsconfig.json | 33 + .../schema.json5 | 89 + .../expected/demo-project/.eslintignore | 8 + .../expected/demo-project/.eslintrc.js | 15 + .../expected/demo-project/.gitignore | 18 + .../expected/demo-project/.prettierignore | 8 + .../expected/demo-project/.prettierrc.js | 3 + .../expected/demo-project/.stylelintignore | 8 + .../expected/demo-project/.stylelintrc.js | 3 + .../expected/demo-project/README.md | 15 + .../expected/demo-project/build.json | 8 + .../expected/demo-project/jsconfig.json | 10 + .../expected/demo-project/package.json | 33 + .../expected/demo-project/src/app.js | 9 + .../expected/demo-project/src/app.json | 11 + .../expected/demo-project/src/constants.js | 3 + .../demo-project/src/document/index.jsx | 25 + .../expected/demo-project/src/global.css | 3 + .../expected/demo-project/src/i18n.js | 68 + .../demo-project/src/pages/Aaaa/index.css | 0 .../demo-project/src/pages/Aaaa/index.jsx | 171 + .../expected/demo-project/src/utils.js | 61 + .../expected/demo-project/tsconfig.json | 33 + .../demo11-utils-name-alias/schema.json5 | 136 + .../expected/demo-project/.eslintignore | 8 + .../expected/demo-project/.eslintrc.js | 15 + .../expected/demo-project/.gitignore | 18 + .../expected/demo-project/.prettierignore | 8 + .../expected/demo-project/.prettierrc.js | 3 + .../expected/demo-project/.stylelintignore | 8 + .../expected/demo-project/.stylelintrc.js | 3 + .../expected/demo-project/README.md | 15 + .../expected/demo-project/build.json | 5 + .../expected/demo-project/jsconfig.json | 10 + .../expected/demo-project/package.json | 29 + .../expected/demo-project/src/app.js | 9 + .../expected/demo-project/src/app.json | 11 + .../expected/demo-project/src/constants.js | 3 + .../demo-project/src/document/index.jsx | 25 + .../expected/demo-project/src/global.css | 3 + .../expected/demo-project/src/i18n.js | 75 + .../demo-project/src/pages/Home/index.css | 0 .../demo-project/src/pages/Home/index.jsx | 162 + .../expected/demo-project/src/utils.js | 45 + .../expected/demo-project/tsconfig.json | 33 + .../rax-app/demo12-refs/schema.json5 | 73 + .../expected/demo-project/.eslintignore | 8 + .../expected/demo-project/.eslintrc.js | 15 + .../expected/demo-project/.gitignore | 18 + .../expected/demo-project/.prettierignore | 8 + .../expected/demo-project/.prettierrc.js | 3 + .../expected/demo-project/.stylelintignore | 8 + .../expected/demo-project/.stylelintrc.js | 3 + .../expected/demo-project/README.md | 15 + .../expected/demo-project/build.json | 5 + .../expected/demo-project/jsconfig.json | 10 + .../expected/demo-project/package.json | 29 + .../expected/demo-project/src/app.js | 9 + .../expected/demo-project/src/app.json | 11 + .../expected/demo-project/src/constants.js | 3 + .../demo-project/src/document/index.jsx | 25 + .../expected/demo-project/src/global.css | 3 + .../expected/demo-project/src/i18n.js | 68 + .../demo-project/src/pages/Example/index.css | 0 .../demo-project/src/pages/Example/index.jsx | 173 + .../expected/demo-project/src/utils.js | 45 + .../expected/demo-project/tsconfig.json | 33 + .../demo13-datasource-prop/schema.json5 | 65 + .../demo1/expected/demo-project/.editorconfig | 14 + .../demo1/expected/demo-project/.eslintignore | 17 + .../demo1/expected/demo-project/.eslintrc.js | 5 + .../demo1/expected/demo-project/.gitignore | 25 + .../expected/demo-project/.prettierignore | 11 + .../expected/demo-project/.prettierrc.js | 5 + .../expected/demo-project/.stylelintignore | 9 + .../expected/demo-project/.stylelintrc.js | 5 + .../demo1/expected/demo-project/README.md | 62 + .../demo1/expected/demo-project/abc.json | 6 + .../demo1/expected/demo-project/build.json | 21 + .../demo1/expected/demo-project/jsconfig.json | 13 + .../demo1/expected/demo-project/package.json | 51 + .../expected/demo-project/public/index.html | 12 + .../demo1/expected/demo-project/src/app.js | 11 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/global.scss | 13 + .../demo1/expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 70 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 0 .../demo-project/src/pages/Test/index.jsx | 205 + .../demo1/expected/demo-project/src/routes.js | 18 + .../demo1/expected/demo-project/src/utils.js | 47 + .../demo1/expected/demo-project/tsconfig.json | 35 + .../test-cases/react-app/demo1/schema.json5 | 276 + .../expected/demo-project/.editorconfig | 14 + .../expected/demo-project/.eslintignore | 17 + .../expected/demo-project/.eslintrc.js | 5 + .../expected/demo-project/.gitignore | 25 + .../expected/demo-project/.prettierignore | 11 + .../expected/demo-project/.prettierrc.js | 5 + .../expected/demo-project/.stylelintignore | 9 + .../expected/demo-project/.stylelintrc.js | 5 + .../expected/demo-project/README.md | 62 + .../expected/demo-project/abc.json | 6 + .../expected/demo-project/build.json | 21 + .../expected/demo-project/jsconfig.json | 13 + .../expected/demo-project/package.json | 54 + .../expected/demo-project/public/index.html | 12 + .../expected/demo-project/src/app.js | 11 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/global.scss | 6 + .../expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 70 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Aaaa/index.css | 0 .../demo-project/src/pages/Aaaa/index.jsx | 118 + .../expected/demo-project/src/routes.js | 18 + .../expected/demo-project/src/utils.js | 61 + .../expected/demo-project/tsconfig.json | 35 + .../demo2-utils-name-alias/schema.json5 | 123 + .../demo2/expected/demo-project/.editorconfig | 14 + .../demo2/expected/demo-project/.eslintignore | 17 + .../demo2/expected/demo-project/.eslintrc.js | 5 + .../demo2/expected/demo-project/.gitignore | 25 + .../expected/demo-project/.prettierignore | 11 + .../expected/demo-project/.prettierrc.js | 5 + .../expected/demo-project/.stylelintignore | 9 + .../expected/demo-project/.stylelintrc.js | 5 + .../demo2/expected/demo-project/README.md | 62 + .../demo2/expected/demo-project/abc.json | 6 + .../demo2/expected/demo-project/build.json | 21 + .../demo2/expected/demo-project/jsconfig.json | 13 + .../demo2/expected/demo-project/package.json | 49 + .../expected/demo-project/public/index.html | 12 + .../demo2/expected/demo-project/src/app.js | 11 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/global.scss | 13 + .../demo2/expected/demo-project/src/i18n.js | 86 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 70 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 0 .../demo-project/src/pages/Test/index.jsx | 129 + .../demo2/expected/demo-project/src/routes.js | 18 + .../demo2/expected/demo-project/src/utils.js | 47 + .../demo2/expected/demo-project/tsconfig.json | 35 + .../test-cases/react-app/demo2/schema.json5 | 256 + .../demo3/expected/demo-project/.editorconfig | 14 + .../demo3/expected/demo-project/.eslintignore | 17 + .../demo3/expected/demo-project/.eslintrc.js | 5 + .../demo3/expected/demo-project/.gitignore | 25 + .../expected/demo-project/.prettierignore | 11 + .../expected/demo-project/.prettierrc.js | 5 + .../expected/demo-project/.stylelintignore | 9 + .../expected/demo-project/.stylelintrc.js | 5 + .../demo3/expected/demo-project/README.md | 62 + .../demo3/expected/demo-project/abc.json | 6 + .../demo3/expected/demo-project/build.json | 21 + .../demo3/expected/demo-project/jsconfig.json | 13 + .../demo3/expected/demo-project/package.json | 49 + .../expected/demo-project/public/index.html | 12 + .../demo3/expected/demo-project/src/app.js | 11 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/global.scss | 13 + .../demo3/expected/demo-project/src/i18n.js | 86 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 70 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 0 .../demo-project/src/pages/Test/index.jsx | 107 + .../demo3/expected/demo-project/src/routes.js | 18 + .../demo3/expected/demo-project/src/utils.js | 47 + .../demo3/expected/demo-project/tsconfig.json | 35 + .../test-cases/react-app/demo3/schema.json5 | 159 + .../demo4/expected/demo-project/.editorconfig | 14 + .../demo4/expected/demo-project/.eslintignore | 17 + .../demo4/expected/demo-project/.eslintrc.js | 5 + .../demo4/expected/demo-project/.gitignore | 25 + .../expected/demo-project/.prettierignore | 11 + .../expected/demo-project/.prettierrc.js | 5 + .../expected/demo-project/.stylelintignore | 9 + .../expected/demo-project/.stylelintrc.js | 5 + .../demo4/expected/demo-project/README.md | 62 + .../demo4/expected/demo-project/abc.json | 6 + .../demo4/expected/demo-project/build.json | 21 + .../demo4/expected/demo-project/jsconfig.json | 13 + .../demo4/expected/demo-project/package.json | 51 + .../expected/demo-project/public/index.html | 12 + .../demo4/expected/demo-project/src/app.js | 11 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/global.scss | 6 + .../demo4/expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 70 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 8 + .../demo-project/src/pages/Test/index.jsx | 292 + .../demo4/expected/demo-project/src/routes.js | 18 + .../demo4/expected/demo-project/src/utils.js | 47 + .../demo4/expected/demo-project/tsconfig.json | 35 + .../test-cases/react-app/demo4/schema.json5 | 353 + .../demo5/expected/demo-project/.editorconfig | 14 + .../demo5/expected/demo-project/.eslintignore | 17 + .../demo5/expected/demo-project/.eslintrc.js | 5 + .../demo5/expected/demo-project/.gitignore | 25 + .../expected/demo-project/.prettierignore | 11 + .../expected/demo-project/.prettierrc.js | 5 + .../expected/demo-project/.stylelintignore | 9 + .../expected/demo-project/.stylelintrc.js | 5 + .../demo5/expected/demo-project/README.md | 62 + .../demo5/expected/demo-project/abc.json | 6 + .../demo5/expected/demo-project/build.json | 21 + .../demo5/expected/demo-project/jsconfig.json | 13 + .../demo5/expected/demo-project/package.json | 52 + .../expected/demo-project/public/index.html | 12 + .../demo5/expected/demo-project/src/app.js | 11 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/global.scss | 6 + .../demo5/expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 70 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 8 + .../demo-project/src/pages/Test/index.jsx | 389 ++ .../demo5/expected/demo-project/src/routes.js | 18 + .../demo5/expected/demo-project/src/utils.js | 47 + .../demo5/expected/demo-project/tsconfig.json | 35 + .../test-cases/react-app/demo5/schema.json5 | 677 ++ .../expected/demo-project/.editorconfig | 14 + .../expected/demo-project/.eslintignore | 17 + .../expected/demo-project/.eslintrc.js | 5 + .../expected/demo-project/.gitignore | 25 + .../expected/demo-project/.prettierignore | 11 + .../expected/demo-project/.prettierrc.js | 5 + .../expected/demo-project/.stylelintignore | 9 + .../expected/demo-project/.stylelintrc.js | 5 + .../expected/demo-project/README.md | 62 + .../expected/demo-project/abc.json | 6 + .../expected/demo-project/build.json | 21 + .../expected/demo-project/jsconfig.json | 13 + .../expected/demo-project/package.json | 51 + .../expected/demo-project/public/index.html | 12 + .../expected/demo-project/src/app.js | 11 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/global.scss | 13 + .../expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 70 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 0 .../demo-project/src/pages/Test/index.jsx | 205 + .../expected/demo-project/src/routes.js | 18 + .../expected/demo-project/src/utils.js | 47 + .../expected/demo-project/tsconfig.json | 35 + .../demo6-literal-condition/schema.json5 | 273 + .../expected/demo-project/.editorconfig | 14 + .../expected/demo-project/.eslintignore | 17 + .../expected/demo-project/.eslintrc.js | 5 + .../expected/demo-project/.gitignore | 25 + .../expected/demo-project/.prettierignore | 11 + .../expected/demo-project/.prettierrc.js | 5 + .../expected/demo-project/.stylelintignore | 9 + .../expected/demo-project/.stylelintrc.js | 5 + .../expected/demo-project/README.md | 62 + .../expected/demo-project/abc.json | 6 + .../expected/demo-project/build.json | 21 + .../expected/demo-project/jsconfig.json | 13 + .../expected/demo-project/package.json | 51 + .../expected/demo-project/public/index.html | 12 + .../expected/demo-project/src/app.js | 11 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/global.scss | 6 + .../expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 70 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 8 + .../demo-project/src/pages/Test/index.jsx | 1076 +++ .../expected/demo-project/src/routes.js | 18 + .../expected/demo-project/src/utils.js | 47 + .../expected/demo-project/tsconfig.json | 35 + .../demo7-literal-condition2/schema.json5 | 1703 +++++ .../expected/demo-project/.editorconfig | 14 + .../expected/demo-project/.eslintignore | 17 + .../expected/demo-project/.eslintrc.js | 5 + .../expected/demo-project/.gitignore | 25 + .../expected/demo-project/.prettierignore | 11 + .../expected/demo-project/.prettierrc.js | 5 + .../expected/demo-project/.stylelintignore | 9 + .../expected/demo-project/.stylelintrc.js | 5 + .../expected/demo-project/README.md | 62 + .../expected/demo-project/abc.json | 6 + .../expected/demo-project/build.json | 21 + .../expected/demo-project/jsconfig.json | 13 + .../expected/demo-project/package.json | 50 + .../expected/demo-project/public/index.html | 12 + .../expected/demo-project/src/app.js | 11 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/global.scss | 6 + .../expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 70 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Example/index.css | 0 .../demo-project/src/pages/Example/index.jsx | 116 + .../expected/demo-project/src/routes.js | 18 + .../expected/demo-project/src/utils.js | 47 + .../expected/demo-project/tsconfig.json | 35 + .../demo8-datasource-prop/schema.json5 | 65 + .../expected/demo-project/.editorconfig | 14 + .../expected/demo-project/.eslintignore | 17 + .../expected/demo-project/.eslintrc.js | 5 + .../expected/demo-project/.gitignore | 25 + .../expected/demo-project/.prettierignore | 11 + .../expected/demo-project/.prettierrc.js | 5 + .../expected/demo-project/.stylelintignore | 9 + .../expected/demo-project/.stylelintrc.js | 5 + .../expected/demo-project/README.md | 62 + .../expected/demo-project/abc.json | 6 + .../expected/demo-project/build.json | 21 + .../expected/demo-project/jsconfig.json | 13 + .../expected/demo-project/package.json | 50 + .../expected/demo-project/public/index.html | 12 + .../expected/demo-project/src/app.js | 11 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/global.scss | 6 + .../expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 70 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/$/index.css | 0 .../demo-project/src/pages/$/index.jsx | 125 + .../expected/demo-project/src/routes.js | 18 + .../expected/demo-project/src/utils.js | 47 + .../expected/demo-project/tsconfig.json | 35 + .../demo9-datasource-engine/schema.json5 | 59 + .../expected/demo-project/.editorconfig | 14 + .../expected/demo-project/.eslintignore | 17 + .../expected/demo-project/.eslintrc.js | 5 + .../expected/demo-project/.gitignore | 25 + .../expected/demo-project/.prettierignore | 11 + .../expected/demo-project/.prettierrc.js | 5 + .../expected/demo-project/.stylelintignore | 9 + .../expected/demo-project/.stylelintrc.js | 5 + .../expected/demo-project/README.md | 62 + .../expected/demo-project/abc.json | 6 + .../expected/demo-project/build.json | 21 + .../expected/demo-project/jsconfig.json | 13 + .../expected/demo-project/package.json | 52 + .../expected/demo-project/public/index.html | 12 + .../expected/demo-project/src/app.js | 11 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/global.scss | 6 + .../expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 70 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 8 + .../demo-project/src/pages/Test/index.jsx | 822 +++ .../expected/demo-project/src/routes.js | 18 + .../expected/demo-project/src/utils.js | 47 + .../expected/demo-project/tsconfig.json | 35 + .../react-app/demo_10-jsslot/schema.json5 | 1206 ++++ .../expected/demo-project/.editorconfig | 14 + .../expected/demo-project/.eslintignore | 17 + .../expected/demo-project/.eslintrc.js | 5 + .../expected/demo-project/.gitignore | 25 + .../expected/demo-project/.prettierignore | 11 + .../expected/demo-project/.prettierrc.js | 5 + .../expected/demo-project/.stylelintignore | 9 + .../expected/demo-project/.stylelintrc.js | 5 + .../expected/demo-project/README.md | 62 + .../expected/demo-project/abc.json | 6 + .../expected/demo-project/build.json | 21 + .../expected/demo-project/jsconfig.json | 13 + .../expected/demo-project/package.json | 52 + .../expected/demo-project/public/index.html | 12 + .../expected/demo-project/src/app.js | 11 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/global.scss | 6 + .../expected/demo-project/src/i18n.js | 77 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 70 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 8 + .../demo-project/src/pages/Test/index.jsx | 976 +++ .../expected/demo-project/src/routes.js | 18 + .../expected/demo-project/src/utils.js | 47 + .../expected/demo-project/tsconfig.json | 35 + .../react-app/demo_11-jsslot-2/schema.json5 | 1457 +++++ .../demo1/expected/demo-project/.editorconfig | 14 + .../demo1/expected/demo-project/.eslintignore | 17 + .../demo1/expected/demo-project/.eslintrc.js | 5 + .../demo1/expected/demo-project/.gitignore | 25 + .../expected/demo-project/.prettierignore | 11 + .../expected/demo-project/.prettierrc.js | 5 + .../expected/demo-project/.stylelintignore | 9 + .../expected/demo-project/.stylelintrc.js | 5 + .../demo1/expected/demo-project/README.md | 62 + .../demo1/expected/demo-project/abc.json | 6 + .../demo1/expected/demo-project/build.json | 22 + .../demo1/expected/demo-project/jsconfig.json | 13 + .../demo1/expected/demo-project/package.json | 44 + .../expected/demo-project/public/index.html | 12 + .../demo1/expected/demo-project/src/app.js | 11 + .../expected/demo-project/src/constants.js | 3 + .../expected/demo-project/src/global.scss | 13 + .../demo1/expected/demo-project/src/i18n.js | 33 + .../BasicLayout/components/Footer/index.jsx | 14 + .../components/Footer/index.module.scss | 15 + .../BasicLayout/components/Logo/index.jsx | 16 + .../components/Logo/index.module.scss | 20 + .../BasicLayout/components/PageNav/index.jsx | 70 + .../src/layouts/BasicLayout/index.jsx | 81 + .../src/layouts/BasicLayout/menuConfig.js | 11 + .../demo-project/src/pages/Test/index.css | 0 .../demo-project/src/pages/Test/index.jsx | 79 + .../demo1/expected/demo-project/src/routes.js | 18 + .../demo1/expected/demo-project/src/utils.js | 47 + .../demo1/expected/demo-project/tsconfig.json | 35 + .../react-module/demo1/schema.json5 | 296 + .../tests/helpers/solutionHelper.ts | 106 + .../__snapshots__/requireUtils.test.ts.snap | 18 + .../tests/plugins/common/requireUtils.test.ts | 17 + .../p0-condition-at-root.test.ts.snap | 355 + .../plugins/jsx/p0-condition-at-root.test.ts | 104 + .../__snapshots__/prettier.test.ts.snap | 44 + .../tests/postprocessor/prettier.test.ts | 39 + modules/code-generator/tests/public/README.md | 1 + .../__snapshots__/p0-basic.test.ts.snap | 178 + .../SchemaParser/data/schema-with-slot.json | 1457 +++++ .../public/SchemaParser/p0-basic.test.ts | 13 + .../code-generator/tests/public/cli.test.ts | 32 + .../tests/public/publisher/disk/disk.test.ts | 56 + .../tests/public/publisher/zip/zip.test.ts | 87 + .../tests/public/solutions/icejs3-app.test.ts | 67 + .../tests/public/solutions/rax-app.test.ts | 68 + .../tests/public/solutions/react-app.test.ts | 67 + .../tests/utils/compositeType.test.ts | 141 + .../code-generator/tests/utils/errors.test.ts | 27 + .../expressionParser/jsExpression.test.ts | 45 + ...parseExpressionConvertThis2Context.test.ts | 95 + .../parseExpressionGetGlobalVariables.test.ts | 134 + .../parseExpressionGetKeywords.test.ts | 31 + .../tests/utils/flattenResult.test.ts | 60 + .../utils/resultHelper/example-result.json | 46 + .../tests/utils/resultHelper/findFile.test.ts | 34 + .../utils/resultHelper/globFiles.test.ts | 67 + .../resultHelper/removeDirsFromResult.test.ts | 101 + .../removeFilesFromResult.test.ts | 102 + .../utils/resultHelper/scanFiles.test.ts | 68 + .../utils/schema/data/schema-with-slot.json | 1457 +++++ .../tests/utils/schema/handleSubNodes.test.ts | 92 + .../tests/utils/validate.test.ts | 20 + .../tests/utils/version.test.ts | 33 + modules/code-generator/tsconfig.json | 8 + modules/material-parser/README.md | 22 + modules/material-parser/build.test.json | 5 + modules/material-parser/demo/component.jsx | 81 + modules/material-parser/demo/component.tsx | 54 + modules/material-parser/demo/parse-jsx.js | 11 + modules/material-parser/demo/parse-tsx.js | 11 + modules/material-parser/jest.config.js | 20 + modules/material-parser/package.json | 76 + modules/material-parser/schemas/schema.json | 537 ++ modules/material-parser/schemas/schema.yml | 351 + modules/material-parser/scripts/transform.js | 35 + modules/material-parser/src/core/index.ts | 10 + .../material-parser/src/core/schema/types.ts | 163 + modules/material-parser/src/generate.ts | 65 + modules/material-parser/src/index.ts | 70 + modules/material-parser/src/localize.ts | 126 + .../src/parse/dynamic/index.ts | 121 + .../src/parse/dynamic/requireInSandbox.ts | 37 + modules/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 + modules/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 | 179 + .../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 | 52 + .../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 + modules/material-parser/src/parse/ts/index.ts | 609 ++ .../src/parse/ts/tsconfig.json | 11 + modules/material-parser/src/scan.ts | 78 + modules/material-parser/src/types/Basic.ts | 5 + .../material-parser/src/types/ChannelType.ts | 9 + modules/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 + modules/material-parser/src/types/Meta.ts | 14 + modules/material-parser/src/types/index.ts | 8 + modules/material-parser/src/utils.ts | 138 + modules/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 +++++++++++++++++ modules/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 | 21 + .../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 | 64 + .../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 | 27 + .../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 | 31 + .../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 | 58 + .../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 | 10 + modules/material-parser/test/helpers/index.ts | 10 + modules/material-parser/test/index.test.ts | 110 + modules/material-parser/test/localize.test.ts | 6 + modules/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 + modules/material-parser/tsconfig.json | 19 + modules/material-parser/webpack.config.js | 40 + 1444 files changed, 91697 insertions(+) create mode 100644 modules/code-generator/.gitignore create mode 100644 modules/code-generator/.prettierrc.js create mode 100644 modules/code-generator/.versionrc create mode 100644 modules/code-generator/CHANGELOG.md create mode 100644 modules/code-generator/CONTRIBUTING.md create mode 100644 modules/code-generator/README.md create mode 100644 modules/code-generator/babel.config.js create mode 100644 modules/code-generator/bin/lowcode-code-generator.js create mode 100644 modules/code-generator/example-schema.json create mode 100644 modules/code-generator/example-schema.json5 create mode 100644 modules/code-generator/jest.config.js create mode 100644 modules/code-generator/jest.setup.js create mode 100644 modules/code-generator/package.json create mode 100644 modules/code-generator/scripts/build-cli.js create mode 100644 modules/code-generator/scripts/build-standalone-loader.js create mode 100644 modules/code-generator/scripts/build-standalone-worker.js create mode 100644 modules/code-generator/scripts/build-standalone.js create mode 100644 modules/code-generator/scripts/build-template-static-files.js create mode 100644 modules/code-generator/scripts/build-types create mode 100644 modules/code-generator/scripts/build.js create mode 100644 modules/code-generator/scripts/move-files-to-build-dest.js create mode 100644 modules/code-generator/scripts/run-demo-project create mode 100644 modules/code-generator/scripts/test-standalone.js create mode 100644 modules/code-generator/src/analyzer/componentAnalyzer.ts create mode 100644 modules/code-generator/src/cli/index.ts create mode 100644 modules/code-generator/src/cli/init-solution.ts create mode 100644 modules/code-generator/src/cli/run.ts create mode 100644 modules/code-generator/src/cli/solutions/example-solution.ts create mode 100644 modules/code-generator/src/config/env.ts create mode 100644 modules/code-generator/src/const/file.ts create mode 100644 modules/code-generator/src/const/generator.ts create mode 100644 modules/code-generator/src/const/index.ts create mode 100644 modules/code-generator/src/core/jsx/handlers/transformJsExpression.ts create mode 100644 modules/code-generator/src/core/jsx/handlers/transformThis2Context.ts create mode 100644 modules/code-generator/src/core/jsx/util/isLiteralAtomicExpr.ts create mode 100644 modules/code-generator/src/core/jsx/util/isSimpleStraightLiteral.ts create mode 100644 modules/code-generator/src/generator/ChunkBuilder.ts create mode 100644 modules/code-generator/src/generator/CodeBuilder.ts create mode 100644 modules/code-generator/src/generator/ModuleBuilder.ts create mode 100644 modules/code-generator/src/generator/ProjectBuilder.ts create mode 100644 modules/code-generator/src/index.ts create mode 100644 modules/code-generator/src/parser/SchemaParser.ts create mode 100644 modules/code-generator/src/plugins/common/esmodule.ts create mode 100644 modules/code-generator/src/plugins/common/requireUtils.ts create mode 100644 modules/code-generator/src/plugins/common/styleImport.ts create mode 100644 modules/code-generator/src/plugins/component/rax/commonDeps.ts create mode 100644 modules/code-generator/src/plugins/component/rax/const.ts create mode 100644 modules/code-generator/src/plugins/component/rax/containerClass.ts create mode 100644 modules/code-generator/src/plugins/component/rax/containerInitState.ts create mode 100644 modules/code-generator/src/plugins/component/rax/containerInjectContext.ts create mode 100644 modules/code-generator/src/plugins/component/rax/containerInjectDataSourceEngine.ts create mode 100644 modules/code-generator/src/plugins/component/rax/containerInjectUtils.ts create mode 100644 modules/code-generator/src/plugins/component/rax/containerLifeCycle.ts create mode 100644 modules/code-generator/src/plugins/component/rax/containerMethods.ts create mode 100644 modules/code-generator/src/plugins/component/rax/jsx.ts create mode 100644 modules/code-generator/src/plugins/component/react/const.ts create mode 100644 modules/code-generator/src/plugins/component/react/containerClass.ts create mode 100644 modules/code-generator/src/plugins/component/react/containerInitState.ts create mode 100644 modules/code-generator/src/plugins/component/react/containerInjectConstants.ts create mode 100644 modules/code-generator/src/plugins/component/react/containerInjectContext.ts create mode 100644 modules/code-generator/src/plugins/component/react/containerInjectDataSourceEngine.ts create mode 100644 modules/code-generator/src/plugins/component/react/containerInjectI18n.ts create mode 100644 modules/code-generator/src/plugins/component/react/containerInjectUtils.ts create mode 100644 modules/code-generator/src/plugins/component/react/containerLifeCycle.ts create mode 100644 modules/code-generator/src/plugins/component/react/containerMethod.ts create mode 100644 modules/code-generator/src/plugins/component/react/jsx.ts create mode 100644 modules/code-generator/src/plugins/component/react/reactCommonDeps.ts create mode 100644 modules/code-generator/src/plugins/component/style/css.ts create mode 100644 modules/code-generator/src/plugins/project/constants.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/index.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/plugins/entry.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/plugins/entryHtml.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/plugins/globalStyle.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/plugins/packageJSON.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/plugins/router.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/README.md.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/abc.json.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/build.json.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/editorconfig.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/eslintignore.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/eslintrc.js.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/gitignore.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/jsconfig.json.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/prettierignore.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/prettierrc.js.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.jsx.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.style.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.jsx.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.style.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/PageNav/index.jsx.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/index.jsx.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/menuConfig.js.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/stylelintignore.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/stylelintrc.js.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/files/tsconfig.json.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/index.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs/template/static-files.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/index.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/plugins/appConfig.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/plugins/buildConfig.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/plugins/globalStyle.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/plugins/layout.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/plugins/packageJSON.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/template/files/README.md.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/template/files/browserslistrc.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/template/files/document.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/template/files/gitignore.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/template/files/src/layouts/BasicLayout/components/Footer/index.jsx.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/template/files/src/layouts/BasicLayout/components/Footer/index.style.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/template/files/src/layouts/BasicLayout/components/Logo/index.jsx.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/template/files/src/layouts/BasicLayout/components/Logo/index.style.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/template/files/src/layouts/BasicLayout/components/PageNav/index.jsx.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/template/files/src/layouts/BasicLayout/index.jsx.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/template/files/src/layouts/BasicLayout/menuConfig.js.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/template/files/tsconfig.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/template/files/typings.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/template/index.ts create mode 100644 modules/code-generator/src/plugins/project/framework/icejs3/template/static-files.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/index.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/plugins/appConfig.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/plugins/buildConfig.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/plugins/entry.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/plugins/entryDocument.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/plugins/globalStyle.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/plugins/packageJSON.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/template/files/.eslintignore.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/template/files/.eslintrc.js.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/template/files/.gitignore.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/template/files/.prettierignore.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/template/files/.prettierrc.js.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/template/files/.stylelintignore.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/template/files/.stylelintrc.js.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/template/files/README.md.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/template/files/jsconfig.json.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/template/files/tsconfig.json.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/template/index.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/template/static-files.ts create mode 100644 modules/code-generator/src/plugins/project/framework/rax/types/RaxFrameworkOptions.ts create mode 100644 modules/code-generator/src/plugins/project/i18n.ts create mode 100644 modules/code-generator/src/plugins/project/utils.ts create mode 100644 modules/code-generator/src/polyfills/buffer.ts create mode 100644 modules/code-generator/src/postprocessor/index.ts create mode 100644 modules/code-generator/src/postprocessor/prettier/index.ts create mode 100644 modules/code-generator/src/publisher/disk/index.ts create mode 100644 modules/code-generator/src/publisher/disk/utils.ts create mode 100644 modules/code-generator/src/publisher/zip/index.ts create mode 100644 modules/code-generator/src/publisher/zip/utils.ts create mode 100644 modules/code-generator/src/solutions/icejs.ts create mode 100644 modules/code-generator/src/solutions/icejs3.ts create mode 100644 modules/code-generator/src/solutions/rax-app.ts create mode 100644 modules/code-generator/src/standalone-loader.ts create mode 100644 modules/code-generator/src/standalone-worker.ts create mode 100644 modules/code-generator/src/standalone.ts create mode 100644 modules/code-generator/src/types/analyze.ts create mode 100644 modules/code-generator/src/types/core.ts create mode 100644 modules/code-generator/src/types/deps.ts create mode 100644 modules/code-generator/src/types/error.ts create mode 100644 modules/code-generator/src/types/file.ts create mode 100644 modules/code-generator/src/types/index.ts create mode 100644 modules/code-generator/src/types/intermediate.ts create mode 100644 modules/code-generator/src/types/jsx.ts create mode 100644 modules/code-generator/src/types/publisher.ts create mode 100644 modules/code-generator/src/typings.d.ts create mode 100644 modules/code-generator/src/utils/OrderedSet.ts create mode 100644 modules/code-generator/src/utils/Scope.ts create mode 100644 modules/code-generator/src/utils/ScopeBindings.ts create mode 100644 modules/code-generator/src/utils/aopHelper.ts create mode 100644 modules/code-generator/src/utils/common.ts create mode 100644 modules/code-generator/src/utils/compositeType.ts create mode 100644 modules/code-generator/src/utils/dataSource.ts create mode 100644 modules/code-generator/src/utils/debug.ts create mode 100644 modules/code-generator/src/utils/encodeJsxAttrString.ts create mode 100644 modules/code-generator/src/utils/errors.ts create mode 100644 modules/code-generator/src/utils/expressionParser.ts create mode 100644 modules/code-generator/src/utils/format.ts create mode 100644 modules/code-generator/src/utils/index.ts create mode 100644 modules/code-generator/src/utils/jsExpression.ts create mode 100644 modules/code-generator/src/utils/jsSlot.ts create mode 100644 modules/code-generator/src/utils/jsxHelpers.ts create mode 100644 modules/code-generator/src/utils/nodeToJSX.ts create mode 100644 modules/code-generator/src/utils/pathHelper.ts create mode 100644 modules/code-generator/src/utils/resultHelper.ts create mode 100644 modules/code-generator/src/utils/schema.ts create mode 100644 modules/code-generator/src/utils/templateHelper.ts create mode 100644 modules/code-generator/src/utils/theme.ts create mode 100644 modules/code-generator/src/utils/validate.ts create mode 100644 modules/code-generator/src/utils/version.ts create mode 100644 modules/code-generator/standalone-loader/index.js create mode 100644 modules/code-generator/standalone-loader/package.json create mode 100644 modules/code-generator/standalone-worker/index.js create mode 100644 modules/code-generator/standalone-worker/package.json create mode 100644 modules/code-generator/standalone/index.js create mode 100644 modules/code-generator/standalone/package.json create mode 100644 modules/code-generator/static-files/rax/.eslintignore.template create mode 100644 modules/code-generator/static-files/rax/.eslintrc.js.template create mode 100644 modules/code-generator/static-files/rax/.gitignore.template create mode 100644 modules/code-generator/static-files/rax/.prettierignore.template create mode 100644 modules/code-generator/static-files/rax/.prettierrc.js.template create mode 100644 modules/code-generator/static-files/rax/.stylelintignore.template create mode 100644 modules/code-generator/static-files/rax/.stylelintrc.js.template create mode 100644 modules/code-generator/static-files/rax/README.md.template create mode 100644 modules/code-generator/static-files/rax/jsconfig.json.template create mode 100644 modules/code-generator/static-files/rax/tsconfig.json.template create mode 100644 modules/code-generator/tests/bugfix/.gitignore create mode 100644 modules/code-generator/tests/bugfix/i18n-with-params.schema.json create mode 100644 modules/code-generator/tests/bugfix/i18n-with-params.test.ts create mode 100644 modules/code-generator/tests/bugfix/icejs-import-wrong-naming.schema.json create mode 100644 modules/code-generator/tests/bugfix/icejs-import-wrong-naming.test.ts create mode 100644 modules/code-generator/tests/bugfix/icejs-js-function1.schema.json create mode 100644 modules/code-generator/tests/bugfix/icejs-js-function1.test.ts create mode 100644 modules/code-generator/tests/bugfix/icejs-missing-imports-1.schema.json create mode 100644 modules/code-generator/tests/bugfix/icejs-missing-imports-1.test.ts create mode 100644 modules/code-generator/tests/bugfix/icejs-package-json-dependencies.schema.json create mode 100644 modules/code-generator/tests/bugfix/icejs-package-json-dependencies.test.ts create mode 100644 modules/code-generator/tests/bugfix/icejs-page-map1.schema.json create mode 100644 modules/code-generator/tests/bugfix/icejs-page-map1.test.ts create mode 100644 modules/code-generator/tests/bugfix/page-element1.schema.json create mode 100644 modules/code-generator/tests/bugfix/page-element1.test.ts create mode 100644 modules/code-generator/tests/bugfix/page-element2.schema.json create mode 100644 modules/code-generator/tests/bugfix/page-element2.test.ts create mode 100644 modules/code-generator/tests/bugfix/strict-mode-context-1.schema.json create mode 100644 modules/code-generator/tests/bugfix/strict-mode-context-1.test.ts create mode 100644 modules/code-generator/tests/bugfix/tolerate-eval-errors-1-loop.schema.json create mode 100644 modules/code-generator/tests/bugfix/tolerate-eval-errors-1-loop.test.ts create mode 100644 modules/code-generator/tests/bugfix/tolerate-eval-errors-2-nested-loop.schema.json create mode 100644 modules/code-generator/tests/bugfix/tolerate-eval-errors-2-nested-loop.test.ts create mode 100644 modules/code-generator/tests/cli.test.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/.browserslistrc create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/ice.config.mts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/app.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/document.tsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/pages/layout.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/typings.d.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/.browserslistrc create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/ice.config.mts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/app.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/document.tsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/pages/Aaaa/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/pages/Aaaa/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/pages/layout.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/typings.d.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/.browserslistrc create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/ice.config.mts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/app.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/document.tsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/pages/layout.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/typings.d.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/.browserslistrc create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/ice.config.mts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/app.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/document.tsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/pages/layout.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/typings.d.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo3/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/.browserslistrc create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/ice.config.mts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/app.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/document.tsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/pages/layout.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/typings.d.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo4/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/.browserslistrc create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/ice.config.mts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/app.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/document.tsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/pages/layout.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/typings.d.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo5/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/.browserslistrc create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/ice.config.mts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/app.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/document.tsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/pages/layout.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/typings.d.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo6-literal-condition/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/.browserslistrc create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/ice.config.mts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/app.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/document.tsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/pages/layout.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/typings.d.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo7-literal-condition2/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/.browserslistrc create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/ice.config.mts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/app.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/document.tsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/pages/Example/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/pages/Example/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/pages/layout.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/typings.d.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo8-datasource-prop/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/.browserslistrc create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/ice.config.mts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/app.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/document.tsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/pages/$/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/pages/$/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/pages/layout.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/typings.d.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo9-datasource-engine/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/.browserslistrc create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/ice.config.mts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/app.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/document.tsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/pages/layout.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/typings.d.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_10-jsslot/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/.browserslistrc create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/ice.config.mts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/app.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/document.tsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/pages/layout.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/typings.d.ts create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo_11-jsslot-2/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/src/app.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/src/document/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/src/global.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/src/pages/Home/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/src/pages/Home/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/src/app.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/src/document/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/src/global.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/src/pages/Home/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/src/pages/Home/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/src/app.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/src/document/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/src/global.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/src/pages/Detail/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/src/pages/Detail/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/src/pages/Home/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/src/pages/Home/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/src/pages/List/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/src/pages/List/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/src/app.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/src/document/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/src/global.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/src/pages/Home/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/src/pages/Home/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/src/app.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/src/document/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/src/global.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/src/pages/Home/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/src/pages/Home/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/src/app.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/src/document/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/src/global.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/src/pages/Home/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/src/pages/Home/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/src/app.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/src/document/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/src/global.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/src/pages/Home/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/src/pages/Home/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/src/app.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/src/document/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/src/global.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/src/pages/Home/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/src/pages/Home/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/src/app.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/src/document/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/src/global.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/src/pages/Home/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/src/pages/Home/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/src/app.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/src/document/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/src/global.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/src/pages/Home/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/src/pages/Home/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/src/app.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/src/document/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/src/global.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/src/pages/Aaaa/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/src/pages/Aaaa/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/src/app.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/src/document/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/src/global.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/src/pages/Home/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/src/pages/Home/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/src/app.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/src/document/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/src/global.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/src/pages/Example/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/src/pages/Example/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/.editorconfig create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/abc.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/public/index.html create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/routes.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo1/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/.editorconfig create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/abc.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/public/index.html create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/src/pages/Aaaa/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/src/pages/Aaaa/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/src/routes.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2-utils-name-alias/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/.editorconfig create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/abc.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/public/index.html create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/src/routes.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo2/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/.editorconfig create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/abc.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/public/index.html create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/src/routes.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo3/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/.editorconfig create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/abc.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/public/index.html create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/src/routes.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo4/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/.editorconfig create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/abc.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/public/index.html create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/src/routes.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo5/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/.editorconfig create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/abc.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/public/index.html create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/src/routes.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo6-literal-condition/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/.editorconfig create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/abc.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/public/index.html create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/src/routes.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo7-literal-condition2/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/.editorconfig create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/abc.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/public/index.html create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/src/pages/Example/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/src/pages/Example/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/src/routes.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo8-datasource-prop/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/.editorconfig create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/abc.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/public/index.html create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/src/pages/$/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/src/pages/$/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/src/routes.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo9-datasource-engine/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/.editorconfig create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/abc.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/public/index.html create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/src/routes.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_10-jsslot/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/.editorconfig create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/abc.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/public/index.html create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/src/routes.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-app/demo_11-jsslot-2/schema.json5 create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/.editorconfig create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/.eslintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/.eslintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/.gitignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/.prettierignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/.prettierrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/.stylelintignore create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/.stylelintrc.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/README.md create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/abc.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/build.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/jsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/package.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/public/index.html create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/src/app.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/src/constants.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/src/global.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/src/i18n.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/src/layouts/BasicLayout/components/Footer/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/src/layouts/BasicLayout/components/Logo/index.module.scss create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/src/layouts/BasicLayout/components/PageNav/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/src/layouts/BasicLayout/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/src/layouts/BasicLayout/menuConfig.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/src/pages/Test/index.css create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/src/pages/Test/index.jsx create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/src/routes.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/src/utils.js create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/expected/demo-project/tsconfig.json create mode 100644 modules/code-generator/tests/fixtures/test-cases/react-module/demo1/schema.json5 create mode 100644 modules/code-generator/tests/helpers/solutionHelper.ts create mode 100644 modules/code-generator/tests/plugins/common/__snapshots__/requireUtils.test.ts.snap create mode 100644 modules/code-generator/tests/plugins/common/requireUtils.test.ts create mode 100644 modules/code-generator/tests/plugins/jsx/__snapshots__/p0-condition-at-root.test.ts.snap create mode 100644 modules/code-generator/tests/plugins/jsx/p0-condition-at-root.test.ts create mode 100644 modules/code-generator/tests/postprocessor/__snapshots__/prettier.test.ts.snap create mode 100644 modules/code-generator/tests/postprocessor/prettier.test.ts create mode 100644 modules/code-generator/tests/public/README.md create mode 100644 modules/code-generator/tests/public/SchemaParser/__snapshots__/p0-basic.test.ts.snap create mode 100644 modules/code-generator/tests/public/SchemaParser/data/schema-with-slot.json create mode 100644 modules/code-generator/tests/public/SchemaParser/p0-basic.test.ts create mode 100644 modules/code-generator/tests/public/cli.test.ts create mode 100644 modules/code-generator/tests/public/publisher/disk/disk.test.ts create mode 100644 modules/code-generator/tests/public/publisher/zip/zip.test.ts create mode 100644 modules/code-generator/tests/public/solutions/icejs3-app.test.ts create mode 100644 modules/code-generator/tests/public/solutions/rax-app.test.ts create mode 100644 modules/code-generator/tests/public/solutions/react-app.test.ts create mode 100644 modules/code-generator/tests/utils/compositeType.test.ts create mode 100644 modules/code-generator/tests/utils/errors.test.ts create mode 100644 modules/code-generator/tests/utils/expressionParser/jsExpression.test.ts create mode 100644 modules/code-generator/tests/utils/expressionParser/parseExpressionConvertThis2Context.test.ts create mode 100644 modules/code-generator/tests/utils/expressionParser/parseExpressionGetGlobalVariables.test.ts create mode 100644 modules/code-generator/tests/utils/expressionParser/parseExpressionGetKeywords.test.ts create mode 100644 modules/code-generator/tests/utils/flattenResult.test.ts create mode 100644 modules/code-generator/tests/utils/resultHelper/example-result.json create mode 100644 modules/code-generator/tests/utils/resultHelper/findFile.test.ts create mode 100644 modules/code-generator/tests/utils/resultHelper/globFiles.test.ts create mode 100644 modules/code-generator/tests/utils/resultHelper/removeDirsFromResult.test.ts create mode 100644 modules/code-generator/tests/utils/resultHelper/removeFilesFromResult.test.ts create mode 100644 modules/code-generator/tests/utils/resultHelper/scanFiles.test.ts create mode 100644 modules/code-generator/tests/utils/schema/data/schema-with-slot.json create mode 100644 modules/code-generator/tests/utils/schema/handleSubNodes.test.ts create mode 100644 modules/code-generator/tests/utils/validate.test.ts create mode 100644 modules/code-generator/tests/utils/version.test.ts create mode 100644 modules/code-generator/tsconfig.json create mode 100644 modules/material-parser/README.md create mode 100644 modules/material-parser/build.test.json create mode 100644 modules/material-parser/demo/component.jsx create mode 100644 modules/material-parser/demo/component.tsx create mode 100644 modules/material-parser/demo/parse-jsx.js create mode 100644 modules/material-parser/demo/parse-tsx.js create mode 100644 modules/material-parser/jest.config.js create mode 100644 modules/material-parser/package.json create mode 100644 modules/material-parser/schemas/schema.json create mode 100644 modules/material-parser/schemas/schema.yml create mode 100644 modules/material-parser/scripts/transform.js create mode 100644 modules/material-parser/src/core/index.ts create mode 100644 modules/material-parser/src/core/schema/types.ts create mode 100644 modules/material-parser/src/generate.ts create mode 100644 modules/material-parser/src/index.ts create mode 100644 modules/material-parser/src/localize.ts create mode 100644 modules/material-parser/src/parse/dynamic/index.ts create mode 100644 modules/material-parser/src/parse/dynamic/requireInSandbox.ts create mode 100644 modules/material-parser/src/parse/index.ts create mode 100644 modules/material-parser/src/parse/js/handlers/defaultPropsHandler.ts create mode 100644 modules/material-parser/src/parse/js/handlers/index.ts create mode 100644 modules/material-parser/src/parse/js/handlers/preProcessHandler.ts create mode 100644 modules/material-parser/src/parse/js/handlers/propTypeHandler.ts create mode 100644 modules/material-parser/src/parse/js/handlers/propTypeJsDocHandler.ts create mode 100644 modules/material-parser/src/parse/js/index.ts create mode 100644 modules/material-parser/src/parse/js/resolver/checkIsIIFE.ts create mode 100644 modules/material-parser/src/parse/js/resolver/findAssignedMethods.ts create mode 100644 modules/material-parser/src/parse/js/resolver/index.ts create mode 100644 modules/material-parser/src/parse/js/resolver/isReactComponentStaticMember.ts create mode 100644 modules/material-parser/src/parse/js/resolver/isStaticMethod.ts create mode 100644 modules/material-parser/src/parse/js/resolver/resolveExportDeclaration.ts create mode 100644 modules/material-parser/src/parse/js/resolver/resolveHOC.ts create mode 100644 modules/material-parser/src/parse/js/resolver/resolveIIFE.ts create mode 100644 modules/material-parser/src/parse/js/resolver/resolveImport.ts create mode 100644 modules/material-parser/src/parse/js/resolver/resolveTranspiledClass.ts create mode 100644 modules/material-parser/src/parse/js/utils/cache.ts create mode 100644 modules/material-parser/src/parse/js/utils/evaluate.ts create mode 100644 modules/material-parser/src/parse/js/utils/findJSFilePath.ts create mode 100644 modules/material-parser/src/parse/js/utils/getComposedPath.ts create mode 100644 modules/material-parser/src/parse/js/utils/getName.ts create mode 100644 modules/material-parser/src/parse/js/utils/getRoot.ts create mode 100644 modules/material-parser/src/parse/js/utils/makeProxy.ts create mode 100644 modules/material-parser/src/parse/transform.ts create mode 100644 modules/material-parser/src/parse/ts/generateDTS.ts create mode 100644 modules/material-parser/src/parse/ts/index.ts create mode 100644 modules/material-parser/src/parse/ts/tsconfig.json create mode 100644 modules/material-parser/src/scan.ts create mode 100644 modules/material-parser/src/types/Basic.ts create mode 100644 modules/material-parser/src/types/ChannelType.ts create mode 100644 modules/material-parser/src/types/DSLType.ts create mode 100644 modules/material-parser/src/types/IAccesser.ts create mode 100644 modules/material-parser/src/types/IExtensionConfigManifest.ts create mode 100644 modules/material-parser/src/types/IMaterialParsedModel.ts create mode 100644 modules/material-parser/src/types/IMaterialScanModel.ts create mode 100644 modules/material-parser/src/types/IMaterializeOptions.ts create mode 100644 modules/material-parser/src/types/Meta.ts create mode 100644 modules/material-parser/src/types/index.ts create mode 100644 modules/material-parser/src/utils.ts create mode 100644 modules/material-parser/src/validate/index.ts create mode 100644 modules/material-parser/src/validate/schema.json create mode 100644 modules/material-parser/test/__snapshots__/dynamic.test.ts.snap create mode 100644 modules/material-parser/test/__snapshots__/index.test.ts.snap create mode 100644 modules/material-parser/test/__snapshots__/online.test.ts.snap create mode 100644 modules/material-parser/test/dynamic.test.ts create mode 100644 modules/material-parser/test/fixtures/dts-component/index.d.ts create mode 100644 modules/material-parser/test/fixtures/dts-component/package.json create mode 100644 modules/material-parser/test/fixtures/dts-component/src/data.js create mode 100644 modules/material-parser/test/fixtures/dts-component/src/i18n.js create mode 100644 modules/material-parser/test/fixtures/dts-component/src/index.jsx create mode 100644 modules/material-parser/test/fixtures/dts-component/src/main.scss create mode 100644 modules/material-parser/test/fixtures/dts-component/src/scss/variable.scss create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/amContainer.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/amManifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/container.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/manifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/manifest.json create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/IconFont.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/amContainer.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/amManifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/container.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/manifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/manifest.json create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/amContainer.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/amManifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/container.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/manifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/manifest.json create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/amContainer.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/amManifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/container.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/manifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/manifest.json create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/amContainer.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/amManifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/container.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/manifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/manifest.json create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/amContainer.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/amManifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/container.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/manifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/manifest.json create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/amContainer.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/amManifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/container.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/manifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/manifest.json create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/style/index.css create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/style/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/style/index.less create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCBackgroundProps.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCBoxModelProps.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCFlexLayoutProps.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCLayoutProps.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/basic/utils/HOCTextProps.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/es/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/package.json create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/amContainer.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/amManifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/container.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/manifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/manifest.json create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/IconFont.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/amContainer.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/amManifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/container.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/manifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/manifest.json create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/amContainer.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/amManifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/container.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/manifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/manifest.json create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/amContainer.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/amManifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/container.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/manifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/manifest.json create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/amContainer.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/amManifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/container.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/manifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/manifest.json create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/amContainer.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/amManifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/container.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/manifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/manifest.json create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/amContainer.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/amManifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/container.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/manifest.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/manifest.json create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/style/index.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/style/index.less create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCBackgroundProps.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCBoxModelProps.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCFlexLayoutProps.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCLayoutProps.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/basic/utils/HOCTextProps.js create mode 100644 modules/material-parser/test/fixtures/multiple-exported-component/src/index.js create mode 100644 modules/material-parser/test/fixtures/rax-component/package.json create mode 100644 modules/material-parser/test/fixtures/rax-component/src/index.css create mode 100644 modules/material-parser/test/fixtures/rax-component/src/index.tsx create mode 100644 modules/material-parser/test/fixtures/single-exported-component/es/container.js create mode 100644 modules/material-parser/test/fixtures/single-exported-component/es/index.js create mode 100644 modules/material-parser/test/fixtures/single-exported-component/es/main.css create mode 100644 modules/material-parser/test/fixtures/single-exported-component/es/main.scss create mode 100644 modules/material-parser/test/fixtures/single-exported-component/es/manifest.js create mode 100644 modules/material-parser/test/fixtures/single-exported-component/es/manifest.json create mode 100644 modules/material-parser/test/fixtures/single-exported-component/package.json create mode 100644 modules/material-parser/test/fixtures/single-exported-component/src/index.js create mode 100644 modules/material-parser/test/fixtures/single-exported-component/src/main.scss create mode 100644 modules/material-parser/test/fixtures/transpiled-component/package.json create mode 100644 modules/material-parser/test/fixtures/ts-component/package.json create mode 100644 modules/material-parser/test/fixtures/ts-component/src/index.tsx create mode 100644 modules/material-parser/test/fixtures/ts-component/src/main-module.tsx create mode 100644 modules/material-parser/test/fixtures/ts-component/src/sub-module.tsx create mode 100644 modules/material-parser/test/fixtures/ts-component2/package.json create mode 100644 modules/material-parser/test/fixtures/ts-component2/src/empty.tsx create mode 100644 modules/material-parser/test/fixtures/ts-component2/src/index.scss create mode 100644 modules/material-parser/test/fixtures/ts-component2/src/index.tsx create mode 100644 modules/material-parser/test/fixtures/without-display-name/index.js create mode 100644 modules/material-parser/test/fixtures/without-display-name/package.json create mode 100644 modules/material-parser/test/helpers/index.ts create mode 100644 modules/material-parser/test/index.test.ts create mode 100644 modules/material-parser/test/localize.test.ts create mode 100644 modules/material-parser/test/online.test.ts create mode 100644 modules/material-parser/test/validate/__snapshots__/index.test.ts.snap create mode 100644 modules/material-parser/test/validate/fixtures/basic-error/schema.json create mode 100644 modules/material-parser/test/validate/fixtures/basic-success/schema.json create mode 100644 modules/material-parser/test/validate/fixtures/configure/schema.json create mode 100644 modules/material-parser/test/validate/fixtures/props-basic-type/schema.json create mode 100644 modules/material-parser/test/validate/fixtures/props-complex-type/schema.json create mode 100644 modules/material-parser/test/validate/index.test.ts create mode 100644 modules/material-parser/tsconfig.json create mode 100644 modules/material-parser/webpack.config.js diff --git a/modules/code-generator/.gitignore b/modules/code-generator/.gitignore new file mode 100644 index 0000000..bf10c9f --- /dev/null +++ b/modules/code-generator/.gitignore @@ -0,0 +1,122 @@ +# project custom +build +es +dist +output +package-lock.json +yarn.lock +deploy-space/packages +deploy-space/.env +/demo/ +/demo-output*/ +/generated/ + +# IDE +.vscode +.idea + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release +lib + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# mac config files +.DS_Store + +# codealike +codealike.json +.node + +# def publish +.package + +# types +/types + +# backup files +*.bak + +# tests +tests/fixtures/**/actual + + + diff --git a/modules/code-generator/.prettierrc.js b/modules/code-generator/.prettierrc.js new file mode 100644 index 0000000..24c5859 --- /dev/null +++ b/modules/code-generator/.prettierrc.js @@ -0,0 +1,7 @@ +module.exports = { + printWidth: 100, + tabWidth: 2, + semi: true, + singleQuote: true, + trailingComma: 'all', +}; diff --git a/modules/code-generator/.versionrc b/modules/code-generator/.versionrc new file mode 100644 index 0000000..a41c11e --- /dev/null +++ b/modules/code-generator/.versionrc @@ -0,0 +1,3 @@ +{ + "releaseCommitMessageFormat": "chore(release): code-generator - {{currentTag}}" +} \ No newline at end of file diff --git a/modules/code-generator/CHANGELOG.md b/modules/code-generator/CHANGELOG.md new file mode 100644 index 0000000..8a6c546 --- /dev/null +++ b/modules/code-generator/CHANGELOG.md @@ -0,0 +1,266 @@ +# Changelog + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + +### [1.0.7-beta.2](https://github.com/fe-lce/lowcode-engine/compare/@felce/lowcode-code-generator@1.0.3...@felce/lowcode-code-generator@1.0.7-beta.2) (2022-11-24) + +### Bug Fixes + +- 🐛 解决 react 中 jsx 出码的时候对于循环数据漏包 \_\_$evalArray 的问题 ([3b9b177](https://github.com/fe-lce/lowcode-engine/commit/3b9b177b052169cd0c1078cf8b488f04cb374dac)) +- 🐛 解决出码缺乏对于 i18n 数据的 params 的处理的问题 ([2cf788c](https://github.com/fe-lce/lowcode-engine/commit/2cf788c1716ae63fef20004348c59a5a65c6b3d2)), closes [#288](https://github.com/fe-lce/lowcode-engine/issues/288) +- 🐛 解决小程序环境没有 window, 而 rax 出码中却默认在 \_\_$eval 中用到 window 的问题 ([ce531ae](https://github.com/fe-lce/lowcode-engine/commit/ce531aeb457711fac92d828b431cfc3d643b3682)) +- add support for jsx expression ([453e069](https://github.com/fe-lce/lowcode-engine/commit/453e0699ece06d98e59227e23248baf1de4082aa)) +- 修复生成的 icejs 项目不支持 constants 的问题, fixes [#1259](https://github.com/fe-lce/lowcode-engine/issues/1259) ([a079fbc](https://github.com/fe-lce/lowcode-engine/commit/a079fbc256f8275e8a69eb6d8abb6f6b08179578)) +- 修正 react 框架出码中在严格模式对 methods 和 context 的处理 ([b1a6100](https://github.com/fe-lce/lowcode-engine/commit/b1a61006bba4292790899c7c49c9c611a9384472)) + +### [1.0.7-beta.1](https://github.com/fe-lce/lowcode-engine/compare/@felce/lowcode-code-generator@1.0.7-beta.0...@felce/lowcode-code-generator@1.0.7-beta.1) (2022-10-26) + +### Bug Fixes + +- fix empty string lost when generate variable ([2cf74cd](https://github.com/fe-lce/lowcode-engine/commit/2cf74cd04b4f48a3501d37329d39784f6964366a)) + +### [1.0.7-beta.0](https://github.com/fe-lce/lowcode-engine/compare/@felce/lowcode-code-generator@1.0.6-beta.0...@felce/lowcode-code-generator@1.0.7-beta.0) (2022-10-25) + +### [1.0.6-beta.0](https://github.com/fe-lce/lowcode-engine/compare/@felce/lowcode-code-generator@1.0.3...@felce/lowcode-code-generator@1.0.6-beta.0) (2022-10-25) + +### Features + +- 🎸 设计态支持数据源引擎配置 ([04631f8](https://github.com/fe-lce/lowcode-engine/commit/04631f813782dbf6d175f51c40ccc75ca4c099d2)) +- 大纲树支持节点过滤 ([f30db20](https://github.com/fe-lce/lowcode-engine/commit/f30db20606f5f2fdac0017305b1dda7ab2258c4b)) +- 为 renderer 追加 displayName,以支持后续的反射功能 ([6399cce](https://github.com/fe-lce/lowcode-engine/commit/6399cce05ae494dac6facf4366949b0b97576079)) +- 资产包支持一个package从另一个package异步导出 ([#1150](https://github.com/fe-lce/lowcode-engine/issues/1150)) ([6b78157](https://github.com/fe-lce/lowcode-engine/commit/6b78157b211d6eabf60297b9ce980a3e10cc8272)) +- add availableActions for ComponentMeta ([de1f60b](https://github.com/fe-lce/lowcode-engine/commit/de1f60bbee157267e2c2212df1077cc49ce506f4)) +- add code coverage action ([ed3ddcf](https://github.com/fe-lce/lowcode-engine/commit/ed3ddcf5c942a8e78e1f247e41d4159da97e75a8)) +- add componentMeta getter for setingPropEntry ([2f8b954](https://github.com/fe-lce/lowcode-engine/commit/2f8b9545de0210260001a832b52f608238ac4191)) +- add expanded to shell SettingPropEntry ([534e294](https://github.com/fe-lce/lowcode-engine/commit/534e29429d445d97c71d95d4c4e492868527bb6b)) +- add flag createIfNode for ShellNode#getProp ([152a24d](https://github.com/fe-lce/lowcode-engine/commit/152a24d65528d0a3b7990c9aa87e6d8d09aa9b2a)) +- add getComponentsMap() for DocumentModel ([f956645](https://github.com/fe-lce/lowcode-engine/commit/f9566454ef83eb4c48b68d63a766c3d0ff927c73)) +- add getExtraPropValue setExtraPropValue to shell SettingPropEntry ([70e7c1c](https://github.com/fe-lce/lowcode-engine/commit/70e7c1c2e8998e80d58447759efdf651105724a9)) +- add id setter for DocumentModel ([941ae05](https://github.com/fe-lce/lowcode-engine/commit/941ae0592586334694c48197aaa6692d49cefbce)) +- add importSchema event for documentModel ([4b8ec09](https://github.com/fe-lce/lowcode-engine/commit/4b8ec09e86e3950a9d4066c28e681a59273b4c93)) +- add isGroup & items to shell SettingPropEntry ([7b76ff3](https://github.com/fe-lce/lowcode-engine/commit/7b76ff357e4e638454c31a9b1324fb68966ec522)) +- add mergeChldren API for shell node ([a47d4ee](https://github.com/fe-lce/lowcode-engine/commit/a47d4eea28cf4479e3b3a2bd1d194a6433666825)) +- add onMountNode event for DocumentModel ([dcc247c](https://github.com/fe-lce/lowcode-engine/commit/dcc247c7d54f6af2ed36d46bfd79c7eacf7bd604)) +- add renderer for simulatorHost ([1cfc8d6](https://github.com/fe-lce/lowcode-engine/commit/1cfc8d668b8897ef3a53c11520312cc6d18338f9)) +- add script for synchronizing packages to intranet registry ([b4f463e](https://github.com/fe-lce/lowcode-engine/commit/b4f463e7d45f7b476de04bd4d98ad9f74d53cf13)) +- add scrollToNode for simulator host ([#1075](https://github.com/fe-lce/lowcode-engine/issues/1075)) ([0bcd9ff](https://github.com/fe-lce/lowcode-engine/commit/0bcd9ff78227aeddaf2fdc22d10fbd662fed91d3)) +- add setVisible for Node ([ba90327](https://github.com/fe-lce/lowcode-engine/commit/ba90327eac0f5f82f6349bb9a7684bf51259e9c9)) +- add showArea & hideArea method for skeleton ([8f6b53e](https://github.com/fe-lce/lowcode-engine/commit/8f6b53e67d89ee7af754132f0994a759522b3821)) +- add slotNode for shell prop ([d9a44c5](https://github.com/fe-lce/lowcode-engine/commit/d9a44c5de7861e9180567b4afb787e381cefac61)) +- add some features ([18d1a4f](https://github.com/fe-lce/lowcode-engine/commit/18d1a4fe1d952bcd4715e693def09fee94da49a5)) +- add some necessary methods and attributes ([4fd7f27](https://github.com/fe-lce/lowcode-engine/commit/4fd7f27f8eb33b66324ede279b412940fc1f7032)) +- add some params for onDragstart & onDrag & onDragend ([d1c9838](https://github.com/fe-lce/lowcode-engine/commit/d1c9838343ba1bdd4c02c1cfbf1f920dd8c87e7d)) +- add top attrbute for Shell SettingPropEntry ([51aca3d](https://github.com/fe-lce/lowcode-engine/commit/51aca3d330b6483c05b71867f1b362a9f5db6cfe)) +- added lowcode engine standard specs ([f25feba](https://github.com/fe-lce/lowcode-engine/commit/f25feba63f181efa83f1a8dff530e1c39ab1b34c)) +- added lowcode engine standard specs ([57df803](https://github.com/fe-lce/lowcode-engine/commit/57df803179ca9cec4e8ab1dac1be577175732e65)) +- added thisRequiredInJSE API to control whether JSExpression expression access context must use this ([#702](https://github.com/fe-lce/lowcode-engine/issues/702)) ([da7f77e](https://github.com/fe-lce/lowcode-engine/commit/da7f77ee91b3bf441a4a57614872df32d6a1d041)) +- assetLoader loda scripts with async=false ([f6ad4a1](https://github.com/fe-lce/lowcode-engine/commit/f6ad4a157df8c0ff7db327f4770f454998693d9a)) +- change loop sertter config, set defaultValue prop to JsonSetter ([aa6b9c8](https://github.com/fe-lce/lowcode-engine/commit/aa6b9c8f7a5353771af9f46216310f044e57c533)) +- cp dist files of simulator-renderer to that of engine ([03c5397](https://github.com/fe-lce/lowcode-engine/commit/03c53971df6de8c35620fd77743ac4f57a82d323)) +- export nodeChildrenSymbol && remove some unnecessary editor.set ([e83adce](https://github.com/fe-lce/lowcode-engine/commit/e83adcee815eea73b6b1ed4f43f4d684c11818ca)) +- fix render-core leaf hoc component condition config should get from leaf exportSchema fn ([85704c3](https://github.com/fe-lce/lowcode-engine/commit/85704c36946191a1b88db789cfac59e9d027a371)) +- low-code components support lifecycle and function execution ([176583f](https://github.com/fe-lce/lowcode-engine/commit/176583f48af573d30c0d2c36faa3d901b0541c06)) +- **material-parser:** check module before install it; fix default value issue in ts parser ([fc452f7](https://github.com/fe-lce/lowcode-engine/commit/fc452f7166f02acfba6076c1a9425e6f5880b5f6)) +- modify the output method of rendering module parsing errors ([8255b79](https://github.com/fe-lce/lowcode-engine/commit/8255b7945836ee5d25fae73913faa6d0af7b3ff3)) +- pass e to customizeIgnoreSelectors ([900b239](https://github.com/fe-lce/lowcode-engine/commit/900b2394323e85f0dce5df83dfc773f96da23e24)) +- refine nesting drawer ([4c032d0](https://github.com/fe-lce/lowcode-engine/commit/4c032d0d0ead9731c038bd62dccc4a7d96435183)) +- refine nesting drawer ([94a211e](https://github.com/fe-lce/lowcode-engine/commit/94a211e2795f74721cfd2ae3ff38a1d3607e9cd0)) +- refine pop drawer ([abf8fae](https://github.com/fe-lce/lowcode-engine/commit/abf8fae3ef4d62b5688362e1b98f1b508a207029)) +- requestHandlersMap should be optional ([ee7160e](https://github.com/fe-lce/lowcode-engine/commit/ee7160ea3c625d421c07730ef51711b8f14392a0)) +- return unbind function for onChangeDetecting & onChangeSelection ([30267cb](https://github.com/fe-lce/lowcode-engine/commit/30267cb173fca2cd80a61450b9f2fe2bceac0f06)) +- support for hiding settings tabs when there is only one item ([#669](https://github.com/fe-lce/lowcode-engine/issues/669)) ([cbd95a1](https://github.com/fe-lce/lowcode-engine/commit/cbd95a1778415406670f37507ce957af6b3ecd4a)) +- support for NotFoundComponent design state is optional ([#1013](https://github.com/fe-lce/lowcode-engine/issues/1013)) ([d3c891e](https://github.com/fe-lce/lowcode-engine/commit/d3c891e2a46d138e31c81a7f9b804a8240154df5)) +- support opening document with id ([3f7c0cd](https://github.com/fe-lce/lowcode-engine/commit/3f7c0cd5191b7924f2630c58e6439f4d4a936ac9)) +- support SPA mode ([1f9150e](https://github.com/fe-lce/lowcode-engine/commit/1f9150e4b260d522bd7cb31497069b700a1e8576)) +- sync utils/constants ([#506](https://github.com/fe-lce/lowcode-engine/issues/506)) ([2871b5b](https://github.com/fe-lce/lowcode-engine/commit/2871b5ba4c3dbf1ed76bf4d6359fb457190a9b22)) +- the tips when dragging a component from the component panel same with the moving component ([dbe0764](https://github.com/fe-lce/lowcode-engine/commit/dbe0764ff4901450f03ca56b62167fbc87d2524a)) + +### Bug Fixes + +- 🐛 解决 react 中 jsx 出码的时候对于循环数据漏包 \_\_$evalArray 的问题 ([3b9b177](https://github.com/fe-lce/lowcode-engine/commit/3b9b177b052169cd0c1078cf8b488f04cb374dac)) +- 🐛 解决出码缺乏对于 i18n 数据的 params 的处理的问题 ([2cf788c](https://github.com/fe-lce/lowcode-engine/commit/2cf788c1716ae63fef20004348c59a5a65c6b3d2)), closes [#288](https://github.com/fe-lce/lowcode-engine/issues/288) +- 🐛 解决小程序环境没有 window, 而 rax 出码中却默认在 \_\_$eval 中用到 window 的问题 ([ce531ae](https://github.com/fe-lce/lowcode-engine/commit/ce531aeb457711fac92d828b431cfc3d643b3682)) +- 🐛 修复数据源引擎请求处理器映射严格模式下被过滤的问题 ([75626d8](https://github.com/fe-lce/lowcode-engine/commit/75626d877db017b8862b1d5e64d75f3af7ff667a)) +- 🐛 修正 i18n 里面的一个参数命名问题 ([20c6fca](https://github.com/fe-lce/lowcode-engine/commit/20c6fca03e99b11fa5c257cbbda0d4d23f410090)) +- 新元素无法在大纲树拖拽 ([3d41fd5](https://github.com/fe-lce/lowcode-engine/commit/3d41fd5d0783048a7cfb54c6f80d058856153d25)) +- 修复React17选中组件bug ([750d282](https://github.com/fe-lce/lowcode-engine/commit/750d282c03a880204fefdef01e180510465b82f8)) +- 修正 react 框架出码中在严格模式对 methods 和 context 的处理 ([b1a6100](https://github.com/fe-lce/lowcode-engine/commit/b1a61006bba4292790899c7c49c9c611a9384472)) +- 左侧抽屉固定模式层级不足 ([c657cee](https://github.com/fe-lce/lowcode-engine/commit/c657cee0694e3126dee89588a2aa17c4e118f786)) +- add lowcode-designer, lowcode-utils dependencies ([d250242](https://github.com/fe-lce/lowcode-engine/commit/d2502427ca988881747a35bd8da49f024939b833)) +- add support for jsx expression ([1043ef8](https://github.com/fe-lce/lowcode-engine/commit/1043ef82b1e9ceefc3b74fd21eb28e9a740bd1db)) +- addon-combine affect metadata unexpectedly ([fc5fbc6](https://github.com/fe-lce/lowcode-engine/commit/fc5fbc63a04a32bc887754f32e74c76149d74b05)) +- adjust synchronize-order of packages ([81a7304](https://github.com/fe-lce/lowcode-engine/commit/81a73049bd848524e1156761ded08ddf325863ba)) +- change typescript type export to export type ([50e4a03](https://github.com/fe-lce/lowcode-engine/commit/50e4a03b7d810131ce413cc057b43d4a726f1ebe)) +- change typescript type export to export type ([573504b](https://github.com/fe-lce/lowcode-engine/commit/573504b0e3537ca60d234ce2b2f3feedb323405e)) +- declare parameter appHelper for valid engine options ([058a842](https://github.com/fe-lce/lowcode-engine/commit/058a84226af8ca19d8c7d63599d80d0cdf70281c)) +- defaultValue should be evaluated inspite of condition result is falsy, fixes [#1045](https://github.com/fe-lce/lowcode-engine/issues/1045) ([fcfce3c](https://github.com/fe-lce/lowcode-engine/commit/fcfce3cbeb5a53600c40aea07ffef19c9c9591c4)) +- delete the defaultValue configuration outside the loop ([acf7449](https://github.com/fe-lce/lowcode-engine/commit/acf7449ca231d45e8ed7e1d9416817ea11b1266f)) +- delete unused typescript types ([63f5d2c](https://github.com/fe-lce/lowcode-engine/commit/63f5d2ca3e0bda92898fd0df28c9500707812082)) +- delete unused typescript types ([2432aed](https://github.com/fe-lce/lowcode-engine/commit/2432aed83d55407d2f8b5f94910ada7ea78bb59e)) +- designer/loadIncrementalAssets await Sequential ([#841](https://github.com/fe-lce/lowcode-engine/issues/841)) ([8232424](https://github.com/fe-lce/lowcode-engine/commit/823242469743d235923b3b946ec7d2db70887ead)) +- error thrown when triggering undo after save schema on SchemaPane ([9be46e7](https://github.com/fe-lce/lowcode-engine/commit/9be46e7b34e3a40cbc489dbae4bfd0915c2090e3)) +- fallback focusNode to root if empty ([a9a118f](https://github.com/fe-lce/lowcode-engine/commit/a9a118fe6e79080245c6eea42ed26772b7c784ca)) +- **filter:** unique key prop warning ([3fe6e41](https://github.com/fe-lce/lowcode-engine/commit/3fe6e41536cd3a9b9c7eaca5b353de4bd1f91b11)) +- **filter:** unique key prop warning ([06e6920](https://github.com/fe-lce/lowcode-engine/commit/06e6920602bdf21b6e1ffe5cfa3dfe4856e7c57e)) +- fix css resources with parameters not loading correctly ([f859752](https://github.com/fe-lce/lowcode-engine/commit/f85975211814147d40ae5330a76cb21cb6c66916)) +- fix css resources with parameters not loading correctly ([9a5a04a](https://github.com/fe-lce/lowcode-engine/commit/9a5a04ac9560fb6a51bf4e0ed8ea446381d39c35)) +- fix dataSource needs to be compatible due to empty schema ([98bc477](https://github.com/fe-lce/lowcode-engine/commit/98bc477d80dbf7993f89befdb42762d78a55fb1b)) +- fix displayName spell mistake ([2b2bcbd](https://github.com/fe-lce/lowcode-engine/commit/2b2bcbdaebde6a3ce974072f586386ef7ef3497c)) +- fix internal project.getSchema default stage is error ([0d40db2](https://github.com/fe-lce/lowcode-engine/commit/0d40db2581f4fe5a9e22f763f21aec641e366c34)) +- fix lint issues for renderer-core/renderer/base ([d85437d](https://github.com/fe-lce/lowcode-engine/commit/d85437d4af1043371e27dfde98cecf914b93a126)) +- fix lint issues for renderer-core/renderer/base ([4b59190](https://github.com/fe-lce/lowcode-engine/commit/4b59190c7f9d518bc7efac44b7eeee73f1b5d177)) +- fix low-code component rendering problems: 1. thisRequiredInJSE does not take effect 2. jsx components cannot obtain source components ([5dd4625](https://github.com/fe-lce/lowcode-engine/commit/5dd462544fbbbccfa97165f2bcfeed8629fab2a3)) +- fix material-spec demo ([438cccd](https://github.com/fe-lce/lowcode-engine/commit/438cccd58e4341638070c1d8b2d4e78e4e20e3fb)) +- fix misused doc urls ([16a8857](https://github.com/fe-lce/lowcode-engine/commit/16a88578634b9da2f04698df5ca5a5e69151bb97)) +- fix monitor utils incorrect assignment method ([bf280c6](https://github.com/fe-lce/lowcode-engine/commit/bf280c6fa1e46d084fc8f20323164816fad4076f)) +- fix outline-pane invisible occasionally when dragging tree node ([031c7f2](https://github.com/fe-lce/lowcode-engine/commit/031c7f25f10a6cfebfc7929c9226f4e4167a359f)) +- fix outline-tree initialization failed ([a2d5c6f](https://github.com/fe-lce/lowcode-engine/commit/a2d5c6fd90ca0226bbbfea01a4b28c8b8d307a78)) +- fix render module state expression initialization exception ([5bd68ee](https://github.com/fe-lce/lowcode-engine/commit/5bd68ee6b448fa58b022870b3f8175d8b77febde)) +- fix render module state expression initialization exception ([9c545cc](https://github.com/fe-lce/lowcode-engine/commit/9c545cca6004f65e2f206ea001cefa3fa3cfa807)) +- fix setter hooks error ([8a3a0b8](https://github.com/fe-lce/lowcode-engine/commit/8a3a0b824162e25a930711c6fef511b4b369e897)) +- fix test case failures of designer ([4b0521a](https://github.com/fe-lce/lowcode-engine/commit/4b0521a47494f78e120f75021e0a076fb00ce53e)) +- Fix the conversion failure of some props expressions under Slot props of low-code components ([7db5461](https://github.com/fe-lce/lowcode-engine/commit/7db5461706c739fac673b2466bc2fda7661242e4)) +- fix the leaf hoc component fails to monitor Node changes, and modify the logic for get node ([6ee6b07](https://github.com/fe-lce/lowcode-engine/commit/6ee6b07a10ba4aac583def52d8ff1fa78d111d0b)) +- fix the leaf hoc component fails to monitor Node changes, and modify the logic for get node ([f400172](https://github.com/fe-lce/lowcode-engine/commit/f4001728259047b09db75d76a8c3ef1e1bcb4e0a)) +- fix the problem that material.getComponentMetasMap returns the wrong result ([e02933c](https://github.com/fe-lce/lowcode-engine/commit/e02933c18bc15519b2eba8ad946282502a509611)) +- Fix the rendering error caused by incorrect key value when configuring the loop ([1026763](https://github.com/fe-lce/lowcode-engine/commit/1026763dc5a77d4395a1e86e5a0084ab4fb4230c)) +- fix the unit test failure problem caused by thisRequiredInJSE modification ([c2c59b7](https://github.com/fe-lce/lowcode-engine/commit/c2c59b7ff72ba06156bbcdb952262739d6188209)) +- fix unnecessary props calculation ([f1fed75](https://github.com/fe-lce/lowcode-engine/commit/f1fed75f39be8289ede1ec558b04428a69e25b5f)) +- fixed an issue where materials would be rendered multiple times ([9d187cc](https://github.com/fe-lce/lowcode-engine/commit/9d187ccb7de55857e861d3fc881c610506872d03)) +- fixed an issue where materials would be rendered multiple times ([64cc328](https://github.com/fe-lce/lowcode-engine/commit/64cc3283c15342151a8f93c46a276681f3575153)) +- fixed focusNodeSelector configuration not taking effect ([9beae9c](https://github.com/fe-lce/lowcode-engine/commit/9beae9c3269901bf03a29033121c7d480571bce5)) +- fixed the issue that thisRequiredInJSE did not take effect in some scenarios ([7e5a919](https://github.com/fe-lce/lowcode-engine/commit/7e5a919f9352397f11741fd911495996469c0256)) +- in ES require changed to import ([b4d7d6d](https://github.com/fe-lce/lowcode-engine/commit/b4d7d6d8c290a335a2c1f60731d4417b23444941)) +- in ES require changed to import ([7c8cd36](https://github.com/fe-lce/lowcode-engine/commit/7c8cd36a10a7caa61de31a15abd93ab8a97fbe08)) +- leaf should be type of ShellNode other than InnerNode ([5bb8cf5](https://github.com/fe-lce/lowcode-engine/commit/5bb8cf5d12d38d70b69fa28deb2f8aa0afa9b9b9)) +- lowcode component exec lifecycle has error ([f99a47e](https://github.com/fe-lce/lowcode-engine/commit/f99a47e502080134454795f5e361cfa4fba3f03b)) +- lowcode component leaf dont have export prop, exec leaf.export make error ([9d51dcd](https://github.com/fe-lce/lowcode-engine/commit/9d51dcdae38850be0206861f2cae74ca68805c25)) +- missing engine options config info ([a79875c](https://github.com/fe-lce/lowcode-engine/commit/a79875cf8698d3912b50526d97f6ac72e9a21fc9)) +- missing engine options config info ([9ccded0](https://github.com/fe-lce/lowcode-engine/commit/9ccded006ef44cd538abaa140250e519243bf090)) +- npm run clean error in windows ([a176e9d](https://github.com/fe-lce/lowcode-engine/commit/a176e9d245981fb5718c8d144f477202b3796be6)) +- project event listeners will not be invoked sometimes ([a0c772f](https://github.com/fe-lce/lowcode-engine/commit/a0c772fb903cf5eb9e0b811b64bbe3846d4ba8ac)) +- project.exportSchema api lack stage param & setAssets should be a async fn ([0ea76a7](https://github.com/fe-lce/lowcode-engine/commit/0ea76a746fac8ea8e7b999d42434c468c85d6372)) +- project.exportSchema should export componentsMap of all documents ([969a130](https://github.com/fe-lce/lowcode-engine/commit/969a130b373fb028f8051e96cb9d79f1de0a2a1c)) +- removed incorrectly calling childWhitelist hook logic during drag and drop ([#1141](https://github.com/fe-lce/lowcode-engine/issues/1141)) ([6576346](https://github.com/fe-lce/lowcode-engine/commit/6576346b9185bedb090be9c84129e077cf5389b3)) +- renderer not rendering correct components when loading components with loadAsyncLibrary api ([9b3b4f9](https://github.com/fe-lce/lowcode-engine/commit/9b3b4f9b0e35ef3ea2f0117f0cdb2254e15d5389)) +- should pass index param when creating a Prop instance under a list type Prop instance, fix [#780](https://github.com/fe-lce/lowcode-engine/issues/780) ([a8de3f2](https://github.com/fe-lce/lowcode-engine/commit/a8de3f299c7b26fa939d2b2ea1428143e2b5fb01)) +- simulator eclipses setting area [#773](https://github.com/fe-lce/lowcode-engine/issues/773) ([b4b30a3](https://github.com/fe-lce/lowcode-engine/commit/b4b30a359932f5c0e8fde1b28f54a883c87901d8)) +- spec typo ([#1064](https://github.com/fe-lce/lowcode-engine/issues/1064)) ([ecb9dca](https://github.com/fe-lce/lowcode-engine/commit/ecb9dca2b9386ef6fadfd009d161a9203b9b9558)) +- try catch calculation of dynamic setter ([f61e2a2](https://github.com/fe-lce/lowcode-engine/commit/f61e2a2b8a3d8d6754474cd392bc259917c7eb10)) +- type=legao dont make request ([98ececa](https://github.com/fe-lce/lowcode-engine/commit/98ececa9c11f93e5f849b201b5b5e7ff453733d7)) +- **types:** rrror declaration of the children prop ([951d1cb](https://github.com/fe-lce/lowcode-engine/commit/951d1cb103fa46c0e7926d6138657c7d10cc4f88)) +- use the original object if it is not a shell object ([5ea53f7](https://github.com/fe-lce/lowcode-engine/commit/5ea53f706b6571946bcfa56b8655b55717381771)) +- use the outer documentation url of unique key, fixes [#868](https://github.com/fe-lce/lowcode-engine/issues/868) ([d770007](https://github.com/fe-lce/lowcode-engine/commit/d770007ff8c39e6cf527e07a7d6468dbb88c776d)) +- use the outer documentation url of unique key, fixes [#868](https://github.com/fe-lce/lowcode-engine/issues/868) ([912ee22](https://github.com/fe-lce/lowcode-engine/commit/912ee22180a424f63298c319c62fb481513af904)) +- use uppercase resize trigger names based on material spec ([7fda0ef](https://github.com/fe-lce/lowcode-engine/commit/7fda0efe131e0e2e3141849cf3f87307e7ce1b36)) +- when designMode is not design, the hidden attribute does not take effect ([3dd0b6d](https://github.com/fe-lce/lowcode-engine/commit/3dd0b6d0a86267e3029c176ff49aff793ce3e186)) + +### [1.0.4](https://github.com/fe-lce/lowcode-engine/compare/@felce/lowcode-code-generator@1.0.4-beta.0...@felce/lowcode-code-generator@1.0.4) (2022-04-12) + +### Bug Fixes + +- 🐛 解决 react 中 jsx 出码的时候对于循环数据漏包 \_\_$evalArray 的问题 ([eb4cc69](https://github.com/fe-lce/lowcode-engine/commit/eb4cc693f5dbcae54546c569eb8fa331d074e062)) + +### [1.0.4-beta.1](https://github.com/fe-lce/lowcode-engine/compare/@felce/lowcode-code-generator@1.0.4-beta.0...@felce/lowcode-code-generator@1.0.4-beta.1) (2022-04-11) + +### Bug Fixes + +- 🐛 解决 react 中 jsx 出码的时候对于循环数据漏包 \_\_$evalArray 的问题 ([987f4ce](https://github.com/fe-lce/lowcode-engine/commit/987f4cea54ef8a75d0b63a0268b5a20b2938b8a7)) + +### [1.0.4-beta.0](https://github.com/fe-lce/lowcode-engine/compare/@felce/lowcode-code-generator@1.0.3...@felce/lowcode-code-generator@1.0.4-beta.0) (2022-04-10) + +### Features + +- **material-parser:** check module before install it; fix default value issue in ts parser ([fc452f7](https://github.com/fe-lce/lowcode-engine/commit/fc452f7166f02acfba6076c1a9425e6f5880b5f6)) + +### Bug Fixes + +- 🐛 修正 i18n 里面的一个参数命名问题 ([1e9e388](https://github.com/fe-lce/lowcode-engine/commit/1e9e388ce9104d76c4f6d9bc513c57e5059d7982)) +- 🐛 解决出码缺乏对于 i18n 数据的 params 的处理的问题 ([1eb9add](https://github.com/fe-lce/lowcode-engine/commit/1eb9addd8df2323f9aabac87af32ac2efcd6bf22)), closes [#288](https://github.com/fe-lce/lowcode-engine/issues/288) +- 🐛 解决小程序环境没有 window, 而 rax 出码中却默认在 \_\_$eval 中用到 window 的问题 ([67dabb0](https://github.com/fe-lce/lowcode-engine/commit/67dabb04beb32b6e94eb1276222e53b416e47c9d)) +- Fix the conversion failure of some props expressions under Slot props of low-code components ([7db5461](https://github.com/fe-lce/lowcode-engine/commit/7db5461706c739fac673b2466bc2fda7661242e4)) +- fix unnecessary props calculation ([f1fed75](https://github.com/fe-lce/lowcode-engine/commit/f1fed75f39be8289ede1ec558b04428a69e25b5f)) +- 修正 react 框架出码中在严格模式对 methods 和 context 的处理 ([79db4ac](https://github.com/fe-lce/lowcode-engine/commit/79db4ac97f34f24b7f7460fb3fc67521967f8cc5)) + +### [1.0.3](https://github.com/fe-lce/lowcode-engine/compare/@felce/lowcode-code-generator@1.0.2...@felce/lowcode-code-generator@1.0.3) (2022-03-29) + +### Features + +- add getConvertedExtraKey / getOriginalExtraKey to utils ([8e7bb9d](https://github.com/fe-lce/lowcode-engine/commit/8e7bb9d4b86454dd77c6928eb769cd764cad8630)) + +### Bug Fixes + +- 🐛 出码: 解决 componentName 和 exportName 不一致时生成的 import 语句的问题 ([eefc091](https://github.com/fe-lce/lowcode-engine/commit/eefc091ee7e86d6214d20d486212cb5aff237946)) +- component cannot be redisplayed by configuration after rendering is closed ([c54f369](https://github.com/fe-lce/lowcode-engine/commit/c54f369e1860d818479dda9d6429f851c0b08fa6)) +- fix loop configuration auto fill empty array issue ([d087092](https://github.com/fe-lce/lowcode-engine/commit/d087092fd712eff0556adacda692d3ff6f2f9f22)) +- make important true by default ([c63b6e1](https://github.com/fe-lce/lowcode-engine/commit/c63b6e1bfadc3fc87ed41840952e02ffbff24fab)) +- make insertAfter & insertBefore work ([70fd372](https://github.com/fe-lce/lowcode-engine/commit/70fd3720d098d6e227acb9281ee22feee66b9c0b)) +- npm源 ([437adcc](https://github.com/fe-lce/lowcode-engine/commit/437adccf5f2dbb400de6e2bef10cfc4b65286f2b)) +- prop should return undefined when all items are undefined ([5bb9ec7](https://github.com/fe-lce/lowcode-engine/commit/5bb9ec7a1dfaabfdb5369226b54d5f63a7999e59)) +- should not create new prop while querying fileName ([19c207d](https://github.com/fe-lce/lowcode-engine/commit/19c207d29de045f473ba73baaf34e7294d40261a)) +- variable binding lost after modify the mock value ([ef95b56](https://github.com/fe-lce/lowcode-engine/commit/ef95b5683273d8302bde1582de8afe3d87a808d8)) +- Workbench should receive the original skeleton other than shell skeleton ([d5c3ca1](https://github.com/fe-lce/lowcode-engine/commit/d5c3ca1068ce2c2140980bd059d0da333574dc34)) + +### [1.0.2](https://github.com/fe-lce/lowcode-engine/compare/@felce/lowcode-code-generator@1.0.2-beta.1...@felce/lowcode-code-generator@1.0.2) (2022-03-08) + +### [1.0.2-beta.1](https://github.com/fe-lce/lowcode-engine/compare/@felce/lowcode-code-generator@1.0.2-beta.0...@felce/lowcode-code-generator@1.0.2-beta.1) (2022-03-08) + +### Bug Fixes + +- 🐛 补充 icejs 模板中缺失的依赖包 ([a94553e](https://github.com/fe-lce/lowcode-engine/commit/a94553e503d439b67478df6a34950d9e3d15a063)) + +### [1.0.2-beta.0](https://github.com/fe-lce/lowcode-engine/compare/@felce/lowcode-code-generator@1.0.0...@felce/lowcode-code-generator@1.0.2-beta.0) (2022-03-08) + +### Features + +- 在 skeleton 增加几个方法和事件 ([a7d436a](https://github.com/fe-lce/lowcode-engine/commit/a7d436a0525a0ce0c7229710077111f283b452f4)) +- modify npm private control & version ([ee55d02](https://github.com/fe-lce/lowcode-engine/commit/ee55d024a7f964ccf35a0efabec817364cea8041)) +- modify yuque link in README ([d522034](https://github.com/fe-lce/lowcode-engine/commit/d522034879d20a7b5ed12f8fe02a30662a2ea7c6)) +- remove CHANGELOG.md ([b996414](https://github.com/fe-lce/lowcode-engine/commit/b996414c436b5d2439c8368eb4e001cdbcd02892)) +- remove module field in material-parser package.json ([6141c27](https://github.com/fe-lce/lowcode-engine/commit/6141c273c9c32eea22b5374679fe625e6ea15394)) +- rename build:umd ([23c7959](https://github.com/fe-lce/lowcode-engine/commit/23c795931e1d5cf43e9c21cd902441c69c1ecc63)) +- replace tnpm with npm ([36caf0f](https://github.com/fe-lce/lowcode-engine/commit/36caf0f18980c16f7ebb82ac845ad6b33e033567)) +- support UMD packageing for react-renderer ([982d0d6](https://github.com/fe-lce/lowcode-engine/commit/982d0d676b3dfbfc10a2190c0040126d6925ed37)) + +### Bug Fixes + +- 🐛 去掉 npm 上没有的依赖 ([#68](https://github.com/fe-lce/lowcode-engine/issues/68)) ([e7ce779](https://github.com/fe-lce/lowcode-engine/commit/e7ce77987eb05871dd1675d2a88367c5569bfbff)) +- 兼容 setters 为空的情况 ([56b459a](https://github.com/fe-lce/lowcode-engine/commit/56b459a017a8350a911ef20f0166d1e62b6390e4)) +- 解决 package.json 中误添加了没有用到的数据源类型的 handler 的包的问题 ([#56](https://github.com/fe-lce/lowcode-engine/issues/56)) ([76341c8](https://github.com/fe-lce/lowcode-engine/commit/76341c8456b227192bb65537dc3d16033db0b3a1)) +- 解决出码的一些问题 ([#87](https://github.com/fe-lce/lowcode-engine/issues/87)) ([4a01c97](https://github.com/fe-lce/lowcode-engine/commit/4a01c97ea6bf23eb677888ba1aba54e5c9f4f630)) +- 修复 setup 的逻辑 ([1cfb15a](https://github.com/fe-lce/lowcode-engine/commit/1cfb15aebea9796af23b2135f2aa4409d81283d7)) +- 修正一些对内的地址 ([07cc1f2](https://github.com/fe-lce/lowcode-engine/commit/07cc1f2954530c64a1a3d260e8d532c9e19892e8)) +- 增加必要的方法 ([1b38a81](https://github.com/fe-lce/lowcode-engine/commit/1b38a812653656aa02100a3b1b2a581188d1b3ef)) +- fix tsconfig of material-parser ([46725cb](https://github.com/fe-lce/lowcode-engine/commit/46725cb9f3166912c8f5b42f1e0b1177158c1ee3)) +- lint&fix auto generated types.ts ([7dde970](https://github.com/fe-lce/lowcode-engine/commit/7dde9701c7960b29523abddf32421cdbac47016d)) +- The outline tree does not display the loop flag when the loop is an empty array ([191e284](https://github.com/fe-lce/lowcode-engine/commit/191e284f2fa190c2b3aecb4df31849b2bdc99d38)) + +### [1.0.1](https://github.com/fe-lce/lowcode-engine/compare/@felce/lowcode-code-generator@1.0.0...@felce/lowcode-code-generator@1.0.1) (2022-03-08) + +### Features + +- 在 skeleton 增加几个方法和事件 ([a7d436a](https://github.com/fe-lce/lowcode-engine/commit/a7d436a0525a0ce0c7229710077111f283b452f4)) +- modify npm private control & version ([ee55d02](https://github.com/fe-lce/lowcode-engine/commit/ee55d024a7f964ccf35a0efabec817364cea8041)) +- modify yuque link in README ([d522034](https://github.com/fe-lce/lowcode-engine/commit/d522034879d20a7b5ed12f8fe02a30662a2ea7c6)) +- remove CHANGELOG.md ([b996414](https://github.com/fe-lce/lowcode-engine/commit/b996414c436b5d2439c8368eb4e001cdbcd02892)) +- remove module field in material-parser package.json ([6141c27](https://github.com/fe-lce/lowcode-engine/commit/6141c273c9c32eea22b5374679fe625e6ea15394)) +- rename build:umd ([23c7959](https://github.com/fe-lce/lowcode-engine/commit/23c795931e1d5cf43e9c21cd902441c69c1ecc63)) +- replace tnpm with npm ([36caf0f](https://github.com/fe-lce/lowcode-engine/commit/36caf0f18980c16f7ebb82ac845ad6b33e033567)) +- support UMD packageing for react-renderer ([982d0d6](https://github.com/fe-lce/lowcode-engine/commit/982d0d676b3dfbfc10a2190c0040126d6925ed37)) + +### Bug Fixes + +- 🐛 修正一些示例地址 ([8d21283](https://github.com/fe-lce/lowcode-engine/commit/8d212832e77a1ec763db668683917705774acd0d)) +- 兼容 setters 为空的情况 ([56b459a](https://github.com/fe-lce/lowcode-engine/commit/56b459a017a8350a911ef20f0166d1e62b6390e4)) +- 修复 setup 的逻辑 ([1cfb15a](https://github.com/fe-lce/lowcode-engine/commit/1cfb15aebea9796af23b2135f2aa4409d81283d7)) +- 修正一些对内的地址 ([07cc1f2](https://github.com/fe-lce/lowcode-engine/commit/07cc1f2954530c64a1a3d260e8d532c9e19892e8)) +- 增加必要的方法 ([1b38a81](https://github.com/fe-lce/lowcode-engine/commit/1b38a812653656aa02100a3b1b2a581188d1b3ef)) +- fix tsconfig of material-parser ([46725cb](https://github.com/fe-lce/lowcode-engine/commit/46725cb9f3166912c8f5b42f1e0b1177158c1ee3)) +- lint&fix auto generated types.ts ([7dde970](https://github.com/fe-lce/lowcode-engine/commit/7dde9701c7960b29523abddf32421cdbac47016d)) +- The outline tree does not display the loop flag when the loop is an empty array ([191e284](https://github.com/fe-lce/lowcode-engine/commit/191e284f2fa190c2b3aecb4df31849b2bdc99d38)) + +## 1.0.0 (2022-02-17) + +### Features + +- first commit - genesis ([4f4ac51](https://github.com/fe-lce/lowcode-engine/commit/4f4ac5115d18357a7399632860808f6cffc33fad)) diff --git a/modules/code-generator/CONTRIBUTING.md b/modules/code-generator/CONTRIBUTING.md new file mode 100644 index 0000000..5950d40 --- /dev/null +++ b/modules/code-generator/CONTRIBUTING.md @@ -0,0 +1,40 @@ +# 如何共建 + +1. 拉取最新代码,切换到 develop 分支,基于 develop 分支切出一个 feature 或 hotfix 分支 +2. 到 `lowcode-engine` 项目根目录下,执行 `lerna bootstrap && lerna run build --scope "@felce/lowcode-types"` 来安装依赖并构建 +3. 到 `lowcode-engine/modules/code-generator`下,安装依赖(`npm i`),然后先跑一遍 `npm test` 看看是否所有用例都能通过 (如果网络条件不太好,建议使用 [cnpm - 淘宝提供的中国 NPM 镜像](https://npmmirror.com/)) +4. 在 tests 目录下编写您的需求/问题的测试用例 +5. 修改 src 下的一些代码,然后运行 `npm test` 或 `npm start` 启动 jest 进行调测 +6. 确保所有的测试用例都能通过时,提 MR 给 @牧毅 -- MR 将在 1 个工作日内给您回复意见。 + +当然,欢迎提前私聊沟通 @牧毅,或加入 低代码渲染/出码服务金牌用户群 讨论沟通。 + +# FAQ + +## 如何查看单测覆盖率? + +执行 `npm test:cov` 命令,这样会自动生成单测覆盖率的报告到 `coverage` 目录下。 + +## 如何只执行一个测试用例? + +```sh +npm test -t 'demo2-utils-name-alias' +``` + +## 更新特定测试用例的 expected: + +```sh +npm test:update-snapshots -t 'demo2-utils-name-alias' +``` + +## 如何只执行某个测试用例文件? + +执行 `npx jest 测试用例的文件路径` 即可,如: + +```sh +npx jest tests/plugins/common/requireUtils.test.ts +``` + +## 如何调试某个测试用例? + +建议需要打断点的地方通过 VSCode 打上断点,然后打开 VSCode 的 JavaScript Debug Terminal,在其中执行 `npx jest tests/path/to/your/test/file.ts` 或 `npx jest -t your-test-case-title` 来执行你的测试用例 -- 这样执行到打了断点的语句时会自动断住,以便调试。 diff --git a/modules/code-generator/README.md b/modules/code-generator/README.md new file mode 100644 index 0000000..cf61fba --- /dev/null +++ b/modules/code-generator/README.md @@ -0,0 +1,123 @@ +# 出码 + +所谓出码,即将低代码编排出的 schema 进行解析并转换成最终可执行的代码的过程。本模块提供有 Icejs 和 Rax 两套框架的出码方案,并提供了强大而灵活的扩展机制。 + +## 使用方法 + +### 1) 通过命令行快速体验 + +欢迎使用命令行工具快速体验:`npx @felce/lowcode-code-generator -i example-schema.json -o generated -s icejs` + +--其中 example-schema.json 可以从[这里下载](https://unpkg.com/@felce/lowcode-code-generator@beta/example-schema.json) + +### 2) 通过设计器插件快速体验 + +1. 安装依赖: `npm install --save @alilc/lowcode-plugin-code-generator` +2. 注册插件: + +```ts +import { plugins } from '@felce/lowcode-engine'; +import CodeGenPlugin from '@alilc/lowcode-plugin-code-generator'; + +// 在你的初始化函数中: +await plugins.register(CodeGenPlugin); + +// 如果您不希望自动加上出码按钮,则可以这样注册 +await plugins.register(CodeGenPlugin, { disableCodeGenActionBtn: true }); +``` + +然后运行你的低代码编辑器项目即可 -- 在设计器的右上角会出现一个“出码”按钮,点击即可在浏览器中出码并预览。 + +### 3)服务端出码接入 + +此代码生成器一开始就是为服务端出码设计的,你可以直接这样来在 node.js 环境中使用: + +1. 安装依赖: `npm install --save @felce/lowcode-code-generator` +2. 引入代码生成器: + +```js +import CodeGenerator from '@felce/lowcode-code-generator'; +``` + +3. 创建项目构建器: + +```js +const projectBuilder = CodeGenerator.solutions.icejs(); +``` + +4. 生成代码 + +```js +const project = await projectBuilder.generateProject( + schema, // 编排搭建出来的 schema +); +``` + +5. 将生成的代码写入到磁盘中(也可以生成一个 zip 包) + +```js +// 写入磁盘 +await CodeGenerator.publishers.disk().publish({ + project, // 上一步生成的 project + outputPath: '/path/to/your/output/dir', // 输出目录 + projectSlug: 'your-project-slug', // 项目标识 +}); + +// 写入到 zip 包 +await CodeGenerator.publishers.zip().publish({ + project, // 上一步生成的 project + outputPath: '/path/to/your/output/dir', // 输出目录 + projectSlug: 'your-project-slug', // 项目标识 -- 对应生成 your-project-slug.zip 文件 +}); +``` + +注:一般来说在服务端出码可以跟 github/gitlab, CI 和 CD 流程等一起串起来使用,通常用于优化性能。 + +### 4)浏览器中出码接入 + +随着现在电脑性能和浏览器技术的发展,出码其实已经不必非得在服务端做了,借助于 Web Worker 特性,可以在浏览器中进行出码: + +1. 安装依赖: `npm install --save @felce/lowcode-code-generator` +2. 引入代码生成器: + +```js +import * as CodeGenerator from '@felce/lowcode-code-generator/standalone-loader'; +``` + +3. 【可选】提前初始化代码生成器: + +```js +// 提前初始化下,这样后面用的时候更快(这个 init 内部会提前准备好创建 worker 的一些资源) +await CodeGenerator.init(); +``` + +4. 出码 + +```js +const project = await CodeGenerator.generateCode({ + solution: 'icejs', // 出码方案 (目前内置有 icejs 和 rax ) + schema, // 编排搭建出来的 schema +}); + +console.log(project); // 出码结果(默认是递归结构描述的,可以传 flattenResult: true 以生成扁平结构的结果) +``` + +注:一般来说在浏览器中出码适合做即时预览功能。 + +5. 下载 zip 包 + +```js +// 写入到 zip 包 +await CodeGenerator.publishers.zip().publish({ + project, // 上一步生成的 project + projectSlug: 'your-project-slug', // 项目标识 -- 对应下载 your-project-slug.zip 文件 +}); +``` + +### 5)自定义出码 + +前端框架灵活多变,默认内置的出码方案很难满足所有人的需求,好在此代码生成器支持非常灵活的插件机制 -- 欢迎参考 ./src/plugins/xxx 来编写您自己的出码插件,然后参考 ./src/solutions/xxx 将各种插件组合成一套适合您的业务场景的出码方案。 + +## 参与共建 + +欢迎参与共建,如何共建请参阅:[./CONTRIBUTING.md](https://github.com/fe-lce/lowcode-engine/blob/main/modules/code-generator/CONTRIBUTING.md) diff --git a/modules/code-generator/babel.config.js b/modules/code-generator/babel.config.js new file mode 100644 index 0000000..c5986f2 --- /dev/null +++ b/modules/code-generator/babel.config.js @@ -0,0 +1 @@ +module.exports = require('../../babel.config'); \ No newline at end of file diff --git a/modules/code-generator/bin/lowcode-code-generator.js b/modules/code-generator/bin/lowcode-code-generator.js new file mode 100644 index 0000000..79c36c4 --- /dev/null +++ b/modules/code-generator/bin/lowcode-code-generator.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node +/* eslint-disable no-var */ +/* eslint-disable prefer-arrow-callback */ +/* eslint-disable @typescript-eslint/no-require-imports */ + +var program = require('commander'); + +program + .command('generate', { isDefault: true }) + .description('Generate code from ali lowcode schema') + .requiredOption('-s, --solution ', 'specify the solution to use (icejs/rax/recore)') + .option('-i, --input ', 'specify the input schema file') + .option('-o, --output ', 'specify the output directory', 'generated') + .option('-c, --cwd ', 'specify the working directory', '.') + .option('-q, --quiet', 'be quiet, do not output anything unless get error', false) + .option('-v, --verbose', 'be verbose, output more information', false) + .option('--solution-options ', 'specify the solution options', '{}') + .arguments('[input-schema] ali lowcode schema JSON file') + .action(function doGenerate(inputSchema, command) { + var options = command.opts(); + if (options.cwd) { + process.chdir(options.cwd); + } + + require('../dist/cli') + .run(inputSchema ? [inputSchema] : [], options) + .then((retCode) => { + process.exit(retCode); + }); + }); + +program + .command('init-solution') + .option('-c, --cwd ', 'specify the working directory', '.') + .option('-q, --quiet', 'be quiet, do not output anything unless get error', false) + .option('-v, --verbose', 'be verbose, output more information', false) + .arguments('') + .action(function initSolution(solutionName, command) { + var options = command.opts(); + if (options.cwd) { + process.chdir(options.cwd); + } + + require('../dist/cli') + .initSolution([solutionName], options) + .then((retCode) => { + process.exit(retCode); + }); + }); + +program.parse(process.argv); + diff --git a/modules/code-generator/example-schema.json b/modules/code-generator/example-schema.json new file mode 100644 index 0000000..5e31b1b --- /dev/null +++ b/modules/code-generator/example-schema.json @@ -0,0 +1,276 @@ +{ + "version": "1.0.0", + "componentsMap": [ + { + "componentName": "Button", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Button" + }, + { + "componentName": "Button.Group", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Button", + "subName": "Group" + }, + { + "componentName": "Input", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Input" + }, + { + "componentName": "Form", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Form" + }, + { + "componentName": "Form.Item", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Form", + "subName": "Item" + }, + { + "componentName": "NumberPicker", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "NumberPicker" + }, + { + "componentName": "Select", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Select" + } + ], + "componentsTree": [ + { + "componentName": "Page", + "id": "node$1", + "meta": { + "title": "测试", + "router": "/" + }, + "props": { + "ref": "outerView", + "autoLoading": true + }, + "fileName": "test", + "state": { + "text": "outer" + }, + "lifeCycles": { + "componentDidMount": { + "type": "JSFunction", + "value": "function componentDidMount() { console.log('componentDidMount'); }" + } + }, + "dataSource": { + "list": [ + { + "id": "urlParams", + "type": "urlParams" + }, + + { + "id": "user", + "type": "fetch", + "options": { + "method": "GET", + "uri": "https://shs.xxx.com/mock/1458/demo/user", + "isSync": true + }, + "dataHandler": { + "type": "JSFunction", + "value": "function (response) {\nif (!response.data.success){\n throw new Error(response.data.message);\n }\n return response.data.data;\n}" + } + }, + + { + "id": "orders", + "type": "fetch", + "options": { + "method": "GET", + "uri": "https://shs.xxx.com/mock/1458/demo/orders", + "isSync": true + }, + "dataHandler": { + "type": "JSFunction", + "value": "function (response) {\nif (!response.data.success){\n throw new Error(response.data.message);\n }\n return response.data.data.result;\n}" + } + } + ], + "dataHandler": { + "type": "JSFunction", + "value": "function (dataMap) {\n console.info(\"All datasources loaded:\", dataMap);\n}" + } + }, + "children": [ + { + "componentName": "Form", + "id": "node$2", + "props": { + "labelCol": { + "type": "JSExpression", + "value": "this.state.colNum" + }, + "style": {}, + "ref": "testForm" + }, + "children": [ + { + "componentName": "Form.Item", + "id": "node$3", + "props": { + "label": "姓名:", + "name": "name", + "initValue": "李雷" + }, + "children": [ + { + "componentName": "Input", + "id": "node$4", + "props": { + "placeholder": "请输入", + "size": "medium", + "style": { + "width": 320 + } + } + } + ] + }, + { + "componentName": "Form.Item", + "id": "node$5", + "props": { + "label": "年龄:", + "name": "age", + "initValue": "22" + }, + "children": [ + { + "componentName": "NumberPicker", + "id": "node$6", + "props": { + "size": "medium", + "type": "normal" + } + } + ] + }, + { + "componentName": "Form.Item", + "id": "node$7", + "props": { + "label": "职业:", + "name": "profession" + }, + "children": [ + { + "componentName": "Select", + "id": "node$8", + "props": { + "dataSource": [ + { + "label": "教师", + "value": "t" + }, + { + "label": "医生", + "value": "d" + }, + { + "label": "歌手", + "value": "s" + } + ] + } + } + ] + }, + { + "componentName": "Div", + "id": "node$9", + "props": { + "style": { + "textAlign": "center" + } + }, + "children": [ + { + "componentName": "Button.Group", + "id": "node$a", + "props": {}, + "children": [ + { + "componentName": "Button", + "id": "node$b", + "condition": { + "type": "JSExpression", + "value": "this.index >= 1" + }, + "loop": ["a", "b", "c"], + "props": { + "type": "primary", + "style": { + "margin": "0 5px 0 5px" + } + }, + "children": [ + { + "type": "JSExpression", + "value": "this.item" + } + ] + } + ] + } + ] + } + ] + } + ] + } + ], + "constants": { + "ENV": "prod", + "DOMAIN": "xxx.xxx.com" + }, + "css": "body {font-size: 12px;} .table { width: 100px;}", + "config": { + "sdkVersion": "1.0.3", + "historyMode": "hash", + "targetRootID": "J_Container", + "layout": { + "componentName": "BasicLayout", + "props": { + "logo": "...", + "name": "测试网站" + } + }, + "theme": { + "package": "@alife/theme-fusion", + "version": "^0.1.0", + "primary": "#ff9966" + } + }, + "meta": { + "name": "demo应用", + "git_group": "appGroup", + "project_name": "app_demo", + "description": "这是一个测试应用", + "spma": "spa23d", + "creator": "Test" + } +} diff --git a/modules/code-generator/example-schema.json5 b/modules/code-generator/example-schema.json5 new file mode 100644 index 0000000..4ab0299 --- /dev/null +++ b/modules/code-generator/example-schema.json5 @@ -0,0 +1,276 @@ +{ + version: '1.0.0', + componentsMap: [ + { + componentName: 'Button', + package: '@alifd/next', + version: '1.19.18', + destructuring: true, + exportName: 'Button', + }, + { + componentName: 'Button.Group', + package: '@alifd/next', + version: '1.19.18', + destructuring: true, + exportName: 'Button', + subName: 'Group', + }, + { + componentName: 'Input', + package: '@alifd/next', + version: '1.19.18', + destructuring: true, + exportName: 'Input', + }, + { + componentName: 'Form', + package: '@alifd/next', + version: '1.19.18', + destructuring: true, + exportName: 'Form', + }, + { + componentName: 'Form.Item', + package: '@alifd/next', + version: '1.19.18', + destructuring: true, + exportName: 'Form', + subName: 'Item', + }, + { + componentName: 'NumberPicker', + package: '@alifd/next', + version: '1.19.18', + destructuring: true, + exportName: 'NumberPicker', + }, + { + componentName: 'Select', + package: '@alifd/next', + version: '1.19.18', + destructuring: true, + exportName: 'Select', + }, + ], + componentsTree: [ + { + componentName: 'Page', + id: 'node$1', + meta: { + title: '测试', + router: '/', + }, + props: { + ref: 'outerView', + autoLoading: true, + }, + fileName: 'test', + state: { + text: 'outer', + }, + lifeCycles: { + componentDidMount: { + type: 'JSFunction', + value: "function componentDidMount() { console.log('componentDidMount'); }", + }, + }, + dataSource: { + list: [ + { + id: 'urlParams', + type: 'urlParams', + }, + + { + id: 'user', + type: 'fetch', + options: { + method: 'GET', + uri: 'https://shs.xxx.com/mock/1458/demo/user', + isSync: true, + }, + dataHandler: { + type: 'JSFunction', + value: 'function (response) {\nif (!response.data.success){\n throw new Error(response.data.message);\n }\n return response.data.data;\n}', + }, + }, + + { + id: 'orders', + type: 'fetch', + options: { + method: 'GET', + uri: 'https://shs.xxx.com/mock/1458/demo/orders', + isSync: true, + }, + dataHandler: { + type: 'JSFunction', + value: 'function (response) {\nif (!response.data.success){\n throw new Error(response.data.message);\n }\n return response.data.data.result;\n}', + }, + }, + ], + dataHandler: { + type: 'JSFunction', + value: 'function (dataMap) {\n console.info("All datasources loaded:", dataMap);\n}', + }, + }, + children: [ + { + componentName: 'Form', + id: 'node$2', + props: { + labelCol: { + type: 'JSExpression', + value: 'this.state.colNum', + }, + style: {}, + ref: 'testForm', + }, + children: [ + { + componentName: 'Form.Item', + id: 'node$3', + props: { + label: '姓名:', + name: 'name', + initValue: '李雷', + }, + children: [ + { + componentName: 'Input', + id: 'node$4', + props: { + placeholder: '请输入', + size: 'medium', + style: { + width: 320, + }, + }, + }, + ], + }, + { + componentName: 'Form.Item', + id: 'node$5', + props: { + label: '年龄:', + name: 'age', + initValue: '22', + }, + children: [ + { + componentName: 'NumberPicker', + id: 'node$6', + props: { + size: 'medium', + type: 'normal', + }, + }, + ], + }, + { + componentName: 'Form.Item', + id: 'node$7', + props: { + label: '职业:', + name: 'profession', + }, + children: [ + { + componentName: 'Select', + id: 'node$8', + props: { + dataSource: [ + { + label: '教师', + value: 't', + }, + { + label: '医生', + value: 'd', + }, + { + label: '歌手', + value: 's', + }, + ], + }, + }, + ], + }, + { + componentName: 'Div', + id: 'node$9', + props: { + style: { + textAlign: 'center', + }, + }, + children: [ + { + componentName: 'Button.Group', + id: 'node$a', + props: {}, + children: [ + { + componentName: 'Button', + id: 'node$b', + condition: { + type: 'JSExpression', + value: 'this.index >= 1', + }, + loop: ['a', 'b', 'c'], + props: { + type: 'primary', + style: { + margin: '0 5px 0 5px', + }, + }, + children: [ + { + type: 'JSExpression', + value: 'this.item', + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + constants: { + ENV: 'prod', + DOMAIN: 'xxx.xxx.com', + }, + css: 'body {font-size: 12px;} .table { width: 100px;}', + config: { + sdkVersion: '1.0.3', + historyMode: 'hash', + targetRootID: 'J_Container', + layout: { + componentName: 'BasicLayout', + props: { + logo: '...', + name: '测试网站', + }, + }, + theme: { + package: '@alife/theme-fusion', + version: '^0.1.0', + primary: '#ff9966', + }, + }, + meta: { + name: 'demo应用', + git_group: 'appGroup', + project_name: 'app_demo', + description: '这是一个测试应用', + spma: 'spa23d', + creator: 'Test', + }, +} diff --git a/modules/code-generator/jest.config.js b/modules/code-generator/jest.config.js new file mode 100644 index 0000000..0f90814 --- /dev/null +++ b/modules/code-generator/jest.config.js @@ -0,0 +1,10 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + transformIgnorePatterns: ['/node_modules/(?!core-js)/'], + moduleFileExtensions: ['ts', 'tsx', 'js', 'json'], + collectCoverage: false, + collectCoverageFrom: ['src/**/*.{ts,tsx}', '!**/node_modules/**', '!**/vendor/**'], + testMatch: ['/tests/**/*.test.ts'], + setupFiles: ['./jest.setup.js'], +}; diff --git a/modules/code-generator/jest.setup.js b/modules/code-generator/jest.setup.js new file mode 100644 index 0000000..67da561 --- /dev/null +++ b/modules/code-generator/jest.setup.js @@ -0,0 +1,12 @@ +// 对于 standalone 模式的专门 polyfills +if (process.env.TEST_TARGET === 'standalone') { + // 模拟浏览器环境 + global.window = global; + global.self = global; + + // 将所有测试用例里面的 './src' 都替换为 './dist/standalone' + jest.mock('./src', () => require('./dist/standalone')); +} + +// 如果在调试模式下,则不限制超时时间 +jest.setTimeout(typeof v8debug === 'object' ? Infinity : 30 * 1000); diff --git a/modules/code-generator/package.json b/modules/code-generator/package.json new file mode 100644 index 0000000..48f7c42 --- /dev/null +++ b/modules/code-generator/package.json @@ -0,0 +1,155 @@ +{ + "name": "@felce/lowcode-code-generator", + "version": "1.1.7", + "description": "出码引擎 for LowCode Engine", + "license": "MIT", + "main": "lib/index.js", + "module": "es/index.js", + "typings": "types/index.d.ts", + "files": [ + "bin", + "lib", + "es", + "demo", + "dist", + "types", + "standalone", + "standalone-worker", + "standalone-loader", + "loader", + "CHANGELOG.md", + "README.md", + "CONTRIBUTING.md", + "example-schema.json", + "example-schema.json5" + ], + "bin": { + "lowcode-code-generator": "bin/lowcode-code-generator.js" + }, + "scripts": { + "start": "jest --watchAll", + "build": "npm run clean && node scripts/build", + "build:standalone": "node scripts/build-standalone", + "clean": "rimraf es lib dist types generated demo coverage output test-cases/*/*/actual", + "lint": "eslint --ext .jsx,.js,.ts,.tsx src/", + "lintfix": "eslint --ext .jsx,.js,.ts,.tsx --fix src/", + "check:types": "tsc --noEmit", + "template": "node ./scripts/build-template-static-files.js", + "test": "npm run test:normal && npm run test:standalone", + "test:normal": "jest", + "test:standalone": "node scripts/test-standalone", + "test:cov": "jest --coverage", + "test:update-snapshots": "cross-env UPDATE_EXPECTED=true jest -u", + "analyze:standalone": "ANALYZE=true node scripts/build-standalone", + "release:beta": "standard-version -t @felce/lowcode-code-generator\\@ -r patch --prerelease beta && git push --follow-tags && npm publish --tag beta", + "release:patch": "standard-version -t @felce/lowcode-code-generator\\@ -r patch && git push --follow-tags && npm publish", + "release:minor": "standard-version -t @felce/lowcode-code-generator\\@ -r minor && git push --follow-tags && npm publish", + "prepublishOnly": "npm run build", + "demo": "node bin/lowcode-code-generator.js -i example-schema.json -o demo -s icejs" + }, + "standard-version": { + "skip": { + "changelog": true + } + }, + "husky": { + "hooks": { + "pre-commit": "lint-staged", + "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" + } + }, + "lint-staged": { + "**/*.{js,jsx,ts,tsx}": "eslint" + }, + "dependencies": { + "@felce/lowcode-types": "^1.0.0", + "@babel/generator": "^7.12.11", + "@babel/parser": "^7.12.11", + "@babel/runtime": "^7.12.5", + "@babel/traverse": "^7.12.12", + "@babel/types": "^7.12.12", + "@types/debug": "^4.1.7", + "@types/fs-extra": "^9.0.12", + "@types/glob": "^7.2.0", + "@types/lodash": "^4.14.162", + "@types/node-fetch": "2.x", + "@types/qs": "^6.9.6", + "@types/semver": "^7.3.4", + "buffer": "^6.0.3", + "chalk": "^4.1.0", + "change-case": "^3.1.0", + "commander": "^6.1.0", + "debug": "^4.3.2", + "file-saver": "^2.0.5", + "fp-ts": "^2.11.9", + "fs-extra": "9.x", + "glob": "^7.2.0", + "html-entities": "^2.3.2", + "json5": "^2.2.0", + "jsonc": "^2.0.0", + "jszip": "^3.5.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "mock-fs": "^5.1.2", + "moment": "^2.29.1", + "nanomatch": "^1.2.13", + "node-fetch": "2.x", + "path-browserify": "^1.0.1", + "prettier": "^2.5.1", + "qs": "^6.10.1", + "semver": "^7.3.4", + "short-uuid": "^3.1.1", + "babel-jest": "^26.5.2", + "tslib": "^2.3.1" + }, + "browser": { + "path": "path-browserify", + "lodash": "lodash-es", + "prettier": "prettier/standalone" + }, + "devDependencies": { + "@iceworks/spec": "^1.4.2", + "@types/babel__traverse": "^7.11.0", + "@types/file-saver": "^2.0.7", + "@types/jest": "^27.0.2", + "@types/lodash": "^4.14.162", + "@types/node": "^14.14.20", + "@types/prettier": "^2.4.2", + "@typescript-eslint/eslint-plugin": "^4.12.0", + "@typescript-eslint/parser": "^4.12.0", + "concurrently": "^6.5.1", + "cross-env": "^7.0.3", + "esbuild": "^0.14.5", + "esbuild-plugin-alias": "^0.2.1", + "esbuild-plugin-ignore": "^1.1.0", + "esbuild-visualizer": "^0.3.1", + "eslint": "^7.17.0", + "eslint-config-ali": "^11.4.1", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-react": "^7.22.0", + "eslint-plugin-react-hooks": "^4.2.0", + "jest": "^26.5.2", + "jest-util": "^27.4.2", + "rimraf": "^3.0.2", + "standard-version": "^9.1.1", + "ts-jest": "^26.5.2", + "ts-loader": "^6.2.2", + "ts-node": "^8.10.2", + "tsconfig-paths": "^3.9.0", + "typescript": "4.x", + "yargs-parser": "^20.2.9" + }, + "engines": { + "node": ">=10.0.0" + }, + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + "repository": { + "type": "http", + "url": "https://github.com/fe-lce/lowcode-engine/tree/main/modules/code-generator" + }, + "bugs": "https://github.com/fe-lce/lowcode-engine/issues", + "homepage": "https://github.com/fe-lce/lowcode-engine/#readme" +} diff --git a/modules/code-generator/scripts/build-cli.js b/modules/code-generator/scripts/build-cli.js new file mode 100644 index 0000000..40fcb73 --- /dev/null +++ b/modules/code-generator/scripts/build-cli.js @@ -0,0 +1,56 @@ +/* eslint-disable no-console */ +/* eslint-disable @typescript-eslint/no-require-imports */ +const esbuild = require('esbuild'); +const ignorePlugin = require('esbuild-plugin-ignore'); + +// 执行脚本 +(async () => { + try { + console.log('building...'); + const result = await esbuild.build({ + entryPoints: ['src/cli/index.ts'], + outfile: 'dist/cli.js', + bundle: true, + platform: 'node', + target: ['node10'], + format: 'cjs', + sourcemap: true, + sourcesContent: true, + plugins: [ + ignorePlugin([ + // @felce/lowcode-types 中误依赖了 react,这里忽略下 + { + resourceRegExp: /^react$/, + contextRegExp: /./, + }, + { + resourceRegExp: /setter-config/, + contextRegExp: /lowcode-types/, + }, + ]), + ], + define: {}, + treeShaking: true, + minify: false, + minifyWhitespace: false, + minifyIdentifiers: false, + minifySyntax: false, + legalComments: 'external', + external: Object.keys(require('../package.json').dependencies), + }); + if (result.errors.length > 0) { + throw result.errors; + } + + if (result.warnings.length > 0) { + result.warnings.forEach((warnings) => { + console.warn(warnings); + }); + } + + console.log('done'); + } catch (e) { + console.error(e); + process.exit(1); + } +})(); diff --git a/modules/code-generator/scripts/build-standalone-loader.js b/modules/code-generator/scripts/build-standalone-loader.js new file mode 100644 index 0000000..bee318d --- /dev/null +++ b/modules/code-generator/scripts/build-standalone-loader.js @@ -0,0 +1,73 @@ +/* eslint-disable no-console */ +/* eslint-disable @typescript-eslint/no-require-imports */ +const esbuild = require('esbuild'); + +const packageVersion = require('../package.json').version; +console.log('build standalone-loader: packageVersion=%s', packageVersion); + +const enableAnalyze = process.env.ANALYZE === 'true'; +const buildConfig = { + entryPoints: ['src/standalone-loader.ts'], + outfile: 'dist/standalone-loader.js', + metafile: enableAnalyze, + bundle: true, + target: ['chrome69'], + format: 'cjs', + sourcemap: true, + sourcesContent: true, + external: Object.keys(require('../package.json').dependencies), + define: { + process: JSON.stringify({ + env: { + NODE_ENV: 'production', + STANDALONE: 'true', + }, + }), + __PACKAGE_VERSION__: JSON.stringify(packageVersion), + }, + minify: false, + minifyWhitespace: false, + minifyIdentifiers: false, + minifySyntax: false, + legalComments: 'external', + treeShaking: true, +}; + +// 执行脚本 +(async () => { + try { + console.log('building cjs...'); + const result = await esbuild.build({ + ...buildConfig, + }); + if (result.errors.length > 0) { + throw result.errors; + } + + if (result.warnings.length > 0) { + result.warnings.forEach((warnings) => { + console.warn(warnings); + }); + } + + const result2 = await esbuild.build({ + ...buildConfig, + outfile: buildConfig.outfile.replace(/\.js$/, '.esm.js'), + format: 'esm', + }); + if (result2.errors.length > 0) { + throw result2.errors; + } + + if (result2.warnings.length > 0) { + result2.warnings.forEach((warnings) => { + console.warn(warnings); + }); + } + + console.log('done'); + } catch (e) { + console.error(e); + process.exit(1); + } +})(); diff --git a/modules/code-generator/scripts/build-standalone-worker.js b/modules/code-generator/scripts/build-standalone-worker.js new file mode 100644 index 0000000..3134566 --- /dev/null +++ b/modules/code-generator/scripts/build-standalone-worker.js @@ -0,0 +1,107 @@ +/* eslint-disable no-console */ +/* eslint-disable @typescript-eslint/no-require-imports */ +const esbuild = require('esbuild'); +const { spawnSync } = require('child_process'); +const ignorePlugin = require('esbuild-plugin-ignore'); +const fs = require('fs'); +const path = require('path'); + +const enableAnalyze = process.env.ANALYZE === 'true'; +const buildConfig = { + entryPoints: ['src/standalone-worker.ts'], + outfile: 'dist/standalone-worker.js', + metafile: enableAnalyze, + bundle: true, + target: ['chrome69'], + format: 'iife', + sourcemap: true, + sourcesContent: true, + plugins: [ + ignorePlugin([ + { + resourceRegExp: /^fs$/, + contextRegExp: /./, + }, + // @felce/lowcode-types 中误依赖了 react,这里忽略下 + { + resourceRegExp: /^react$/, + contextRegExp: /./, + }, + { + resourceRegExp: /setter-config/, + contextRegExp: /lowcode-types|..[\\/]types/, + }, + ]), + ], + define: { + process: JSON.stringify({ + env: { + NODE_ENV: 'production', + STANDALONE: 'true', + }, + }), + }, + treeShaking: true, +}; + +// 执行脚本 +(async () => { + try { + console.log('building...'); + const result = await esbuild.build({ + ...buildConfig, + minify: false, + minifyWhitespace: false, + minifyIdentifiers: false, + minifySyntax: false, + legalComments: 'external', + }); + if (result.errors.length > 0) { + throw result.errors; + } + + if (result.warnings.length > 0) { + result.warnings.forEach((warnings) => { + console.warn(warnings); + }); + } + + if (enableAnalyze) { + const metaFile = buildConfig.outfile.replace(/\.js/, '.meta.json'); + const statsFile = buildConfig.outfile.replace(/\.js/, '.stats.html'); + fs.writeFileSync(metaFile, JSON.stringify(result.metafile || {}), { encoding: 'utf-8' }); + spawnSync('npx', ['esbuild-visualizer', '--metadata', metaFile, '--filename', statsFile], { + shell: true, + stdio: 'inherit', + }); + spawnSync('open', [statsFile], { + shell: true, + stdio: 'inherit', + }); + return; + } + + const outFileContent = fs.readFileSync(buildConfig.outfile, 'utf-8'); + + console.log('minifying...'); + const minifiedOutFile = buildConfig.outfile.replace(/\.js$/, '.min.js'); + const minifiedResult = esbuild.transformSync(outFileContent, { + minify: true, + sourcemap: true, + sourcesContent: true, + sourcefile: path.basename(buildConfig.outfile), + }); + + fs.writeFileSync(minifiedOutFile, minifiedResult.code, { encoding: 'utf-8' }); + fs.writeFileSync(`${minifiedOutFile}.map`, minifiedResult.map, { encoding: 'utf-8' }); + + minifiedResult.warnings.forEach((warnings) => { + console.log(warnings); + }); + + console.log('done'); + } catch (e) { + console.error(e); + process.exit(1); + } +})(); diff --git a/modules/code-generator/scripts/build-standalone.js b/modules/code-generator/scripts/build-standalone.js new file mode 100644 index 0000000..804a775 --- /dev/null +++ b/modules/code-generator/scripts/build-standalone.js @@ -0,0 +1,135 @@ +/* eslint-disable no-console */ +/* eslint-disable @typescript-eslint/no-require-imports */ +const esbuild = require('esbuild'); +const { spawnSync } = require('child_process'); +const ignorePlugin = require('esbuild-plugin-ignore'); +const fs = require('fs'); +const path = require('path'); + +const UMD_GLOBAL_NAME = 'AliLowCodeCodeGenerator'; + +const enableAnalyze = process.env.ANALYZE === 'true'; +const buildConfig = { + entryPoints: ['src/standalone.ts'], + outfile: 'dist/standalone.js', + metafile: enableAnalyze, + bundle: true, + target: ['chrome69'], + format: 'cjs', + sourcemap: true, + sourcesContent: true, + plugins: [ + ignorePlugin([ + { + resourceRegExp: /^fs$/, + contextRegExp: /./, + }, + // @felce/lowcode-types 中误依赖了 react,这里忽略下 + { + resourceRegExp: /^react$/, + contextRegExp: /./, + }, + { + resourceRegExp: /setter-config/, + contextRegExp: /lowcode-types|..[\\/]types/, + }, + ]), + ], + define: { + process: JSON.stringify({ + env: { + NODE_ENV: 'production', + STANDALONE: 'true', + }, + }), + }, + treeShaking: true, +}; + +// 执行脚本 +(async () => { + try { + console.log('building...'); + const result = await esbuild.build({ + ...buildConfig, + minify: false, + minifyWhitespace: false, + minifyIdentifiers: false, + minifySyntax: false, + legalComments: 'external', + }); + if (result.errors.length > 0) { + throw result.errors; + } + + if (result.warnings.length > 0) { + result.warnings.forEach((warnings) => { + console.warn(warnings); + }); + } + + if (enableAnalyze) { + const metaFile = buildConfig.outfile.replace(/\.js/, '.meta.json'); + const statsFile = buildConfig.outfile.replace(/\.js/, '.stats.html'); + fs.writeFileSync(metaFile, JSON.stringify(result.metafile || {}), { encoding: 'utf-8' }); + spawnSync('npx', ['esbuild-visualizer', '--metadata', metaFile, '--filename', statsFile], { + shell: true, + stdio: 'inherit', + }); + spawnSync('open', [statsFile], { + shell: true, + stdio: 'inherit', + }); + return; + } + + const outFileContent = transformCjsToUmdFile(buildConfig.outfile); + + console.log('minifying...'); + const minifiedOutFile = buildConfig.outfile.replace(/\.js$/, '.min.js'); + const minifiedResult = esbuild.transformSync(outFileContent, { + minify: true, + sourcemap: true, + sourcesContent: true, + sourcefile: path.basename(buildConfig.outfile), + }); + + fs.writeFileSync(minifiedOutFile, minifiedResult.code, { encoding: 'utf-8' }); + fs.writeFileSync(`${minifiedOutFile}.map`, minifiedResult.map, { encoding: 'utf-8' }); + + minifiedResult.warnings.forEach((warnings) => { + console.log(warnings); + }); + + console.log('done'); + } catch (e) { + console.error(e); + process.exit(1); + } +})(); + +// esbuild 没有直接提供 UMD 格式,所以这里我们自行包装转换下 +function transformCjsToUmdFile(file) { + const globalName = UMD_GLOBAL_NAME; + const fileContent = fs.readFileSync(file, { encoding: 'utf-8' }); + const transformedFileContent = `(function (global, factory) { + if (typeof exports === 'object' && typeof module !== 'undefined'){ + factory(module, exports); + } else if (typeof define === 'function' && define.amd) { + define(['module', 'exports'], factory); + } else { + global = global || self; + var m = { exports: {} }; + factory(m, m.exports); + global.${globalName} = m.exports; + } +}(this, function (module, exports) { + 'use strict'; + ${fileContent}; + return module.exports; +})); +`; + + fs.writeFileSync(file, transformedFileContent, { encoding: 'utf-8' }); + return transformedFileContent; +} diff --git a/modules/code-generator/scripts/build-template-static-files.js b/modules/code-generator/scripts/build-template-static-files.js new file mode 100644 index 0000000..c802498 --- /dev/null +++ b/modules/code-generator/scripts/build-template-static-files.js @@ -0,0 +1,125 @@ +/* eslint-disable no-console */ +/* eslint-disable @typescript-eslint/quotes */ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +/* eslint-disable @typescript-eslint/no-require-imports */ +// @ts-check +// 这个文件是用来构建模板中的静态文件的 +const fs = require('fs'); +const glob = require('glob'); +const path = require('path'); +const JSON5 = require('json5'); +const { spawnSync } = require('child_process'); + +const PROJECT_ROOT = path.join(__dirname, '..'); + +const TEMPLATES = [ + { + sourceDir: path.join(PROJECT_ROOT, 'static-files/rax'), + outputDir: path.join(PROJECT_ROOT, 'src/plugins/project/framework/rax/template'), + }, +]; + +try { + TEMPLATES.forEach(buildTemplateStaticFiles); + console.log('All done.'); +} catch (e) { + console.error(e); + process.exit(1); +} + +function buildTemplateStaticFiles({ sourceDir, outputDir }) { + console.log('processing %s template...', path.dirname(sourceDir)); + + // 扫描所有的目录 + const sourceFiles = glob.sync('**/*', { + nodir: true, + dot: true, + cwd: sourceDir, + }); + + console.log('got %d files: %o', sourceFiles.length, sourceFiles); + + const staticFiles = { + imports: [], + runs: [], + }; + + // 生成对应的文件 + sourceFiles.forEach((sourceFileName, index) => { + console.log('processing %s', sourceFileName); + const sourceFileContent = fs.readFileSync(path.join(sourceDir, sourceFileName), 'utf-8'); + const sourceFileRealName = sourceFileName.replace(/\.template$/, ''); + const outputFileName = `${sourceFileRealName}.ts`; + const outputFileFullPath = path.join(outputDir, 'files', outputFileName); + + const sourceFileExtName = path.extname(sourceFileRealName); + const sourceFileBaseName = path.basename(sourceFileRealName, sourceFileExtName); + + // 确保目录存在 + fs.mkdirSync(path.dirname(outputFileFullPath), { recursive: true }); + + // 写入文件 + fs.writeFileSync( + outputFileFullPath, + [ + `/* eslint-disable max-len */`, + `/* Note: this file is generated by "npm run template", please dont modify this file directly */`, + `/* -- instead, you should modify "${path.relative( + PROJECT_ROOT, + path.join(sourceDir, sourceFileName), + )}" and run "npm run template" */`, + `import { ResultFile } from '@felce/lowcode-types';`, + '', + `export default function getFile(): [string[], ResultFile] {`, + ` return ${JSON5.stringify([ + // 文件目录: + path.dirname(sourceFileRealName).split(path.sep).filter(Boolean), + // 文件名和内容: + { + name: sourceFileBaseName, + ext: sourceFileExtName.replace(/^\./, ''), + content: sourceFileContent, + }, + ])};`, + `}`, + '', + ].join('\n'), + { + encoding: 'utf-8', + }, + ); + + staticFiles.imports.push(`import file${index} from './files/${sourceFileRealName}';`); + + staticFiles.runs.push(` runFileGenerator(root, file${index})`); + }); + + console.log('generating static-files.ts...'); + fs.writeFileSync( + path.join(outputDir, 'static-files.ts'), + [ + `/* Note: this file is generated by "npm run template", please dont modify this file directly */`, + `import { ResultDir } from '@felce/lowcode-types'; + + import { createResultDir } from '../../../../../utils/resultHelper'; + import { runFileGenerator } from '../../../../../utils/templateHelper';`, + ...staticFiles.imports, + '', + `export function generateStaticFiles(root = createResultDir('.')): ResultDir {`, + ...staticFiles.runs, + ` return root;`, + `}`, + '', + ].join('\n'), + { encoding: 'utf-8' }, + ); + + // prettier 一把 + console.log('run prettier...'); + spawnSync('npx', ['prettier', '--write', `${outputDir}`], { + stdio: 'inherit', + shell: true, + }); + + console.log('done %s', path.basename(sourceDir)); +} diff --git a/modules/code-generator/scripts/build-types b/modules/code-generator/scripts/build-types new file mode 100644 index 0000000..6141406 --- /dev/null +++ b/modules/code-generator/scripts/build-types @@ -0,0 +1,10 @@ +#!/bin/sh + +echo building types... +tsc --outDir types --declaration --emitDeclarationOnly && \ + echo built types... && \ + rm -rf types/packages && \ + mv types/modules/code-generator/src/* types/ && \ + rm -rf types/modules + + diff --git a/modules/code-generator/scripts/build.js b/modules/code-generator/scripts/build.js new file mode 100644 index 0000000..841eaca --- /dev/null +++ b/modules/code-generator/scripts/build.js @@ -0,0 +1,75 @@ +/* eslint-disable no-console */ +/* eslint-disable @typescript-eslint/no-require-imports */ +const _ = require('lodash'); +const esbuild = require('esbuild'); +const concurrently = require('concurrently'); +const argv = require('yargs-parser')(process.argv.slice(2)); +const packageJson = require('../package.json'); + +if (!argv.format) { + buildAll(); +} else { + buildFormat(argv.format, argv.out || 'dist'); +} + +function buildAll() { + concurrently( + [ + { name: 'build:types', command: 'sh scripts/build-types' }, + { name: 'build:cjs', command: 'node scripts/build --format=cjs --out=lib' }, + { name: 'build:esm', command: 'node scripts/build --format=esm --out=es' }, + { name: 'build:standalone', command: 'node scripts/build-standalone' }, + { name: 'build:standalone-worker', command: 'node scripts/build-standalone-worker' }, + { name: 'build:standalone-loader', command: 'node scripts/build-standalone-loader' }, + { name: 'build:cli', command: 'node scripts/build-cli' }, + ], + { + prefix: 'name', + killOthers: ['failure'], + restartTries: 0, + }, + ).then( + () => { + console.log('all done.'); + }, + () => { + process.exit(1); + }, + ); +} + +function buildFormat(format, outDir) { + try { + console.log('building %s...', format); + const startTime = Date.now(); + const result = esbuild.buildSync({ + entryPoints: ['src/index.ts'], + outfile: `${outDir}/index.js`, + bundle: true, + platform: 'node', + target: ['node10'], + format, + sourcemap: true, + sourcesContent: true, + define: {}, + treeShaking: true, + external: _.keys(packageJson.dependencies), + minify: false, + legalComments: 'external', + }); + if (result.errors.length > 0) { + throw result.errors; + } + + if (result.warnings.length > 0) { + result.warnings.forEach((warnings) => { + console.warn(warnings); + }); + } + + console.log('built %s in %ds', format, ((Date.now() - startTime) / 1000).toFixed(2)); + } catch (e) { + console.error(e); + process.exit(1); + } +} diff --git a/modules/code-generator/scripts/move-files-to-build-dest.js b/modules/code-generator/scripts/move-files-to-build-dest.js new file mode 100644 index 0000000..736df99 --- /dev/null +++ b/modules/code-generator/scripts/move-files-to-build-dest.js @@ -0,0 +1,24 @@ +/* eslint-disable @typescript-eslint/no-require-imports */ +const fs = require('fs'); +const { spawnSync } = require('child_process'); + +const BUILD_DEST = process.env.BUILD_DEST || '.package'; + +fs.mkdirSync(BUILD_DEST, { recursive: true }); + +const distFiles = [...require('../package.json').files, 'package.json']; + +distFiles.forEach((file) => { + console.log('mv %s', file); + if (file === BUILD_DEST) { + fs.mkdirSync(`${BUILD_DEST}/${file}`, { recursive: true }); + spawnSync('mv', [`${file}/*`, `${BUILD_DEST}/${file}/`], { shell: true, stdio: 'inherit' }); + } +}); + +distFiles.forEach((file) => { + console.log('mv %s', file); + if (file !== BUILD_DEST) { + spawnSync('mv', [file, `${BUILD_DEST}/${file}`], { shell: true, stdio: 'inherit' }); + } +}); diff --git a/modules/code-generator/scripts/run-demo-project b/modules/code-generator/scripts/run-demo-project new file mode 100644 index 0000000..1ad7dce --- /dev/null +++ b/modules/code-generator/scripts/run-demo-project @@ -0,0 +1,55 @@ +#!/usr/bin/env node + +// @ts-check +const program = require('commander'); +const { spawnSync } = require('child_process'); +const glob = require('glob'); +const fs = require('fs'); +const path = require('path'); +const _ = require('lodash'); + +program + .option('--npm ', 'specify the npm command location or alias') + .arguments('') + .action((project, options) => { + try { + if (!fs.existsSync(project)) { + throw new Error(`Project ${project} does not exist`); + } + + const getProjectActualPath = [ + () => path.resolve(process.cwd(), project), + () => + path.resolve( + process.cwd(), + path.join( + project, + path.dirname(glob.sync('*/package.json', { cwd: project })[0] || ''), + ), + ), + ] + .map((x) => _.memoize(x)) + .find((x) => fs.existsSync(path.join(x(), 'package.json'))); + + if (!getProjectActualPath) { + throw new Error(`Project ${project} is not a valid project(no package.json)`); + } + + const projectActualPath = getProjectActualPath(); + if (path.resolve(process.cwd(), project) !== projectActualPath) { + console.log('Changing directory to', path.relative(process.cwd(), projectActualPath)); + } + + process.chdir(projectActualPath); + + const npm = options.npm || 'npm'; + const cmd = `${npm} install && ${npm} start`; + console.log('# %s', cmd); + spawnSync(cmd, { stdio: 'inherit', shell: true }); + } catch (err) { + console.log(err); + process.exit(1); + } + }); + +program.parse(process.argv); diff --git a/modules/code-generator/scripts/test-standalone.js b/modules/code-generator/scripts/test-standalone.js new file mode 100644 index 0000000..55d876d --- /dev/null +++ b/modules/code-generator/scripts/test-standalone.js @@ -0,0 +1,17 @@ +// 测试 standalone 模式的基本功能 +// 注1:指定文件测试就直接在后面加文件: node scripts/test-standalone.js tests/public/rax-app.test.ts +// 注2:指定测试用例就直接在后面加`-t xxx`: node scripts/test-standalone.js tests/public/rax-app.test.ts -t demo01 +const { spawnSync } = require('child_process'); + +// 一定要先构建 +spawnSync('npm', ['run', 'build:standalone'], { shell: true, stdio: 'inherit' }); + +// 然后只执行特定的一些测试用例 +spawnSync('npx', ['jest', ...process.argv.slice(2)], { + env: { + ...process.env, + TEST_TARGET: 'standalone', + }, + shell: true, + stdio: 'inherit', +}); diff --git a/modules/code-generator/src/analyzer/componentAnalyzer.ts b/modules/code-generator/src/analyzer/componentAnalyzer.ts new file mode 100644 index 0000000..8a504ae --- /dev/null +++ b/modules/code-generator/src/analyzer/componentAnalyzer.ts @@ -0,0 +1,35 @@ +import type { IPublicTypeNodeSchema, IPublicTypeCompositeObject } from '@felce/lowcode-types'; +import type { TComponentAnalyzer } from '../types'; + +import { handleSubNodes } from '../utils/schema'; + +export const componentAnalyzer: TComponentAnalyzer = (container) => { + let hasRefAttr = false; + const nodeValidator = (n: IPublicTypeNodeSchema) => { + if (n.props) { + const props = n.props as IPublicTypeCompositeObject; + if (props.ref) { + hasRefAttr = true; + } + } + }; + + nodeValidator(container); + + if (!hasRefAttr && container.children) { + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + handleSubNodes( + container.children, + { + node: nodeValidator, + }, + { + rerun: true, + }, + ); + } + + return { + isUsingRef: hasRefAttr, + }; +}; diff --git a/modules/code-generator/src/cli/index.ts b/modules/code-generator/src/cli/index.ts new file mode 100644 index 0000000..fcbbc8a --- /dev/null +++ b/modules/code-generator/src/cli/index.ts @@ -0,0 +1,2 @@ +export * from './run'; +export * from './init-solution'; diff --git a/modules/code-generator/src/cli/init-solution.ts b/modules/code-generator/src/cli/init-solution.ts new file mode 100644 index 0000000..63ee66e --- /dev/null +++ b/modules/code-generator/src/cli/init-solution.ts @@ -0,0 +1,65 @@ +/* eslint-disable no-console */ +import * as fs from 'fs-extra'; +import * as path from 'path'; +import chalk from 'chalk'; +import * as changeCase from 'change-case'; +import { getErrorMessage } from '../utils/errors'; +import { getLowcodeSolutionTemplateFiles } from './solutions/example-solution'; + + +export async function initSolution(args: string[], options: { + quiet?: boolean; + verbose?: boolean; +}) { + try { + const cwd = process.cwd(); + let solutionName = args[0] || 'hello'; + let solutionPath = path.resolve(cwd, solutionName); + if (solutionName === '.') { + solutionName = path.basename(cwd); + solutionPath = cwd; + } + + const modifyFileContent = (content: string) => + content + .replace(/hello-world/g, changeCase.paramCase(solutionName)) + .replace(/HelloWorld/g, changeCase.pascalCase(solutionName)) + .replace(/Hello World/g, changeCase.titleCase(solutionName)); + + await ensureDirExists(solutionPath); + + const templateFiles = getLowcodeSolutionTemplateFiles(); + for (const templateFile of templateFiles) { + if (options.verbose) { + console.log('%s', chalk.gray(`creating file ${templateFile.file}`)); + } + + const templateFilePath = path.join(solutionPath, templateFile.file); + await ensureDirExists(path.dirname(templateFilePath)); + await fs.writeFile(templateFilePath, modifyFileContent(templateFile.content), { encoding: 'utf-8' }); + } + + if (!options.quiet) { + console.log('%s', chalk.green(`solution ${solutionName} created successfully`)); + } + + return 0; + } catch (e) { + console.log(chalk.red(getErrorMessage(e) || `Unexpected error: ${e}`)); + if (typeof e === 'object' && (e as { stack: string } | null)?.stack && options.verbose) { + console.log(chalk.gray((e as { stack: string }).stack)); + } + return 1; + } +} + +async function ensureDirExists(dirPath: string) { + try { + await fs.mkdir(dirPath, { recursive: true }); + } catch (e) { + if ((e as { code: string }).code === 'EEXIST') { + return;// ignore existing error + } + throw e; + } +} \ No newline at end of file diff --git a/modules/code-generator/src/cli/run.ts b/modules/code-generator/src/cli/run.ts new file mode 100644 index 0000000..304f5ea --- /dev/null +++ b/modules/code-generator/src/cli/run.ts @@ -0,0 +1,146 @@ +/* eslint-disable no-console */ +import chalk from 'chalk'; +import * as fs from 'fs-extra'; +import JSON5 from 'json5'; +import { jsonc } from 'jsonc'; +import { spawnSync } from 'child_process'; +import * as path from 'path'; + +import { getErrorMessage } from '../utils/errors'; +import CodeGenerator from '..'; +import type { IProjectBuilder } from '..'; +import type { IPublicTypeProjectSchema } from '@felce/lowcode-types'; + +/** + * 执行出码 CLI 命令 + * @param args 入参数组 + * @param options 选项 + * @returns {Promise} 错误码 + */ +export async function run( + args: string[], + options: { + solution: string; + input?: string; + output?: string; + quiet?: boolean; + verbose?: boolean; + solutionOptions?: string; + }, +): Promise { + try { + const schemaFile = options.input || args[0]; + if (!schemaFile) { + throw new Error( + 'a schema file must be specified by `--input ` or by the first positional argument', + ); + } + + if ((options.input && args.length > 0) || args.length > 1) { + throw new Error( + 'only one schema file can be specified, either by `--input ` or by the first positional argument', + ); + } + + let solutionOptions = {}; + + if (options.solutionOptions) { + try { + solutionOptions = JSON.parse(options.solutionOptions); + } catch (err: any) { + throw new Error(`solution options parse error, error message is "${err.message}"`); + } + } + + // 读取 Schema + const schema = await loadSchemaFile(schemaFile); + + // 创建一个项目构建器 + const createProjectBuilder = await getProjectBuilderFactory(options.solution, { + quiet: options.quiet, + }); + const builder = createProjectBuilder(solutionOptions); + + // 生成代码 + const generatedSourceCodes = await builder.generateProject(schema); + + // 输出到磁盘 + const publisher = CodeGenerator.publishers.disk(); + + await publisher.publish({ + project: generatedSourceCodes, + outputPath: options.output || 'generated', + projectSlug: 'example', + createProjectFolder: false, + }); + return 0; + } catch (e) { + console.log(chalk.red(getErrorMessage(e) || `Unexpected error: ${e}`)); + if (typeof e === 'object' && (e as { stack: string } | null)?.stack && options.verbose) { + console.log(chalk.gray((e as { stack: string }).stack)); + } + return 1; + } +} + +async function getProjectBuilderFactory( + solution: string, + { quiet }: { quiet?: boolean }, +): Promise<(options: { [prop: string]: any }) => IProjectBuilder> { + if (solution in CodeGenerator.solutions) { + return CodeGenerator.solutions[solution as 'icejs' | 'rax']; + } + + const solutionPackageName = isLocalSolution(solution) + ? solution + : `${solution.startsWith('@') ? solution : `@alilc/lowcode-solution-${solution}`}`; + + if (!isLocalSolution(solution)) { + if (!quiet) { + console.log(`"${solution}" is not internal, installing it as ${solutionPackageName}...`); + } + + spawnSync('npm', ['i', solutionPackageName], { + stdio: quiet ? 'ignore' : 'inherit', + }); + } + + // eslint-disable-next-line @typescript-eslint/no-require-imports + const solutionExports = require( + !isLocalSolution(solution) + ? solutionPackageName + : `${path.isAbsolute(solution) ? solution : path.join(process.cwd(), solution)}`, + ); + + const projectBuilderFactory = + solutionExports.createProjectBuilder || + solutionExports.createAppBuilder || + solutionExports.default; + + if (typeof projectBuilderFactory !== 'function') { + throw new Error( + `"${solutionPackageName}" should export project builder factory via named export 'createProjectBuilder' or via default export`, + ); + } + + return projectBuilderFactory; +} + +function isLocalSolution(solution: string) { + return solution.startsWith('.') || solution.startsWith('/') || solution.startsWith('~'); +} + +async function loadSchemaFile(schemaFile: string): Promise { + if (!schemaFile) { + throw new Error('invalid schema file name'); + } + + const schemaFileContent = await fs.readFile(schemaFile, 'utf8'); + + if (/\.json5/.test(schemaFile)) { + return JSON5.parse(schemaFileContent); + } + + // 默认用 JSONC 的格式解析(兼容 JSON) + return jsonc.parse(schemaFileContent); +} diff --git a/modules/code-generator/src/cli/solutions/example-solution.ts b/modules/code-generator/src/cli/solutions/example-solution.ts new file mode 100644 index 0000000..6c77929 --- /dev/null +++ b/modules/code-generator/src/cli/solutions/example-solution.ts @@ -0,0 +1,795 @@ +export function getLowcodeSolutionTemplateFiles() { + return [ + { + file: '.editorconfig', + content: `root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +quote_type = single + +[*.md] +trim_trailing_whitespace = false +`, + }, + { + file: '.eslintignore', + content: `# 忽略目录 +node_modules/ +build/ +dist/ +test-cases/ +test/ +tests/ +output/ +es/ +lib/ +coverage/ + +# 忽略文件 +**/*.min.js +**/*-min.js +**/*.bundle.js +`, + }, + { + file: '.eslintrc.js', + content: `module.exports = { + extends: 'eslint-config-ali/typescript/react', + rules: { + 'max-len': ['error', { code: 200 }], + 'comma-dangle': 0, + }, +}; +`, + }, + { + file: '.gitignore', + content: `# project custom +build +es +lib +dist +output +package-lock.json +deploy-space/packages +deploy-space/.env +generated + +# IDE +.vscode +.idea + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release +lib + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# mac config files +.DS_Store + +# codealike +codealike.json +.node +`, + }, + { + file: '.prettierignore', + content: '/test-cases/', + }, + { + file: '.prettierrc', + content: `{ + "tabWidth": 2, + "singleQuote": true, + "trailingComma": "es5" +} +`, + }, + { + file: 'CHANGELOG.md', + content: '', + }, + { + file: 'CONTRIBUTING.md', + content: `# 欢迎共建 + +# 注意 + +- 注意解决 eslint 问题 +- 注意代码格式化 -- 建议安装 prettier 插件 +- 发布前注意要跑通 demo 和所有的单测 + +## 本地调试运行 Demo + +\`\`\`sh +> npm run demo +\`\`\` + +## 本地跑单测 + +\`\`\`sh +> npm test +\`\`\` +`, + }, + { + file: 'README.md', + content: `# 低代码出码自定义方案之 Hello World + +## 直接执行 + +\`\`\`sh +> npx ali-lowcode-solution-hello-world demo-schema.json +\`\`\` + +## 本地调试运行 Demo + +\`\`\`sh +> npm run demo +\`\`\` +`, + }, + { + file: 'demo-schema.json', + content: `{ + "version": "1.0.0", + "componentsMap": [ + { + "componentName": "Button", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Button" + }, + { + "componentName": "Button.Group", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Button", + "subName": "Group" + }, + { + "componentName": "Input", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Input" + }, + { + "componentName": "Form", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Form" + }, + { + "componentName": "Form.Item", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Form", + "subName": "Item" + }, + { + "componentName": "NumberPicker", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "NumberPicker" + }, + { + "componentName": "Select", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Select" + } + ], + "componentsTree": [ + { + "componentName": "Page", + "id": "node$1", + "meta": { + "title": "测试", + "router": "/" + }, + "props": { + "ref": "outterView", + "autoLoading": true + }, + "fileName": "test", + "state": { + "text": "outter" + }, + "lifeCycles": { + "componentDidMount": { + "type": "JSFunction", + "value": "function componentDidMount() {\\n console.log('componentDidMount');\\n}" + } + }, + "methodsModule": { + "type": "JSModule", + "source": "export function helloWorld() {\\n console.log('Hello world!');\\n}\\n" + }, + "dataSource": { + "list": [ + { + "id": "urlParams", + "type": "urlParams" + }, + + { + "id": "user", + "type": "fetch", + "options": { + "method": "GET", + "uri": "https://shs.xxx.com/mock/1458/demo/user", + "isSync": true + }, + "dataHandler": { + "type": "JSExpression", + "value": "function (response) {\\nif (!response.data.success){\\n throw new Error(response.data.message);\\n }\\n return response.data.data;\\n}" + } + }, + + { + "id": "orders", + "type": "fetch", + "options": { + "method": "GET", + "uri": "https://shs.xxx.com/mock/1458/demo/orders", + "isSync": true + }, + "dataHandler": { + "type": "JSExpression", + "value": "function (response) {\\nif (!response.data.success){\\n throw new Error(response.data.message);\\n }\\n return response.data.data.result;\\n}" + } + } + ], + "dataHandler": { + "type": "JSExpression", + "value": "function (dataMap) {\\n console.info(\\"All datasources loaded:\\", dataMap);\\n}" + } + }, + "children": [ + { + "componentName": "Form", + "id": "node$2", + "props": { + "labelCol": { + "type": "JSExpression", + "value": "this.state.colNum" + }, + "style": {}, + "ref": "testForm" + }, + "children": [ + { + "componentName": "Form.Item", + "id": "node$3", + "props": { + "label": "姓名:", + "name": "name", + "initValue": "李雷" + }, + "children": [ + { + "componentName": "Input", + "id": "node$4", + "props": { + "placeholder": "请输入", + "size": "medium", + "style": { + "width": 320 + } + } + } + ] + }, + { + "componentName": "Form.Item", + "id": "node$5", + "props": { + "label": "年龄:", + "name": "age", + "initValue": "22" + }, + "children": [ + { + "componentName": "NumberPicker", + "id": "node$6", + "props": { + "size": "medium", + "type": "normal" + } + } + ] + }, + { + "componentName": "Form.Item", + "id": "node$7", + "props": { + "label": "职业:", + "name": "profession" + }, + "children": [ + { + "componentName": "Select", + "id": "node$8", + "props": { + "dataSource": [ + { + "label": "教师", + "value": "t" + }, + { + "label": "医生", + "value": "d" + }, + { + "label": "歌手", + "value": "s" + } + ] + } + } + ] + }, + { + "componentName": "Div", + "id": "node$9", + "props": { + "style": { + "textAlign": "center" + } + }, + "children": [ + { + "componentName": "Button.Group", + "id": "node$a", + "props": {}, + "children": [ + { + "componentName": "Button", + "id": "node$b", + "condition": { + "type": "JSExpression", + "value": "this.index >= 1" + }, + "loop": ["a", "b", "c"], + "props": { + "type": "primary", + "style": { + "margin": "0 5px 0 5px" + } + }, + "children": [ + { + "type": "JSExpression", + "value": "this.item" + } + ] + } + ] + } + ] + } + ] + } + ] + } + ], + "constants": { + "ENV": "prod", + "DOMAIN": "xxx.xxx.com" + }, + "css": "body {font-size: 12px;} .table { width: 100px;}", + "config": { + "sdkVersion": "1.0.3", + "historyMode": "hash", + "targetRootID": "J_Container", + "layout": { + "componentName": "BasicLayout", + "props": { + "logo": "...", + "name": "测试网站" + } + }, + "theme": { + "package": "@alife/theme-fusion", + "version": "^0.1.0", + "primary": "#ff9966" + } + }, + "meta": { + "name": "demo应用", + "git_group": "appGroup", + "project_name": "app_demo", + "description": "这是一个测试应用", + "spma": "spa23d", + "creator": "月飞" + } +} +`, + }, + { + file: 'jest.config.js', + content: `module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + testPathIgnorePatterns: ['/node_modules/', '/test-cases/', '/static-files/', '/lib/'], +}; +`, + }, + { + file: 'package.json', + content: `{ + "name": "ali-lowcode-solution-hello-world", + "version": "1.0.0", + "description": "AlLowCode Code Generate Solution - Hello World", + "files": [ + "src", + "lib", + "tests", + "jest.config.js", + ".editorconfig", + ".eslintignore", + ".eslintrc.js", + ".gitignore", + ".prettierignore", + ".prettierrc", + "CHANGELOG.md", + "CONTRIBUTING.md", + "demo-schema.json", + "package.json", + "README.md", + "tsconfig.json" + ], + "main": "lib/index.js", + "scripts": { + "start": "jest --watch", + "build": "npm run clean && concurrently 'npm run build:ts' 'npm run lint'", + "build:ts": "tsc", + "check:type": "tsc -p . --noEmit", + "clean": "rm -rf build dist lib generated", + "dev": "build-scripts start", + "lint": "eslint --ext .tsx,.ts,.js,.jsx src", + "lintfix": "eslint --fix --color --ext .tsx,.ts,.js,.jsx src", + "lint-staged": "lint-staged", + "prepublishOnly": "npm run build", + "postpublish": "git push origin master --tags", + "test": "jest", + "test:watch": "jest --watch", + "test:update-snapshots": "cross-env UPDATE_EXPECTED=true npx jest", + "demo": "npm run build && npx @felce/lowcode-code-generator --solution . --output generated demo-schema.json" + }, + "repository": { + "type": "git", + "url": "git@github.com:your-name/ali-lowcode-solution-hello-world.git" + }, + "author": "", + "license": "ISC", + "publishConfig": { + "registry": "https://registry.npm.xxx.com" + }, + "dependencies": { + "@felce/lowcode-code-generator": "^1.0.0", + "@felce/lowcode-types": "^1.0.0", + "tslib": "^2.3.0" + }, + "devDependencies": { + "@types/async": "^3.2.3", + "@types/jest": "^26.0.17", + "@typescript-eslint/eslint-plugin": "^4.28.4", + "@typescript-eslint/parser": "^4.28.4", + "async": "^3.2.0", + "babel-runtime": "^6.26.0", + "concurrently": "^5.2.0", + "cross-env": "^7.0.0", + "debug": "^4.1.1", + "eslint": "^7.31.0", + "eslint-config-ali": "^12.1.0", + "eslint-plugin-import": "^2.23.4", + "eslint-plugin-react": "^7.24.0", + "eslint-plugin-react-hooks": "^4.2.0", + "glob": "^7.2.0", + "husky": "4.2.5", + "jest": "^26.6.3", + "json5": "^2.2.0", + "lint-staged": "10.1.x", + "lodash": "^4.17.21", + "md5": "^2.2.1", + "prettier": "^2.3.2", + "ts-jest": "^26.4.4", + "ts-node": "^9.0.0", + "typescript": "4.x" + } +} +`, + }, + { + file: 'tsconfig.json', + content: `{ + "compilerOptions": { + "esModuleInterop": true, + "declaration": true, + "experimentalDecorators": true, + "forceConsistentCasingInFileNames": true, + "importHelpers": true, + "incremental": false, + "jsx": "react", + "moduleResolution": "node", + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "stripInternal": true, + "outDir": "./lib", + "declarationDir": "./lib", + "rootDirs": ["./src"], + "target": "es6", + "module": "commonjs", + "lib": ["esnext"], + "types": ["jest", "node"], + "noUnusedLocals": false, + "noUnusedParameters": false + }, + "include": ["src/**/*", "typings/**/*"] +} +`, + }, + { + file: 'src/index.ts', + content: `import CodeGen from '@felce/lowcode-code-generator'; + +import examplePlugin from './plugins/example'; + +export default function createHelloWorldProjectBuilder() { + return CodeGen.createProjectBuilder({ + template: CodeGen.solutionParts.icejs.template, + plugins: { + components: [ + CodeGen.plugins.icejs.reactCommonDeps(), + CodeGen.plugins.common.esModule({ fileType: 'jsx' }), + CodeGen.plugins.common.styleImport(), + CodeGen.plugins.icejs.containerClass(), + CodeGen.plugins.icejs.containerInjectContext(), + CodeGen.plugins.icejs.containerInjectUtils(), + CodeGen.plugins.icejs.containerInjectDataSourceEngine(), + CodeGen.plugins.icejs.containerInjectI18n(), + CodeGen.plugins.icejs.containerInjectConstants(), + CodeGen.plugins.icejs.containerInitState(), + CodeGen.plugins.icejs.containerLifeCycle(), + CodeGen.plugins.icejs.containerMethod(), + examplePlugin(), + CodeGen.plugins.icejs.jsx({ + nodeTypeMapping: { + Div: 'div', + Component: 'div', + Page: 'div', + Block: 'div', + }, + }), + CodeGen.plugins.style.css(), + ], + pages: [ + CodeGen.plugins.icejs.reactCommonDeps(), + CodeGen.plugins.common.esModule({ fileType: 'jsx' }), + CodeGen.plugins.common.styleImport(), + CodeGen.plugins.icejs.containerClass(), + CodeGen.plugins.icejs.containerInjectContext(), + CodeGen.plugins.icejs.containerInjectUtils(), + CodeGen.plugins.icejs.containerInjectDataSourceEngine(), + CodeGen.plugins.icejs.containerInjectI18n(), + CodeGen.plugins.icejs.containerInjectConstants(), + CodeGen.plugins.icejs.containerInitState(), + CodeGen.plugins.icejs.containerLifeCycle(), + CodeGen.plugins.icejs.containerMethod(), + examplePlugin(), + CodeGen.plugins.icejs.jsx({ + nodeTypeMapping: { + Div: 'div', + Component: 'div', + Page: 'div', + Block: 'div', + }, + }), + CodeGen.plugins.style.css(), + ], + router: [ + CodeGen.plugins.common.esModule(), + CodeGen.solutionParts.icejs.plugins.router(), + ], + entry: [CodeGen.solutionParts.icejs.plugins.entry()], + constants: [CodeGen.plugins.project.constants()], + utils: [ + CodeGen.plugins.common.esModule(), + CodeGen.plugins.project.utils('react'), + ], + i18n: [CodeGen.plugins.project.i18n()], + globalStyle: [CodeGen.solutionParts.icejs.plugins.globalStyle()], + htmlEntry: [CodeGen.solutionParts.icejs.plugins.entryHtml()], + packageJSON: [CodeGen.solutionParts.icejs.plugins.packageJSON()], + }, + postProcessors: [CodeGen.postprocessor.prettier()], + }); +} +`, + }, + { + file: 'src/plugins/example.ts', + content: `import { + ICodeStruct, + BuilderComponentPlugin, + BuilderComponentPluginFactory, + FileType, + ChunkType, + IContainerInfo, + COMMON_CHUNK_NAME, + CLASS_DEFINE_CHUNK_NAME, + DEFAULT_LINK_AFTER, +} from '@felce/lowcode-code-generator'; + +export interface PluginConfig { + fileType: string; +} + +const pluginFactory: BuilderComponentPluginFactory = ( + config? +) => { + const cfg: PluginConfig = { + fileType: FileType.JSX, + ...config, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IContainerInfo & { + methodsModule?: { + type?: 'JSModule'; + source?: string; + }; + }; + + if (ir.methodsModule?.type !== 'JSModule' || !ir.methodsModule?.source) { + return next; + } + + // 创建 methods.jsx + next.chunks.push({ + type: ChunkType.STRING, + subModule: 'methods', + fileType: cfg.fileType, + name: COMMON_CHUNK_NAME.CustomContent, + content: ir.methodsModule.source, + linkAfter: [], + }); + + // 引入对应的模块 + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: COMMON_CHUNK_NAME.InternalDepsImport, + content: "import __$$methodsModule from './methods';", + linkAfter: [...DEFAULT_LINK_AFTER[COMMON_CHUNK_NAME.InternalDepsImport]], + }); + + // 将导出的东东都放到 class 上实例方法部分 + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent, + content: 'Object.assign(this, __$$methodsModule);', + linkAfter: [ + ...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorContent], + ], + }); + + return next; + }; + + return plugin; +}; + +export default pluginFactory; +`, + }, + { + file: 'tests/basic.test.ts', + content: `test('basic functions should be ok', () => { + // 这里放一些单元测试 + expect(0).toBe(0); +}); +`, + }, + ]; +} diff --git a/modules/code-generator/src/config/env.ts b/modules/code-generator/src/config/env.ts new file mode 100644 index 0000000..30d564c --- /dev/null +++ b/modules/code-generator/src/config/env.ts @@ -0,0 +1,3 @@ +import * as path from 'path'; + +export const CODE_GENERATOR_ROOT = path.join(__dirname, '../..'); diff --git a/modules/code-generator/src/const/file.ts b/modules/code-generator/src/const/file.ts new file mode 100644 index 0000000..d29ea43 --- /dev/null +++ b/modules/code-generator/src/const/file.ts @@ -0,0 +1,3 @@ +import { FileType } from '../types/core'; + +export const FILE_TYPE_FAMILY = [[FileType.TSX, FileType.TS, FileType.JSX, FileType.JS]]; diff --git a/modules/code-generator/src/const/generator.ts b/modules/code-generator/src/const/generator.ts new file mode 100644 index 0000000..1197458 --- /dev/null +++ b/modules/code-generator/src/const/generator.ts @@ -0,0 +1,129 @@ +export const COMMON_CHUNK_NAME = { + ExternalDepsImport: 'CommonExternalDependencyImport', + InternalDepsImport: 'CommonInternalDependencyImport', + ImportAliasDefine: 'CommonImportAliasDefine', + FileVarDefine: 'CommonFileScopeVarDefine', + FileUtilDefine: 'CommonFileScopeMethodDefine', + FileMainContent: 'CommonFileMainContent', + FileExport: 'CommonFileExport', + StyleDepsImport: 'CommonStyleDepsImport', + StyleCssContent: 'CommonStyleCssContent', + HtmlContent: 'CommonHtmlContent', + CustomContent: 'CommonCustomContent', +}; + +export const CLASS_DEFINE_CHUNK_NAME = { + Start: 'CommonClassDefineStart', + ConstructorStart: 'CommonClassDefineConstructorStart', + ConstructorContent: 'CommonClassDefineConstructorContent', + ConstructorEnd: 'CommonClassDefineConstructorEnd', + StaticVar: 'CommonClassDefineStaticVar', + StaticMethod: 'CommonClassDefineStaticMethod', + InsVar: 'CommonClassDefineInsVar', + InsVarMethod: 'CommonClassDefineInsVarMethod', + InsMethod: 'CommonClassDefineInsMethod', + InsPrivateMethod: 'CommonClassDefineInsPrivateMethod', + End: 'CommonClassDefineEnd', +}; + +export const DEFAULT_LINK_AFTER = { + [COMMON_CHUNK_NAME.ExternalDepsImport]: [], + [COMMON_CHUNK_NAME.InternalDepsImport]: [COMMON_CHUNK_NAME.ExternalDepsImport], + [COMMON_CHUNK_NAME.ImportAliasDefine]: [ + COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport, + ], + [COMMON_CHUNK_NAME.FileVarDefine]: [ + COMMON_CHUNK_NAME.ExternalDepsImport, + COMMON_CHUNK_NAME.InternalDepsImport, + COMMON_CHUNK_NAME.ImportAliasDefine, + ], + [COMMON_CHUNK_NAME.FileUtilDefine]: [ + COMMON_CHUNK_NAME.ExternalDepsImport, + COMMON_CHUNK_NAME.InternalDepsImport, + COMMON_CHUNK_NAME.ImportAliasDefine, + COMMON_CHUNK_NAME.FileVarDefine, + ], + [CLASS_DEFINE_CHUNK_NAME.Start]: [ + COMMON_CHUNK_NAME.ExternalDepsImport, + COMMON_CHUNK_NAME.InternalDepsImport, + COMMON_CHUNK_NAME.ImportAliasDefine, + COMMON_CHUNK_NAME.FileVarDefine, + COMMON_CHUNK_NAME.FileUtilDefine, + ], + [CLASS_DEFINE_CHUNK_NAME.ConstructorStart]: [ + CLASS_DEFINE_CHUNK_NAME.Start, + CLASS_DEFINE_CHUNK_NAME.StaticVar, + CLASS_DEFINE_CHUNK_NAME.StaticMethod, + CLASS_DEFINE_CHUNK_NAME.InsVar, + CLASS_DEFINE_CHUNK_NAME.InsVarMethod, + ], + [CLASS_DEFINE_CHUNK_NAME.ConstructorContent]: [CLASS_DEFINE_CHUNK_NAME.ConstructorStart], + [CLASS_DEFINE_CHUNK_NAME.ConstructorEnd]: [ + CLASS_DEFINE_CHUNK_NAME.ConstructorStart, + CLASS_DEFINE_CHUNK_NAME.ConstructorContent, + ], + [CLASS_DEFINE_CHUNK_NAME.StaticVar]: [CLASS_DEFINE_CHUNK_NAME.Start], + [CLASS_DEFINE_CHUNK_NAME.StaticMethod]: [ + CLASS_DEFINE_CHUNK_NAME.Start, CLASS_DEFINE_CHUNK_NAME.StaticVar, + ], + [CLASS_DEFINE_CHUNK_NAME.InsVar]: [ + CLASS_DEFINE_CHUNK_NAME.Start, + CLASS_DEFINE_CHUNK_NAME.StaticVar, + CLASS_DEFINE_CHUNK_NAME.StaticMethod, + ], + [CLASS_DEFINE_CHUNK_NAME.InsVarMethod]: [ + CLASS_DEFINE_CHUNK_NAME.Start, + CLASS_DEFINE_CHUNK_NAME.StaticVar, + CLASS_DEFINE_CHUNK_NAME.StaticMethod, + CLASS_DEFINE_CHUNK_NAME.InsVar, + ], + [CLASS_DEFINE_CHUNK_NAME.InsMethod]: [ + CLASS_DEFINE_CHUNK_NAME.Start, + CLASS_DEFINE_CHUNK_NAME.StaticVar, + CLASS_DEFINE_CHUNK_NAME.StaticMethod, + CLASS_DEFINE_CHUNK_NAME.InsVar, + CLASS_DEFINE_CHUNK_NAME.InsVarMethod, + CLASS_DEFINE_CHUNK_NAME.ConstructorEnd, + ], + [CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod]: [ + CLASS_DEFINE_CHUNK_NAME.Start, + CLASS_DEFINE_CHUNK_NAME.StaticVar, + CLASS_DEFINE_CHUNK_NAME.StaticMethod, + CLASS_DEFINE_CHUNK_NAME.InsVar, + CLASS_DEFINE_CHUNK_NAME.InsVarMethod, + CLASS_DEFINE_CHUNK_NAME.InsMethod, + CLASS_DEFINE_CHUNK_NAME.ConstructorEnd, + ], + [CLASS_DEFINE_CHUNK_NAME.End]: [ + CLASS_DEFINE_CHUNK_NAME.Start, + CLASS_DEFINE_CHUNK_NAME.StaticVar, + CLASS_DEFINE_CHUNK_NAME.StaticMethod, + CLASS_DEFINE_CHUNK_NAME.InsVar, + CLASS_DEFINE_CHUNK_NAME.InsVarMethod, + CLASS_DEFINE_CHUNK_NAME.InsMethod, + CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod, + CLASS_DEFINE_CHUNK_NAME.ConstructorEnd, + ], + [COMMON_CHUNK_NAME.FileMainContent]: [ + COMMON_CHUNK_NAME.ExternalDepsImport, + COMMON_CHUNK_NAME.InternalDepsImport, + COMMON_CHUNK_NAME.ImportAliasDefine, + COMMON_CHUNK_NAME.FileVarDefine, + COMMON_CHUNK_NAME.FileUtilDefine, + CLASS_DEFINE_CHUNK_NAME.End, + ], + [COMMON_CHUNK_NAME.FileExport]: [ + COMMON_CHUNK_NAME.ExternalDepsImport, + COMMON_CHUNK_NAME.InternalDepsImport, + COMMON_CHUNK_NAME.ImportAliasDefine, + COMMON_CHUNK_NAME.FileVarDefine, + COMMON_CHUNK_NAME.FileUtilDefine, + CLASS_DEFINE_CHUNK_NAME.End, + COMMON_CHUNK_NAME.FileMainContent, + ], + [COMMON_CHUNK_NAME.StyleDepsImport]: [], + [COMMON_CHUNK_NAME.StyleCssContent]: [COMMON_CHUNK_NAME.StyleDepsImport], + [COMMON_CHUNK_NAME.HtmlContent]: [], +}; + +export const COMMON_SUB_MODULE_NAME = 'index'; diff --git a/modules/code-generator/src/const/index.ts b/modules/code-generator/src/const/index.ts new file mode 100644 index 0000000..24449ca --- /dev/null +++ b/modules/code-generator/src/const/index.ts @@ -0,0 +1,33 @@ +export const NATIVE_ELE_PKG = 'native'; + +export const CONTAINER_TYPE = { + COMPONENT: 'Component', + BLOCK: 'Block', + PAGE: 'Page', +}; + +export const SUPPORT_SCHEMA_VERSION_LIST = ['0.0.1', '1.0.0']; + +// built-in slot names which have been handled in ProjectBuilder +export const BUILTIN_SLOT_NAMES = [ + 'pages', + 'components', + 'router', + 'entry', + 'appConfig', + 'buildConfig', + 'constants', + 'utils', + 'i18n', + 'globalStyle', + 'htmlEntry', + 'packageJSON', + 'demo', +]; + +export const isBuiltinSlotName = function (name: string) { + return BUILTIN_SLOT_NAMES.includes(name); +}; + +export * from './file'; +export * from './generator'; diff --git a/modules/code-generator/src/core/jsx/handlers/transformJsExpression.ts b/modules/code-generator/src/core/jsx/handlers/transformJsExpression.ts new file mode 100644 index 0000000..3bdb8fb --- /dev/null +++ b/modules/code-generator/src/core/jsx/handlers/transformJsExpression.ts @@ -0,0 +1,49 @@ +import { IScope } from '../../../types'; +import { parseExpression } from '../../../utils/expressionParser'; +import { isLiteralAtomicExpr } from '../util/isLiteralAtomicExpr'; +import { isSimpleStraightLiteral } from '../util/isSimpleStraightLiteral'; +import { transformThis2Context } from './transformThis2Context'; + +export function transformJsExpr( + expr: string, + scope: IScope, + { dontWrapEval = false, dontTransformThis2ContextAtRootScope = false } = {}, +) { + if (!expr) { + return 'undefined'; + } + + if (isLiteralAtomicExpr(expr)) { + return expr; + } + + const exprAst = parseExpression(expr); + + // 对于下面这些比较安全的字面值,可以直接返回对应的表达式,而非包一层 + if (isSimpleStraightLiteral(exprAst)) { + return expr; + } + + if (dontWrapEval) { + return transformThis2Context(exprAst, scope, { + ignoreRootScope: dontTransformThis2ContextAtRootScope, + }); + } + + switch (exprAst.type) { + // 对于直接写个函数的,则不用再包下,因为这样不会抛出异常的 + case 'ArrowFunctionExpression': + case 'FunctionExpression': + return transformThis2Context(exprAst, scope, { + ignoreRootScope: dontTransformThis2ContextAtRootScope, + }); + + default: + break; + } + + // 其他的都需要包一层 + return `__$$eval(() => (${transformThis2Context(exprAst, scope, { + ignoreRootScope: dontTransformThis2ContextAtRootScope, + })}))`; +} diff --git a/modules/code-generator/src/core/jsx/handlers/transformThis2Context.ts b/modules/code-generator/src/core/jsx/handlers/transformThis2Context.ts new file mode 100644 index 0000000..fbb1c17 --- /dev/null +++ b/modules/code-generator/src/core/jsx/handlers/transformThis2Context.ts @@ -0,0 +1,29 @@ +import { Expression } from '@babel/types'; +import generate from '@babel/generator'; +import { IScope } from '../../../types'; +import { parseExpressionConvertThis2Context } from '../../../utils/expressionParser'; + +/** + * 将所有的 this.xxx 替换为 __$$context.xxx + * @param expr + */ +export function transformThis2Context( + expr: string | Expression, + scope: IScope, + { ignoreRootScope = false } = {}, +): string { + if (ignoreRootScope && scope.parent == null) { + return typeof expr === 'string' ? expr : generate(expr).code; + } + + // 下面这种字符串替换的方式虽然简单直接,但是对于复杂场景会误匹配,故后期改成了解析 AST 然后修改 AST 最后再重新生成代码的方式 + // return expr + // .replace(/\bthis\.item\./g, () => 'item.') + // .replace(/\bthis\.index\./g, () => 'index.') + // .replace(/\bthis\./g, () => '__$$context.'); + return parseExpressionConvertThis2Context( + expr, + '__$$context', + scope.bindings?.getAllBindings() || [], + ); +} diff --git a/modules/code-generator/src/core/jsx/util/isLiteralAtomicExpr.ts b/modules/code-generator/src/core/jsx/util/isLiteralAtomicExpr.ts new file mode 100644 index 0000000..fe0c95a --- /dev/null +++ b/modules/code-generator/src/core/jsx/util/isLiteralAtomicExpr.ts @@ -0,0 +1,12 @@ +/** + * 判断是否是原子类型的表达式 + */ +export function isLiteralAtomicExpr(expr: string): boolean { + return ( + expr === 'null' || + expr === 'undefined' || + expr === 'true' || + expr === 'false' || + /^-?\d+(\.\d+)?$/.test(expr) + ); +} diff --git a/modules/code-generator/src/core/jsx/util/isSimpleStraightLiteral.ts b/modules/code-generator/src/core/jsx/util/isSimpleStraightLiteral.ts new file mode 100644 index 0000000..0b07152 --- /dev/null +++ b/modules/code-generator/src/core/jsx/util/isSimpleStraightLiteral.ts @@ -0,0 +1,17 @@ +import { Expression } from '@babel/types'; + +/** 判断是非是一些简单直接的字面值 */ +export function isSimpleStraightLiteral(expr: Expression): boolean { + switch (expr.type) { + case 'BigIntLiteral': + case 'BooleanLiteral': + case 'DecimalLiteral': + case 'NullLiteral': + case 'NumericLiteral': + case 'RegExpLiteral': + case 'StringLiteral': + return true; + default: + return false; + } +} diff --git a/modules/code-generator/src/generator/ChunkBuilder.ts b/modules/code-generator/src/generator/ChunkBuilder.ts new file mode 100644 index 0000000..6799d59 --- /dev/null +++ b/modules/code-generator/src/generator/ChunkBuilder.ts @@ -0,0 +1,123 @@ +import { BuilderComponentPlugin, IChunkBuilder, ICodeChunk, ICodeStruct, FileType } from '../types'; + +import { COMMON_SUB_MODULE_NAME } from '../const/generator'; +import { FILE_TYPE_FAMILY } from '../const/file'; + +interface ChunkGroupInfo { + chunk: ICodeChunk; + familyIdx?: number; +} + +function whichFamily(type: FileType): [number, FileType[]] | undefined { + const idx = FILE_TYPE_FAMILY.findIndex((family) => family.indexOf(type) >= 0); + if (idx < 0) { + return undefined; + } + return [idx, FILE_TYPE_FAMILY[idx]]; +} + +export const groupChunks = (chunks: ICodeChunk[]): ICodeChunk[][] => { + const tmp: Record> = {}; + const col = chunks.reduce((chunksSet: Record, chunk) => { + const fileKey = chunk.subModule || COMMON_SUB_MODULE_NAME; + if (!chunksSet[fileKey]) { + // eslint-disable-next-line no-param-reassign + chunksSet[fileKey] = []; + } + const res = whichFamily(chunk.fileType as FileType); + const info: ChunkGroupInfo = { + chunk, + }; + if (res) { + const [familyIdx, family] = res; + const rank = family.indexOf(chunk.fileType as FileType); + if (tmp[fileKey]) { + if (tmp[fileKey][familyIdx] !== undefined) { + if (tmp[fileKey][familyIdx] > rank) { + tmp[fileKey][familyIdx] = rank; + } + } else { + tmp[fileKey][familyIdx] = rank; + } + } else { + tmp[fileKey] = {}; + tmp[fileKey][familyIdx] = rank; + } + info.familyIdx = familyIdx; + } + + chunksSet[fileKey].push(info); + return chunksSet; + }, {}); + + const result: ICodeChunk[][] = []; + Object.keys(col).forEach((key) => { + const byType: Record = {}; + col[key].forEach((info) => { + let t: string = info.chunk.fileType; + if (info.familyIdx !== undefined) { + t = FILE_TYPE_FAMILY[info.familyIdx][tmp[key][info.familyIdx]]; + // eslint-disable-next-line no-param-reassign + info.chunk.fileType = t; + } + if (!byType[t]) { + byType[t] = []; + } + byType[t].push(info.chunk); + }); + result.push(...Object.keys(byType).map((t) => byType[t])); + }); + + return result; +}; + +/** + * 代码片段构建器 + * + * @export + * @class ChunkBuilder + * @template T + */ +export class ChunkBuilder implements IChunkBuilder { + private plugins: BuilderComponentPlugin[]; + + constructor(plugins: BuilderComponentPlugin[] = []) { + this.plugins = plugins; + } + + async run( + ir: unknown, + initialStructure: ICodeStruct = { + ir, + chunks: [], + depNames: [], + contextData: {}, + }, + ) { + const structure = initialStructure; + + const finalStructure: ICodeStruct = await this.plugins.reduce( + async (previousPluginOperation: Promise, plugin) => { + const modifiedStructure = await previousPluginOperation; + return plugin(modifiedStructure); + }, + Promise.resolve(structure), + ); + + const chunks = groupChunks(finalStructure.chunks); + + return { + chunks, + }; + } + + getPlugins() { + return this.plugins; + } + + addPlugin(plugin: BuilderComponentPlugin) { + this.plugins.push(plugin); + } +} + +export default ChunkBuilder; diff --git a/modules/code-generator/src/generator/CodeBuilder.ts b/modules/code-generator/src/generator/CodeBuilder.ts new file mode 100644 index 0000000..e633bab --- /dev/null +++ b/modules/code-generator/src/generator/CodeBuilder.ts @@ -0,0 +1,103 @@ +import { + ChunkContent, + ChunkType, + CodeGeneratorError, + CodeGeneratorFunction, + ICodeBuilder, + ICodeChunk, +} from '../types'; + +export class CodeBuilder implements ICodeBuilder { + private chunkDefinitions: ICodeChunk[] = []; + + private generators: { [key: string]: CodeGeneratorFunction } = { + [ChunkType.STRING]: (str: string) => str, // no-op for string chunks + [ChunkType.JSON]: (json: Record) => JSON.stringify(json), // stringify json to string + }; + + constructor(chunkDefinitions: ICodeChunk[] = []) { + this.chunkDefinitions = chunkDefinitions; + } + + /** + * Links all chunks together based on their requirements. Returns an array + * of ordered chunk names which need to be compiled and glued together. + */ + link(chunkDefinitions: ICodeChunk[] = []): string { + const chunks = chunkDefinitions || this.chunkDefinitions; + if (chunks.length <= 0) { + return ''; + } + + const unprocessedChunks = chunks.map((chunk) => { + return { + name: chunk.name, + type: chunk.type, + content: chunk.content, + linkAfter: this.cleanupInvalidChunks(chunk.linkAfter, chunks), + }; + }); + + const resultingString: string[] = []; + + while (unprocessedChunks.length > 0) { + let indexToRemove = 0; + for (let index = 0; index < unprocessedChunks.length; index++) { + if (unprocessedChunks[index].linkAfter.length <= 0) { + indexToRemove = index; + break; + } + } + + if (unprocessedChunks[indexToRemove].linkAfter.length > 0) { + throw new CodeGeneratorError( + 'Operation aborted. Reason: cyclic dependency between chunks.', + ); + } + + const { type, content, name } = unprocessedChunks[indexToRemove]; + const compiledContent = this.generateByType(type, content); + if (compiledContent) { + resultingString.push(`${compiledContent}\n`); + } + + unprocessedChunks.splice(indexToRemove, 1); + if (!unprocessedChunks.some((ch) => ch.name === name)) { + unprocessedChunks.forEach( + // remove the processed chunk from all the linkAfter arrays from the remaining chunks + (ch) => { + // eslint-disable-next-line no-param-reassign + ch.linkAfter = ch.linkAfter.filter((after) => after !== name); + }, + ); + } + } + + return resultingString.join('\n'); + } + + generateByType(type: string, content: unknown): string { + if (!content) { + return ''; + } + if (Array.isArray(content)) { + return content.map((contentItem) => this.generateByType(type, contentItem)).join('\n'); + } + + if (!this.generators[type]) { + throw new Error( + `Attempted to generate unknown type ${type}. Please register a generator for this type in builder/index.ts`, + ); + } + + return this.generators[type](content); + } + + // remove invalid chunks (which did not end up being created) from the linkAfter fields + // one use-case is when you want to remove the import plugin + private cleanupInvalidChunks(linkAfter: string[], chunks: ICodeChunk[]) { + return linkAfter.filter((chunkName) => chunks.some((chunk) => chunk.name === chunkName)); + } +} + +export default CodeBuilder; diff --git a/modules/code-generator/src/generator/ModuleBuilder.ts b/modules/code-generator/src/generator/ModuleBuilder.ts new file mode 100644 index 0000000..d0fc943 --- /dev/null +++ b/modules/code-generator/src/generator/ModuleBuilder.ts @@ -0,0 +1,118 @@ +import { IPublicTypeProjectSchema, ResultFile, ResultDir } from '@felce/lowcode-types'; + +import { + BuilderComponentPlugin, + CodeGeneratorError, + ICodeChunk, + ICompiledModule, + IContextData, + IModuleBuilder, + IParseResult, + ISchemaParser, + PostProcessor, +} from '../types'; + +import { COMMON_SUB_MODULE_NAME } from '../const/generator'; + +import { SchemaParser } from '../parser/SchemaParser'; +import { ChunkBuilder } from './ChunkBuilder'; +import { CodeBuilder } from './CodeBuilder'; +import { createResultFile, createResultDir, addFile } from '../utils/resultHelper'; + +export function createModuleBuilder( + options: { + plugins: BuilderComponentPlugin[]; + postProcessors: PostProcessor[]; + mainFileName?: string; + contextData?: IContextData; + } = { + plugins: [], + postProcessors: [], + }, +): IModuleBuilder { + const chunkGenerator = new ChunkBuilder(options.plugins); + const linker = new CodeBuilder(); + + const generateModule = async (input: unknown): Promise => { + const moduleMainName = options.mainFileName || COMMON_SUB_MODULE_NAME; + if (chunkGenerator.getPlugins().length <= 0) { + throw new CodeGeneratorError( + 'No plugins found. Component generation cannot work without any plugins!', + ); + } + + let files: ResultFile[] = []; + + const { chunks } = await chunkGenerator.run(input, { + ir: input, + chunks: [], + depNames: [], + contextData: options.contextData || {}, + }); + + chunks.forEach((fileChunkList) => { + const content = linker.link(fileChunkList); + const file = createResultFile( + fileChunkList[0].subModule || moduleMainName, + fileChunkList[0].fileType, + content, + ); + files.push(file); + }); + + if (options.postProcessors.length > 0) { + files = files.map((file) => { + let { content, ext: type, name } = file; + options.postProcessors.forEach((processer) => { + content = processer(content, type, name); + }); + + return createResultFile(file.name, type, content); + }); + } + + return { + files, + }; + }; + + const generateModuleCode = async ( + schema: IPublicTypeProjectSchema | string, + ): Promise => { + // Init + const schemaParser: ISchemaParser = new SchemaParser(); + const parseResult: IParseResult = schemaParser.parse(schema); + + const containerInfo = parseResult.containers[0]; + const { files } = await generateModule(containerInfo); + + const dir = createResultDir(containerInfo.moduleName); + files.forEach((file) => addFile(dir, file)); + + return dir; + }; + + const linkCodeChunks = (chunks: Record, fileName: string) => { + const files: ResultFile[] = []; + + Object.keys(chunks).forEach((fileKey) => { + const fileChunkList = chunks[fileKey]; + const content = linker.link(fileChunkList); + const file = createResultFile( + fileChunkList[0].subModule || fileName, + fileChunkList[0].fileType, + content, + ); + files.push(file); + }); + + return files; + }; + + return { + generateModule, + generateModuleCode, + linkCodeChunks, + addPlugin: chunkGenerator.addPlugin.bind(chunkGenerator), + }; +} diff --git a/modules/code-generator/src/generator/ProjectBuilder.ts b/modules/code-generator/src/generator/ProjectBuilder.ts new file mode 100644 index 0000000..4e6d57e --- /dev/null +++ b/modules/code-generator/src/generator/ProjectBuilder.ts @@ -0,0 +1,372 @@ +import { ResultDir, ResultFile, IPublicTypeProjectSchema } from '@felce/lowcode-types'; + +import { + IModuleBuilder, + IParseResult, + IProjectBuilder, + IProjectPlugins, + IProjectTemplate, + ISchemaParser, + PostProcessor, +} from '../types'; + +import { SchemaParser } from '../parser/SchemaParser'; +import { createResultDir, addDirectory, addFile } from '../utils/resultHelper'; + +import { createModuleBuilder } from './ModuleBuilder'; +import { ProjectPreProcessor, ProjectPostProcessor, IContextData } from '../types/core'; +import { CodeGeneratorError } from '../types/error'; +import { isBuiltinSlotName } from '../const'; + +interface IModuleInfo { + moduleName?: string; + path: string[]; + files: ResultFile[]; +} + +export interface ProjectBuilderInitOptions { + /** 项目模板 */ + template: IProjectTemplate; + + /** 项目插件 */ + plugins: IProjectPlugins; + + /** 模块后置处理器 */ + postProcessors: PostProcessor[]; + + /** Schema 解析器 */ + schemaParser?: ISchemaParser; + + /** 项目级别的前置处理器 */ + projectPreProcessors?: ProjectPreProcessor[]; + + /** 项目级别的后置处理器 */ + projectPostProcessors?: ProjectPostProcessor[]; + + /** 是否处于严格模式 */ + inStrictMode?: boolean; + + /** 一些额外的上下文数据 */ + extraContextData?: Record; + + /** + * Hook which is used to customize original options, we can reorder/add/remove plugins/processors + * of the existing solution. + */ + customizeBuilderOptions?(originalOptions: ProjectBuilderInitOptions): ProjectBuilderInitOptions; +} + +export class ProjectBuilder implements IProjectBuilder { + /** 项目模板 */ + private template: IProjectTemplate; + + /** 项目插件 */ + private plugins: IProjectPlugins; + + /** 模块后置处理器 */ + private postProcessors: PostProcessor[]; + + /** Schema 解析器 */ + private schemaParser: ISchemaParser; + + /** 项目级别的前置处理器 */ + private projectPreProcessors: ProjectPreProcessor[]; + + /** 项目级别的后置处理器 */ + private projectPostProcessors: ProjectPostProcessor[]; + + /** 是否处于严格模式 */ + readonly inStrictMode: boolean; + + /** 一些额外的上下文数据 */ + readonly extraContextData: IContextData; + + constructor(builderOptions: ProjectBuilderInitOptions) { + let customBuilderOptions = builderOptions; + if (typeof builderOptions.customizeBuilderOptions === 'function') { + customBuilderOptions = builderOptions.customizeBuilderOptions(builderOptions); + } + const { + template, + plugins, + postProcessors, + schemaParser = new SchemaParser(), + projectPreProcessors = [], + projectPostProcessors = [], + inStrictMode = false, + extraContextData = {}, + } = customBuilderOptions; + this.template = template; + this.plugins = plugins; + this.postProcessors = postProcessors; + this.schemaParser = schemaParser; + this.projectPreProcessors = projectPreProcessors; + this.projectPostProcessors = projectPostProcessors; + this.inStrictMode = inStrictMode; + this.extraContextData = extraContextData; + } + + async generateProject(originalSchema: IPublicTypeProjectSchema | string): Promise { + // Init + const { schemaParser } = this; + + let schema: IPublicTypeProjectSchema = + typeof originalSchema === 'string' ? JSON.parse(originalSchema) : originalSchema; + + // Parse / Format + // Preprocess + for (const preProcessor of this.projectPreProcessors) { + // eslint-disable-next-line no-await-in-loop + schema = await preProcessor(schema); + } + + // Validate + if (!schemaParser.validate(schema)) { + throw new CodeGeneratorError('Schema is invalid'); + } + + // Collect Deps + // Parse JSExpression + const parseResult: IParseResult = schemaParser.parse(schema); + + const projectRoot = await this.template.generateTemplate(parseResult); + + let buildResult: IModuleInfo[] = []; + + const builders = this.createModuleBuilders({ + extraContextData: { + projectRemark: parseResult?.project?.projectRemark, + template: this.template, + }, + }); + // Generator Code module + // components + // pages + const containerBuildResult: IModuleInfo[] = await Promise.all( + parseResult.containers.map(async (containerInfo) => { + let builder: IModuleBuilder; + let path: string[]; + if (containerInfo.containerType === 'Page') { + builder = builders.pages; + path = this.template.slots.pages.path; + } else { + builder = builders.components; + path = this.template.slots.components.path; + } + + const { files } = await builder.generateModule(containerInfo); + + return { + moduleName: containerInfo.moduleName, + path, + files, + }; + }), + ); + buildResult = buildResult.concat(containerBuildResult); + + // router + if (parseResult.globalRouter && builders.router) { + const { files } = await builders.router.generateModule(parseResult.globalRouter); + + buildResult.push({ + path: this.template.slots.router.path, + files, + }); + } + + // entry + if (parseResult.project && builders.entry) { + const { files } = await builders.entry.generateModule(parseResult.project); + + buildResult.push({ + path: this.template.slots.entry.path, + files, + }); + } + + // appConfig + if (builders.appConfig) { + const { files } = await builders.appConfig.generateModule(parseResult); + + buildResult.push({ + path: this.template.slots.appConfig.path, + files, + }); + } + + // buildConfig + if (builders.buildConfig) { + const { files } = await builders.buildConfig.generateModule(parseResult); + + buildResult.push({ + path: this.template.slots.buildConfig.path, + files, + }); + } + + // constants? + if (parseResult.project && builders.constants && this.template.slots.constants) { + const { files } = await builders.constants.generateModule(parseResult.project); + + buildResult.push({ + path: this.template.slots.constants.path, + files, + }); + } + + // utils? + if (parseResult.globalUtils && builders.utils && this.template.slots.utils) { + const { files } = await builders.utils.generateModule(parseResult.globalUtils); + + buildResult.push({ + path: this.template.slots.utils.path, + files, + }); + } + + // i18n? + if (builders.i18n && this.template.slots.i18n) { + const { files } = await builders.i18n.generateModule(parseResult.project); + + buildResult.push({ + path: this.template.slots.i18n.path, + files, + }); + } + + // globalStyle + if (parseResult.project && builders.globalStyle) { + const { files } = await builders.globalStyle.generateModule(parseResult.project); + + buildResult.push({ + path: this.template.slots.globalStyle.path, + files, + }); + } + + // htmlEntry + if (parseResult.project && builders.htmlEntry) { + const { files } = await builders.htmlEntry.generateModule(parseResult.project); + + buildResult.push({ + path: this.template.slots.htmlEntry.path, + files, + }); + } + + // packageJSON + if (parseResult.project && builders.packageJSON) { + const { files } = await builders.packageJSON.generateModule(parseResult.project); + + buildResult.push({ + path: this.template.slots.packageJSON.path, + files, + }); + } + + // demo + if (parseResult.project && builders.demo) { + const { files } = await builders.demo.generateModule(parseResult.project); + buildResult.push({ + path: this.template.slots.demo.path, + files, + }); + } + + // handle extra slots + await this.generateExtraSlots(builders, parseResult, buildResult); + + // Post Process + const isSingleComponent = parseResult?.project?.projectRemark?.isSingleComponent; + // Combine Modules + buildResult.forEach((moduleInfo) => { + let targetDir = getDirFromRoot(projectRoot, moduleInfo.path); + // if project only contain single component, skip creation of directory. + if (moduleInfo.moduleName && !isSingleComponent) { + const dir = createResultDir(moduleInfo.moduleName); + addDirectory(targetDir, dir); + targetDir = dir; + } + moduleInfo.files.forEach((file) => addFile(targetDir, file)); + }); + + // post-processors + let finalResult = projectRoot; + for (const projectPostProcessor of this.projectPostProcessors) { + // eslint-disable-next-line no-await-in-loop + finalResult = await projectPostProcessor(finalResult, schema, originalSchema, { + template: this.template, + parseResult, + }); + } + + return finalResult; + } + + private createModuleBuilders( + extraContextData: Record = {}, + ): Record { + const builders: Record = {}; + + Object.keys(this.plugins).forEach((pluginName) => { + if (this.plugins[pluginName].length > 0) { + const options: { mainFileName?: string } = {}; + if (this.template.slots[pluginName] && this.template.slots[pluginName].fileName) { + options.mainFileName = this.template.slots[pluginName].fileName; + } + builders[pluginName] = createModuleBuilder({ + plugins: this.plugins[pluginName], + postProcessors: this.postProcessors, + contextData: { + // template: this.template, + inStrictMode: this.inStrictMode, + tolerateEvalErrors: true, + evalErrorsHandler: '', + ...this.extraContextData, + ...extraContextData, + }, + ...options, + }); + } + }); + + return builders; + } + + private async generateExtraSlots( + builders: Record, + parseResult: IParseResult, + buildResult: IModuleInfo[], + ) { + for (const slotName in this.template.slots) { + if (!isBuiltinSlotName(slotName)) { + const { files } = await builders[slotName].generateModule(parseResult); + buildResult.push({ + path: this.template.slots[slotName].path, + files, + }); + } + } + } +} + +export function createProjectBuilder(initOptions: ProjectBuilderInitOptions): IProjectBuilder { + return new ProjectBuilder(initOptions); +} + +function getDirFromRoot(root: ResultDir, path: string[]): ResultDir { + let current: ResultDir = root; + path.forEach((p) => { + const exist = current.dirs.find((d) => d.name === p); + if (exist) { + current = exist; + } else { + const newDir = createResultDir(p); + addDirectory(current, newDir); + current = newDir; + } + }); + + return current; +} diff --git a/modules/code-generator/src/index.ts b/modules/code-generator/src/index.ts new file mode 100644 index 0000000..da9b12d --- /dev/null +++ b/modules/code-generator/src/index.ts @@ -0,0 +1,121 @@ +/** + * 低代码引擎的出码模块,负责将编排产出的 Schema 转换成实际可执行的代码。 + * 注意:为了保持 API 的稳定性,这里所有导出的 API 均要显式命名方式导出 + * (即用 export { xxx } from 'xx' 的方式,不要直接 export * from 'xxx') + * 而且所有导出的 API 务必在 tests/public 中编写单元测试 + */ +import { createProjectBuilder } from './generator/ProjectBuilder'; +import { createModuleBuilder } from './generator/ModuleBuilder'; +import { createDiskPublisher } from './publisher/disk'; +import { createZipPublisher } from './publisher/zip'; +import createIceJsProjectBuilder, { plugins as icejsPlugins } from './solutions/icejs'; +import createIceJs3ProjectBuilder, { plugins as icejs3Plugins } from './solutions/icejs3'; +import createRaxAppProjectBuilder, { plugins as raxPlugins } from './solutions/rax-app'; + +// 引入说明 +import { REACT_CHUNK_NAME } from './plugins/component/react/const'; +import { COMMON_CHUNK_NAME, CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from './const/generator'; + +// 引入通用插件组 +import esmodule from './plugins/common/esmodule'; +import requireUtils from './plugins/common/requireUtils'; +import styleImport from './plugins/common/styleImport'; + +import css from './plugins/component/style/css'; +import constants from './plugins/project/constants'; +import i18n from './plugins/project/i18n'; +import utils from './plugins/project/utils'; +import prettier from './postprocessor/prettier'; + +// 引入全局常用工具 +import * as globalUtils from './utils'; + +import * as CONSTANTS from './const'; + +// 引入内置解决方案模块 +import icejs from './plugins/project/framework/icejs'; +import icejs3 from './plugins/project/framework/icejs3'; +import rax from './plugins/project/framework/rax'; + +export default { + createProjectBuilder, + createModuleBuilder, + solutions: { + icejs: createIceJsProjectBuilder, + icejs3: createIceJs3ProjectBuilder, + rax: createRaxAppProjectBuilder, + }, + solutionParts: { + icejs, + icejs3, + rax, + }, + publishers: { + disk: createDiskPublisher, + zip: createZipPublisher, + }, + plugins: { + common: { + + /** + * 处理 ES Module + * @deprecated please use esModule + */ + esmodule, + esModule: esmodule, + requireUtils, + styleImport, + }, + style: { + css, + }, + project: { + constants, + i18n, + utils, + }, + icejs: { + ...icejsPlugins, + }, + icejs3: { + ...icejs3Plugins, + }, + rax: { + ...raxPlugins, + }, + + /** + * @deprecated please use icejs + */ + react: { + ...icejsPlugins, + }, + }, + postprocessor: { + prettier, + }, + utils: globalUtils, + chunkNames: { + COMMON_CHUNK_NAME, + CLASS_DEFINE_CHUNK_NAME, + REACT_CHUNK_NAME, + }, + defaultLinkAfter: { + COMMON_DEFAULT_LINK_AFTER: DEFAULT_LINK_AFTER, + }, + constants: CONSTANTS, +}; + +// 一些类型定义 +export * from './types'; + +// 一些常量定义 +export * from './const'; + +// 一些工具函数 +export * from './analyzer/componentAnalyzer'; +export * from './parser/SchemaParser'; +export * from './generator/ChunkBuilder'; +export * from './generator/CodeBuilder'; +export * from './generator/ModuleBuilder'; +export * from './generator/ProjectBuilder'; diff --git a/modules/code-generator/src/parser/SchemaParser.ts b/modules/code-generator/src/parser/SchemaParser.ts new file mode 100644 index 0000000..83dfc98 --- /dev/null +++ b/modules/code-generator/src/parser/SchemaParser.ts @@ -0,0 +1,394 @@ +/** + * 解析器是对输入的固定格式数据做拆解,使其符合引擎后续步骤预期,完成统一处理逻辑的步骤。 + * 本解析器面向的是标准 schema 协议。 + */ +import changeCase from 'change-case'; +import { + IPublicTypeUtilItem, + IPublicTypeNodeDataType, + IPublicTypeNodeSchema, + IPublicTypeContainerSchema, + IPublicTypeProjectSchema, + IPublicTypePropsMap, + IPublicTypeNodeData, + IPublicTypeNpmInfo, +} from '@felce/lowcode-types'; +import { + IPageMeta, + CodeGeneratorError, + CompatibilityError, + DependencyType, + IContainerInfo, + IDependency, + IExternalDependency, + IInternalDependency, + InternalDependencyType, + IParseResult, + ISchemaParser, + INpmPackage, + IRouterInfo, +} from '../types'; + +import { SUPPORT_SCHEMA_VERSION_LIST } from '../const'; + +import { getErrorMessage } from '../utils/errors'; +import { handleSubNodes, isValidContainerType, ContainerType } from '../utils/schema'; +import { uniqueArray } from '../utils/common'; +import { componentAnalyzer } from '../analyzer/componentAnalyzer'; +import { ensureValidClassName } from '../utils/validate'; +import type { ProjectRemark } from '../types/intermediate'; + +const defaultContainer: IContainerInfo = { + containerType: 'Component', + componentName: 'Component', + moduleName: 'Index', + fileName: 'Index', + css: '', + props: {}, +}; + +function getRootComponentName(typeName: string, maps: Record): string { + if (maps[typeName]) { + const rec = maps[typeName]; + if (rec.destructuring) { + return rec.componentName || typeName; + } + + const peerName = Object.keys(maps).find((depName: string) => { + const depInfo = maps[depName]; + return ( + depName !== typeName && + !depInfo.destructuring && + depInfo.package === rec.package && + depInfo.version === rec.version && + depInfo.main === rec.main && + depInfo.exportName === rec.exportName && + depInfo.subName === rec.subName + ); + }); + + return peerName || typeName; + } + return typeName; +} + +function processChildren(schema: IPublicTypeNodeSchema): void { + if (schema.props) { + if (Array.isArray(schema.props)) { + // FIXME: is array type props description + } else { + const nodeProps = schema.props as IPublicTypePropsMap; + if (nodeProps.children) { + if (!schema.children) { + // eslint-disable-next-line no-param-reassign + schema.children = nodeProps.children as IPublicTypeNodeDataType; + } else { + let _children: IPublicTypeNodeData[] = []; + + if (Array.isArray(schema.children)) { + _children = _children.concat(schema.children); + } else { + _children.push(schema.children); + } + + if (Array.isArray(nodeProps.children)) { + _children = _children.concat(nodeProps.children as IPublicTypeNodeData[]); + } else { + _children.push(nodeProps.children as IPublicTypeNodeData); + } + + // eslint-disable-next-line no-param-reassign + schema.children = _children; + } + delete nodeProps.children; + } + } + } +} + +function getInternalDep(internalDeps: Record, depName: string) { + const dep = internalDeps[depName]; + return dep && dep.type !== InternalDependencyType.PAGE ? dep : null; +} + +export class SchemaParser implements ISchemaParser { + validate(schema: IPublicTypeProjectSchema): boolean { + if (SUPPORT_SCHEMA_VERSION_LIST.indexOf(schema.version) < 0) { + throw new CompatibilityError(`Not support schema with version [${schema.version}]`); + } + + return true; + } + + parse(schemaSrc: IPublicTypeProjectSchema | string): IParseResult { + // TODO: collect utils depends in JSExpression + const compDeps: Record = {}; + const internalDeps: Record = {}; + let utilsDeps: IExternalDependency[] = []; + + const schema = this.decodeSchema(schemaSrc); + + // 解析三方组件依赖 + schema.componentsMap.forEach((info: any) => { + if (info.componentName) { + compDeps[info.componentName] = { + ...info, + dependencyType: DependencyType.External, + componentName: info.componentName, + exportName: info.exportName ?? info.componentName, + version: info.version || '*', + destructuring: info.destructuring ?? false, + }; + } + }); + + let containers: IContainerInfo[]; + // Test if this is a lowcode component without container + if (schema.componentsTree.length > 0) { + const firstRoot: IPublicTypeContainerSchema = schema + .componentsTree[0] as IPublicTypeContainerSchema; + + if (!firstRoot.fileName && !isValidContainerType(firstRoot)) { + // 整个 schema 描述一个容器,且无根节点定义 + const container: IContainerInfo = { + ...firstRoot, + ...defaultContainer, + props: firstRoot.props || defaultContainer.props, + css: firstRoot.css || defaultContainer.css, + moduleName: (firstRoot as IContainerInfo).moduleName || defaultContainer.moduleName, + children: schema.componentsTree as IPublicTypeNodeSchema[], + }; + containers = [container]; + } else { + // 普通带 1 到多个容器的 schema + containers = schema.componentsTree.map((n) => { + const subRoot = n as IPublicTypeContainerSchema; + const container: IContainerInfo = { + ...subRoot, + componentName: getRootComponentName(subRoot.componentName, compDeps), + containerType: subRoot.componentName, + moduleName: ensureValidClassName( + subRoot.componentName === ContainerType.Component + ? subRoot.fileName + : changeCase.pascalCase(subRoot.fileName), + ), + }; + return container; + }); + } + } else { + throw new CodeGeneratorError("Can't find anything to generate."); + } + + // 分析引用能力的依赖 + containers = containers.map((con) => ({ + ...con, + analyzeResult: componentAnalyzer(con as IPublicTypeContainerSchema), + })); + + // 建立所有容器的内部依赖索引 + containers.forEach((container) => { + let type; + switch (container.containerType) { + case 'Page': + type = InternalDependencyType.PAGE; + break; + case 'Block': + type = InternalDependencyType.BLOCK; + break; + default: + type = InternalDependencyType.COMPONENT; + break; + } + + const dep: IInternalDependency = { + type, + moduleName: container.moduleName, + destructuring: false, + exportName: container.moduleName, + dependencyType: DependencyType.Internal, + }; + + internalDeps[dep.moduleName] = dep; + }); + + const containersDeps = ([] as IDependency[]).concat(...containers.map((c) => c.deps || [])); + // TODO: 不应该在出码部分解决? + // 处理 children 写在了 props 里的情况 + containers.forEach((container) => { + if (container.children) { + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + handleSubNodes( + container.children, + { + node: (i: IPublicTypeNodeSchema) => processChildren(i), + }, + { + rerun: true, + }, + ); + } + }); + + containers.forEach((container) => { + const depNames = this.getComponentNames(container); + // eslint-disable-next-line no-param-reassign + container.deps = uniqueArray(depNames, (i: string) => i) + .map((depName) => getInternalDep(internalDeps, depName) || compDeps[depName]) + .filter(Boolean); + // container.deps = Object.keys(compDeps).map((depName) => compDeps[depName]); + }); + + // 分析路由配置 + const routes: IRouterInfo['routes'] = containers + .filter((container) => container.containerType === 'Page') + .map((page) => { + const { meta } = page; + if (meta) { + return { + path: (meta as IPageMeta).router || `/${page.fileName}`, // 如果无法找到页面路由信息,则用 fileName 做兜底 + fileName: page.fileName, + componentName: page.moduleName, + }; + } + + return { + path: '', + fileName: page.fileName, + componentName: page.moduleName, + }; + }); + + const routerDeps = routes + .map((r) => internalDeps[r.componentName] || compDeps[r.componentName]) + .filter((dep) => !!dep); + + // 分析 Utils 依赖 + let utils: IPublicTypeUtilItem[]; + if (schema.utils) { + utils = schema.utils; + utilsDeps = schema.utils + .filter( + (u): u is { name: string; type: 'npm' | 'tnpm'; content: IPublicTypeNpmInfo } => + u.type !== 'function', + ) + .map( + (u): IExternalDependency => ({ + ...u.content, + componentName: u.name, + version: u.content.version || '*', + destructuring: u.content.destructuring ?? false, + exportName: u.content.exportName ?? u.name, + }), + ); + } else { + utils = []; + } + + // 分析项目 npm 依赖 + let npms: INpmPackage[] = []; + containers.forEach((con) => { + const p = (con.deps || []) + .map((dep) => { + return dep.dependencyType === DependencyType.External ? dep : null; + }) + .filter((dep) => dep !== null); + const npmInfos: INpmPackage[] = p.filter(Boolean).map((i) => ({ + package: (i as IExternalDependency).package, + version: (i as IExternalDependency).version, + })); + npms.push(...npmInfos); + }); + + npms.push( + ...utilsDeps.map((utilsDep) => ({ + package: utilsDep.package, + version: utilsDep.version, + })), + ); + + npms = uniqueArray(npms, (i) => i.package).filter(Boolean); + + return { + containers, + globalUtils: { + utils, + deps: utilsDeps, + }, + globalI18n: schema.i18n, + globalRouter: { + routes, + deps: routerDeps, + }, + project: { + css: schema.css, + constants: schema.constants, + config: schema.config || {}, + meta: schema.meta || {}, + i18n: schema.i18n, + containersDeps, + utilsDeps, + packages: npms || [], + dataSourcesTypes: this.collectDataSourcesTypes(schema), + projectRemark: this.getProjectRemark(containers), + }, + }; + } + + getProjectRemark(containers: IContainerInfo[]): ProjectRemark { + return { + isSingleComponent: containers.length === 1 && containers[0].containerType === 'Component', + }; + } + + getComponentNames(children: IPublicTypeNodeDataType): string[] { + return handleSubNodes( + children, + { + node: (i: IPublicTypeNodeSchema) => i.componentName, + }, + { + rerun: true, + }, + ); + } + + decodeSchema(schemaSrc: string | IPublicTypeProjectSchema): IPublicTypeProjectSchema { + let schema: IPublicTypeProjectSchema; + if (typeof schemaSrc === 'string') { + try { + schema = JSON.parse(schemaSrc); + } catch (error) { + throw new CodeGeneratorError( + `Parse schema failed: ${getErrorMessage(error) || 'unknown reason'}`, + ); + } + } else { + schema = schemaSrc; + } + return schema; + } + + private collectDataSourcesTypes(schema: IPublicTypeProjectSchema): string[] { + const dataSourcesTypes = new Set(); + + // 数据源的默认类型为 fetch + const defaultDataSourceType = 'fetch'; + + // 收集应用级别的数据源 + schema.dataSource?.list?.forEach((ds) => { + dataSourcesTypes.add(ds.type || defaultDataSourceType); + }); + + // 收集容器级别的数据源(页面/组件/区块) + schema.componentsTree.forEach((rootNode) => { + rootNode.dataSource?.list?.forEach((ds) => { + dataSourcesTypes.add(ds.type || defaultDataSourceType); + }); + }); + + return Array.from(dataSourcesTypes.values()); + } +} + +export default SchemaParser; diff --git a/modules/code-generator/src/plugins/common/esmodule.ts b/modules/code-generator/src/plugins/common/esmodule.ts new file mode 100644 index 0000000..53f3f94 --- /dev/null +++ b/modules/code-generator/src/plugins/common/esmodule.ts @@ -0,0 +1,479 @@ +import { flatMap, camelCase, get } from 'lodash'; +import { COMMON_CHUNK_NAME } from '../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + CodeGeneratorError, + DependencyType, + FileType, + ICodeChunk, + ICodeStruct, + IDependency, + IExternalDependency, + IInternalDependency, + IWithDependency, +} from '../../types'; + +import { isValidIdentifier } from '../../utils/validate'; + +// TODO: main 这个信息到底怎么用,是不是外部包不需要使用? +const DEP_MAIN_BLOCKLIST = ['lib', 'lib/index', 'es', 'es/index', 'main']; +const DEFAULT_EXPORT_NAME = '__default__'; + +function groupDepsByPack(deps: IDependency[]): Record { + const depMap: Record = {}; + + const addDep = (pkg: string, dep: IDependency) => { + if (!depMap[pkg]) { + depMap[pkg] = []; + } + depMap[pkg].push(dep); + }; + + deps.forEach((dep) => { + if (dep.dependencyType === DependencyType.Internal) { + addDep(`${(dep as IInternalDependency).moduleName}${dep.main ? `/${dep.main}` : ''}`, dep); + } else { + let depMain = ''; + // TODO: 部分类型的 main 暂时认为没用 + if (dep.main && DEP_MAIN_BLOCKLIST.indexOf(dep.main) < 0) { + depMain = dep.main; + } + if (depMain.substring(0, 1) === '/') { + depMain = depMain.substring(1); + } + addDep(`${(dep as IExternalDependency).package}${depMain ? `/${depMain}` : ''}`, dep); + } + }); + + return depMap; +} + +interface IDependencyItem { + exportName: string; + aliasName?: string; + isDefault?: boolean; + subName?: string; + nodeIdentifier?: string; // 与使用处的映射关系,理论上是不可变更的,如需变更需要提供额外信息 + source: IDependency; +} + +interface IExportItem { + exportName: string; + aliasNames: string[]; + isDefault?: boolean; + needOriginExport: boolean; +} + +function getDependencyIdentifier(info: IDependencyItem): string { + return info.aliasName || info.exportName; +} + +function getExportNameOfDep(dep: IDependency): string { + if (dep.destructuring) { + return ( + dep.exportName || + dep.componentName || + throwNewError('destructuring dependency must have exportName or componentName') + ); + } + + if (!dep.subName) { + return ( + dep.componentName || + dep.exportName || + throwNewError('dependency item must have componentName or exportName') + ); + } + + return ( + dep.exportName || + `__$${camelCase( + get(dep, 'moduleName') || + get(dep, 'package') || + throwNewError('dep.moduleName or dep.package is undefined'), + )}_default` + ); +} + +function throwNewError(msg: string): never { + throw new Error(msg); +} + +function buildPackageImport( + pkg: string, + deps: IDependency[], + targetFileType: string, + useAliasName: boolean, +): ICodeChunk[] { + // 如果压根没有包,则不生成对应的 import 语句(生成了没有任何意义) + if (!pkg || pkg === 'undefined' || pkg === 'null') { + // TODO: 要不要加个 warning? + return []; + } + + const chunks: ICodeChunk[] = []; + + const exportItems: Record = {}; + const defaultExportNames: string[] = []; + + const depsInfo: IDependencyItem[] = deps.map((dep) => { + const info: IDependencyItem = { + exportName: getExportNameOfDep(dep), + isDefault: !dep.destructuring, + subName: dep.subName || undefined, + nodeIdentifier: dep.componentName || undefined, + source: dep, + }; + + // 下面 5 个逻辑是清理不必要的冗余信息,做到数据结构归一化 + if (info.isDefault) { + if (defaultExportNames.indexOf(info.exportName) < 0) { + defaultExportNames.push(info.exportName); + } + } + + if (!info.subName) { + if (info.nodeIdentifier === info.exportName) { + info.nodeIdentifier = undefined; + } + + if (info.isDefault) { + info.aliasName = info.nodeIdentifier || info.exportName; + info.exportName = DEFAULT_EXPORT_NAME; + } + + if (info.nodeIdentifier) { + info.aliasName = info.nodeIdentifier; + info.nodeIdentifier = undefined; + } + } else { + if (info.isDefault) { + info.aliasName = info.exportName; + info.exportName = DEFAULT_EXPORT_NAME; + } + + if (info.nodeIdentifier === `${info.exportName}.${info.subName}`) { + info.nodeIdentifier = undefined; + } + } + + return info; + }); + + // 建立 export 项目的列表 + depsInfo.forEach((info) => { + if (!exportItems[info.exportName]) { + exportItems[info.exportName] = { + exportName: info.exportName, + isDefault: info.isDefault, + aliasNames: [], + needOriginExport: false, + }; + } + + if (!info.nodeIdentifier && !info.aliasName) { + exportItems[info.exportName].needOriginExport = true; + } + }); + + // 建立别名字典 + depsInfo.forEach((info) => { + if (info.aliasName) { + const { aliasNames } = exportItems[info.exportName]; + if (aliasNames.indexOf(info.aliasName) < 0) { + aliasNames.push(info.aliasName); + } + } + }); + + // fix: 父组件ImportAliasDefine, 与子组件import的父组件冲突情况 + depsInfo.forEach((info) => { + if (info.nodeIdentifier) { + const exportItem = exportItems[info.exportName]; + if (!exportItem.needOriginExport && exportItem.aliasNames.length > 0) { + // eslint-disable-next-line no-param-reassign + info.aliasName = exportItem.aliasNames[0]; + } + } + }); + + // 发现 nodeIdentifier 与 exportName 或者 aliasName 冲突的场景 + const nodeIdentifiers = depsInfo.map((info) => info.nodeIdentifier).filter(Boolean); + const conflictInfos = flatMap(Object.keys(exportItems), (exportName) => { + const exportItem = exportItems[exportName]; + const usedNames = [ + ...exportItem.aliasNames, + ...(exportItem.needOriginExport || exportItem.aliasNames.length <= 0 ? [exportName] : []), + ]; + const conflictNames = usedNames.filter((n) => nodeIdentifiers.indexOf(n) >= 0); + if (conflictNames.length > 0) { + return [ + ...(conflictNames.indexOf(exportName) >= 0 ? [[exportName, true, exportItem]] : []), + ...conflictNames.filter((n) => n !== exportName).map((n) => [n, false, exportItem]), + ]; + } + return []; + }); + + const conflictExports = conflictInfos.filter((c) => c[1]).map((c) => c[0] as string); + const conflictAlias = conflictInfos.filter((c) => !c[1]).map((c) => c[0] as string); + + const solutions: Record = {}; + + depsInfo.forEach((info) => { + if (info.aliasName && conflictAlias.indexOf(info.aliasName) >= 0) { + // find solution + let solution = solutions[info.aliasName]; + if (!solution) { + solution = `${info.aliasName}Alias`; + const conflictItem = (conflictInfos.find((c) => c[0] === info.aliasName) || + [])[2] as IExportItem; + conflictItem.aliasNames = conflictItem.aliasNames.filter((a) => a !== info.aliasName); + conflictItem.aliasNames.push(solution); + solutions[info.aliasName] = solution; + } + // eslint-disable-next-line no-param-reassign + info.aliasName = solution; + } + + if (conflictExports.indexOf(info.exportName) >= 0) { + // find solution + let solution = solutions[info.exportName]; + if (!solution) { + solution = `${info.exportName}Export`; + const conflictItem = (conflictInfos.find((c) => c[0] === info.exportName) || + [])[2] as IExportItem; + conflictItem.aliasNames.push(solution); + conflictItem.needOriginExport = false; + solutions[info.exportName] = solution; + } + // eslint-disable-next-line no-param-reassign + info.aliasName = solution; + } + }); + + // 判断是否所有依赖都有合法的 Identifier + depsInfo.forEach((info) => { + const name = info.aliasName || info.exportName; + if (!isValidIdentifier(name)) { + throw new CodeGeneratorError(`Invalid Identifier [${name}]`); + } + if (info.nodeIdentifier && !isValidIdentifier(info.nodeIdentifier)) { + throw new CodeGeneratorError(`Invalid Identifier [${info.nodeIdentifier}]`); + } + }); + + const aliasDefineStatements: Record = {}; + if (useAliasName) { + Object.keys(exportItems).forEach((exportName) => { + const aliasList = exportItems[exportName]?.aliasNames || []; + if (aliasList.length > 0) { + const srcName = exportItems[exportName].needOriginExport ? exportName : aliasList[0]; + const aliasNameList = exportItems[exportName].needOriginExport + ? aliasList + : aliasList.slice(1); + aliasNameList.forEach((a) => { + if (!aliasDefineStatements[a]) { + aliasDefineStatements[a] = `const ${a} = ${srcName};`; + } + }); + } + }); + } + + function getDefaultExportName(info: IDependencyItem): string { + if (info.isDefault) { + return defaultExportNames[0]; + } + return info.exportName; + } + + depsInfo.forEach((info) => { + // 如果是子组件,则导出父组件,并且根据自组件命名规则,判断是否需要定义标识符 + if (info.nodeIdentifier) { + // 前提,存在 nodeIdentifier 一定是有 subName 的,不然前面会优化掉 + const ownerName = getDependencyIdentifier(info); + + chunks.push({ + type: ChunkType.STRING, + fileType: targetFileType, + name: COMMON_CHUNK_NAME.ImportAliasDefine, + content: useAliasName ? `const ${info.nodeIdentifier} = ${ownerName}.${info.subName};` : '', + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport], + ext: { + originalName: `${getDefaultExportName(info)}.${info.subName}`, + aliasName: info.nodeIdentifier, + dependency: info.source, + }, + }); + } else if (info.aliasName) { + // default 方式的导入会生成单独de import 语句,无需生成赋值语句 + if (info.isDefault && defaultExportNames.find((n) => n === info.aliasName)) { + delete aliasDefineStatements[info.aliasName]; + return; + } + + let contentStatement = ''; + if (aliasDefineStatements[info.aliasName]) { + contentStatement = aliasDefineStatements[info.aliasName]; + delete aliasDefineStatements[info.aliasName]; + } + + chunks.push({ + type: ChunkType.STRING, + fileType: targetFileType, + name: COMMON_CHUNK_NAME.ImportAliasDefine, + content: contentStatement, + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport], + ext: { + originalName: getDefaultExportName(info), + aliasName: info.aliasName, + dependency: info.source, + }, + }); + } + }); + + // 可能会剩余一些存在二次转换的定义 + Object.keys(aliasDefineStatements).forEach((a) => { + chunks.push({ + type: ChunkType.STRING, + fileType: targetFileType, + name: COMMON_CHUNK_NAME.ImportAliasDefine, + content: aliasDefineStatements[a], + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport], + }); + }); + + const exportItemList = Object.keys(exportItems).map((k) => exportItems[k]); + const defaultExport = exportItemList.filter((item) => item.isDefault); + const otherExports = exportItemList.filter((item) => !item.isDefault); + + const statementL = ['import']; + if (defaultExport.length > 0) { + if (useAliasName) { + statementL.push(defaultExportNames[0]); + } else { + statementL.push(defaultExport[0].aliasNames[0]); + } + if (otherExports.length > 0) { + statementL.push(', '); + } + } + if (otherExports.length > 0) { + const items = otherExports.map((item) => { + return !useAliasName || item.needOriginExport || item.aliasNames.length <= 0 + ? item.exportName + : `${item.exportName} as ${item.aliasNames[0]}`; + }); + statementL.push(`{ ${items.join(', ')} }`); + } + statementL.push('from'); + + const getInternalDependencyModuleId = () => `@/${(deps[0] as IInternalDependency).type}/${pkg}`; + + if (deps[0].dependencyType === DependencyType.Internal) { + // TODO: Internal Deps path use project slot setting + statementL.push(`'${getInternalDependencyModuleId()}';`); + chunks.push({ + type: ChunkType.STRING, + fileType: targetFileType, + name: COMMON_CHUNK_NAME.InternalDepsImport, + content: statementL.join(' '), + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport], + }); + } else { + statementL.push(`'${pkg}';`); + chunks.push({ + type: ChunkType.STRING, + fileType: targetFileType, + name: COMMON_CHUNK_NAME.ExternalDepsImport, + content: statementL.join(' '), + linkAfter: [], + }); + } + + // 处理下一些额外的 default 方式的导入 + if (defaultExportNames.length > 1) { + if (deps[0].dependencyType === DependencyType.Internal) { + defaultExportNames.slice(1).forEach((exportName) => { + chunks.push({ + type: ChunkType.STRING, + fileType: targetFileType, + name: COMMON_CHUNK_NAME.InternalDepsImport, + content: `import ${exportName} from '${getInternalDependencyModuleId()}';`, + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport], + }); + }); + } else { + defaultExportNames.slice(1).forEach((exportName) => { + chunks.push({ + type: ChunkType.STRING, + fileType: targetFileType, + name: COMMON_CHUNK_NAME.ExternalDepsImport, + content: `import ${exportName} from '${pkg}';`, + linkAfter: [], + }); + + chunks.push({ + type: ChunkType.STRING, + fileType: targetFileType, + name: COMMON_CHUNK_NAME.ImportAliasDefine, + content: '', + linkAfter: [], + ext: { + aliasName: exportName, + originalName: exportName, + dependency: { + package: pkg, + componentName: exportName, + }, + }, + }); + }); + } + } + + return chunks; +} + +export interface PluginConfig { + fileType?: string; // 导出的文件类型 + useAliasName?: boolean; // 是否使用 componentName 重命名组件 identifier + filter?: (deps: IDependency[]) => IDependency[]; // 支持过滤能力 +} + +const pluginFactory: BuilderComponentPluginFactory = (config?: PluginConfig) => { + const cfg = { + fileType: FileType.JS, + useAliasName: true, + ...(config || {}), + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IWithDependency; + + if (ir && ir.deps && ir.deps.length > 0) { + const deps = cfg.filter ? cfg.filter(ir.deps) : ir.deps; + const packs = groupDepsByPack(deps); + + Object.keys(packs).forEach((pkg) => { + const chunks = buildPackageImport(pkg, packs[pkg], cfg.fileType, cfg.useAliasName); + next.chunks.push(...chunks); + }); + } + + return next; + }; + + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/common/requireUtils.ts b/modules/code-generator/src/plugins/common/requireUtils.ts new file mode 100644 index 0000000..4dacf68 --- /dev/null +++ b/modules/code-generator/src/plugins/common/requireUtils.ts @@ -0,0 +1,25 @@ +import { COMMON_CHUNK_NAME } from '../../const/generator'; + +import { BuilderComponentPlugin, BuilderComponentPluginFactory, ChunkType, FileType, ICodeStruct } from '../../types'; + +// TODO: How to merge this logic to common deps +const pluginFactory: BuilderComponentPluginFactory = () => { + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: COMMON_CHUNK_NAME.InternalDepsImport, + content: 'import * from \'react\';', + linkAfter: [], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/common/styleImport.ts b/modules/code-generator/src/plugins/common/styleImport.ts new file mode 100644 index 0000000..23e1293 --- /dev/null +++ b/modules/code-generator/src/plugins/common/styleImport.ts @@ -0,0 +1,64 @@ +import changeCase from 'change-case'; +import { + FileType, + BuilderComponentPluginFactory, + BuilderComponentPlugin, + ICodeStruct, + IWithDependency, + ChunkType, +} from '../../types'; + +import { COMMON_CHUNK_NAME } from '../../const/generator'; + +const pluginFactory: BuilderComponentPluginFactory = () => { + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IWithDependency; + const { chunks } = next; + + if (ir && ir.deps && ir.deps.length > 0) { + let lowcodeMaterialsStyleAdded = false; + let fusionUIStyleAdded = false; + let nextStyleAddedMap: Record = {}; + ir.deps.forEach((dep: any) => { + if (dep.package === '@alifd/next' && !nextStyleAddedMap[dep.exportName]) { + chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: COMMON_CHUNK_NAME.InternalDepsImport, + content: `import '@alifd/next/lib/${changeCase.paramCase(dep.exportName)}/style';`, + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport], + }); + nextStyleAddedMap[dep.exportName] = true; + } else if (dep.package === '@alilc/lowcode-materials' && !lowcodeMaterialsStyleAdded) { + chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: COMMON_CHUNK_NAME.InternalDepsImport, + content: 'import \'@alilc/lowcode-materials/lib/style\';', + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport], + }); + lowcodeMaterialsStyleAdded = true; + } else if (dep.package === '@alifd/fusion-ui' && !fusionUIStyleAdded) { + chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: COMMON_CHUNK_NAME.InternalDepsImport, + content: 'import \'@alifd/fusion-ui/lib/style\';', + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport], + }); + fusionUIStyleAdded = true; + } + }); + } + + return next; + }; + + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/rax/commonDeps.ts b/modules/code-generator/src/plugins/component/rax/commonDeps.ts new file mode 100644 index 0000000..99285aa --- /dev/null +++ b/modules/code-generator/src/plugins/component/rax/commonDeps.ts @@ -0,0 +1,35 @@ +import { COMMON_CHUNK_NAME } from '../../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, +} from '../../../types'; + +const pluginFactory: BuilderComponentPluginFactory = () => { + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: COMMON_CHUNK_NAME.ExternalDepsImport, + content: ` + // 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。 + // 例外:rax 框架的导出名和各种组件名除外。 + import { createElement, Component } from 'rax'; + import { getSearchParams as __$$getSearchParams } from 'rax-app'; + `, + linkAfter: [], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/rax/const.ts b/modules/code-generator/src/plugins/component/rax/const.ts new file mode 100644 index 0000000..a0a07b5 --- /dev/null +++ b/modules/code-generator/src/plugins/component/rax/const.ts @@ -0,0 +1,18 @@ +export const RAX_CHUNK_NAME = { + ClassDidMountBegin: 'RaxComponentClassDidMountBegin', + ClassDidMountContent: 'RaxComponentClassDidMountContent', + ClassDidMountEnd: 'RaxComponentClassDidMountEnd', + ClassWillUnmountBegin: 'RaxComponentClassWillUnmountBegin', + ClassWillUnmountContent: 'RaxComponentClassWillUnmountContent', + ClassWillUnmountEnd: 'RaxComponentClassWillUnmountEnd', + ClassRenderBegin: 'RaxComponentClassRenderBegin', + ClassRenderPre: 'RaxComponentClassRenderPre', + ClassRenderJSX: 'RaxComponentClassRenderJSX', + ClassRenderEnd: 'RaxComponentClassRenderEnd', + MethodsBegin: 'RaxComponentMethodsBegin', + MethodsContent: 'RaxComponentMethodsContent', + MethodsEnd: 'RaxComponentMethodsEnd', + LifeCyclesBegin: 'RaxComponentLifeCyclesBegin', + LifeCyclesContent: 'RaxComponentLifeCyclesContent', + LifeCyclesEnd: 'RaxComponentLifeCyclesEnd', +}; diff --git a/modules/code-generator/src/plugins/component/rax/containerClass.ts b/modules/code-generator/src/plugins/component/rax/containerClass.ts new file mode 100644 index 0000000..5e92363 --- /dev/null +++ b/modules/code-generator/src/plugins/component/rax/containerClass.ts @@ -0,0 +1,157 @@ +import changeCase from 'change-case'; +import { + COMMON_CHUNK_NAME, + CLASS_DEFINE_CHUNK_NAME, + DEFAULT_LINK_AFTER, +} from '../../../const/generator'; +import { RAX_CHUNK_NAME } from './const'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IContainerInfo, +} from '../../../types'; +import { ensureValidClassName } from '../../../utils/validate'; + +const pluginFactory: BuilderComponentPluginFactory = () => { + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IContainerInfo; + + // 将模块名转换成 PascalCase 的格式,并添加特定后缀,防止命名冲突 + const componentClassName = ensureValidClassName( + `${changeCase.pascalCase(ir.moduleName)}$$Page`, + ); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: CLASS_DEFINE_CHUNK_NAME.Start, + content: `class ${componentClassName} extends Component {`, + linkAfter: [ + COMMON_CHUNK_NAME.ExternalDepsImport, + COMMON_CHUNK_NAME.InternalDepsImport, + COMMON_CHUNK_NAME.ImportAliasDefine, + COMMON_CHUNK_NAME.FileVarDefine, + COMMON_CHUNK_NAME.FileUtilDefine, + ], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: CLASS_DEFINE_CHUNK_NAME.End, + content: '}', + linkAfter: [ + CLASS_DEFINE_CHUNK_NAME.Start, + CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod, + RAX_CHUNK_NAME.ClassRenderEnd, + RAX_CHUNK_NAME.MethodsEnd, + ], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: CLASS_DEFINE_CHUNK_NAME.ConstructorStart, + content: 'constructor(props, context) { super(props); ', + linkAfter: DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorStart], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: CLASS_DEFINE_CHUNK_NAME.ConstructorEnd, + content: '} /* end of constructor */', + linkAfter: DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorEnd], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: RAX_CHUNK_NAME.ClassDidMountBegin, + content: 'componentDidMount() {', + linkAfter: [ + CLASS_DEFINE_CHUNK_NAME.Start, + CLASS_DEFINE_CHUNK_NAME.InsVar, + CLASS_DEFINE_CHUNK_NAME.InsMethod, + CLASS_DEFINE_CHUNK_NAME.ConstructorEnd, + ], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: RAX_CHUNK_NAME.ClassDidMountEnd, + content: '} /* end of componentDidMount */', + linkAfter: [RAX_CHUNK_NAME.ClassDidMountBegin, RAX_CHUNK_NAME.ClassDidMountContent], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: RAX_CHUNK_NAME.ClassWillUnmountBegin, + content: 'componentWillUnmount() {', + linkAfter: [ + CLASS_DEFINE_CHUNK_NAME.Start, + CLASS_DEFINE_CHUNK_NAME.InsVar, + CLASS_DEFINE_CHUNK_NAME.InsMethod, + RAX_CHUNK_NAME.ClassDidMountEnd, + ], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: RAX_CHUNK_NAME.ClassWillUnmountEnd, + content: '} /* end of componentWillUnmount */', + linkAfter: [RAX_CHUNK_NAME.ClassWillUnmountBegin, RAX_CHUNK_NAME.ClassWillUnmountContent], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: RAX_CHUNK_NAME.ClassRenderBegin, + content: 'render() {', + linkAfter: [RAX_CHUNK_NAME.ClassDidMountEnd, RAX_CHUNK_NAME.ClassWillUnmountEnd], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: RAX_CHUNK_NAME.ClassRenderEnd, + content: '} /* end of render */', + linkAfter: [ + RAX_CHUNK_NAME.ClassRenderBegin, + RAX_CHUNK_NAME.ClassRenderPre, + RAX_CHUNK_NAME.ClassRenderJSX, + ], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: COMMON_CHUNK_NAME.FileExport, + content: `export default ${componentClassName};`, + linkAfter: [ + COMMON_CHUNK_NAME.ExternalDepsImport, + COMMON_CHUNK_NAME.InternalDepsImport, + COMMON_CHUNK_NAME.ImportAliasDefine, + COMMON_CHUNK_NAME.FileVarDefine, + COMMON_CHUNK_NAME.FileUtilDefine, + CLASS_DEFINE_CHUNK_NAME.End, + ], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/rax/containerInitState.ts b/modules/code-generator/src/plugins/component/rax/containerInitState.ts new file mode 100644 index 0000000..bf37881 --- /dev/null +++ b/modules/code-generator/src/plugins/component/rax/containerInitState.ts @@ -0,0 +1,66 @@ +import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator'; + +import { generateCompositeType } from '../../../utils/compositeType'; +import { Scope } from '../../../utils/Scope'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IContainerInfo, +} from '../../../types'; + +export interface PluginConfig { + fileType: string; + implementType: 'inConstructor' | 'insMember' | 'hooks'; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg: PluginConfig = { + fileType: FileType.JSX, + implementType: 'insMember', + ...config, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IContainerInfo; + const scope = Scope.createRootScope(); + + const state = ir.state || {}; + const fields = Object.keys(state).map((stateName) => { + // TODO: 这里用什么 handlers? + const value = generateCompositeType(state[stateName], scope); + return `${JSON.stringify(stateName)}: ${value}`; + }); + + if (cfg.implementType === 'inConstructor') { + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent, + content: `this.state = { ${fields.join(',')} };`, + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorContent]], + }); + } else if (cfg.implementType === 'insMember') { + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsVar, + content: `state = { ${fields.join(',')} };`, + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsVar]], + }); + } + // TODO: hooks state?? + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/rax/containerInjectContext.ts b/modules/code-generator/src/plugins/component/rax/containerInjectContext.ts new file mode 100644 index 0000000..fed943a --- /dev/null +++ b/modules/code-generator/src/plugins/component/rax/containerInjectContext.ts @@ -0,0 +1,145 @@ +/* eslint-disable @typescript-eslint/indent */ +import { CLASS_DEFINE_CHUNK_NAME, COMMON_CHUNK_NAME } from '../../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IContainerInfo, +} from '../../../types'; +import { RAX_CHUNK_NAME } from './const'; +import { DEFAULT_LINK_AFTER } from '../../../const'; + +export interface PluginConfig { + fileType: string; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg: PluginConfig = { + fileType: FileType.JSX, + ...config, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IContainerInfo; + const useRef = !!ir.analyzeResult?.isUsingRef; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: COMMON_CHUNK_NAME.InternalDepsImport, + content: "import __$$constants from '../../constants';", + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport], + }); + + // TODO: i18n 是可选的,如果没有 i18n 这个文件怎么办?该怎么判断? + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: COMMON_CHUNK_NAME.InternalDepsImport, + content: "import * as __$$i18n from '../../i18n';", + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent, + content: ` + __$$i18n._inject2(this); + `, + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorContent]], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsVar, + content: ` + _context = this._createContext(); + `, + linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start], + }); + + // TODO: 按照目前的实现方案,代码的插拔能力太弱了,需要有一些变化。 + // Step 1: 增加前置的分析器 + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod, + content: ` + _createContext() { + const self = this; + const context = { + get state() { + return self.state; + }, + setState(newState, callback) { + self.setState(newState, callback); + }, + get dataSourceMap() { + return self._dataSourceEngine.dataSourceMap || {}; + }, + async reloadDataSource() { + await self._dataSourceEngine.reloadDataSource(); + }, + get utils() { + return self._utils; + }, + get page() { + return context; + }, + get component() { + return context; + }, + get props() { + return self.props; + }, + get constants() { + return __$$constants; + }, + i18n: __$$i18n.i18n, + i18nFormat: __$$i18n.i18nFormat, + getLocale: __$$i18n.getLocale, + setLocale(locale) { + __$$i18n.setLocale(locale); + self.forceUpdate(); + },${ + useRef + ? ` + $(refName) { + return self._refsManager.get(refName); + }, + $$(refName) { + return self._refsManager.getAll(refName); + }, + get _refsManager() { + if (!self._refsManager) { + self._refsManager = new RefsManager(); + } + return self._refsManager; + }, + ` + : '' + } + ...this._methods, + }; + + return context; + } + `, + linkAfter: [RAX_CHUNK_NAME.ClassRenderEnd], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/rax/containerInjectDataSourceEngine.ts b/modules/code-generator/src/plugins/component/rax/containerInjectDataSourceEngine.ts new file mode 100644 index 0000000..930a279 --- /dev/null +++ b/modules/code-generator/src/plugins/component/rax/containerInjectDataSourceEngine.ts @@ -0,0 +1,196 @@ +/* eslint-disable @typescript-eslint/indent */ + +import { + IPublicTypeCompositeValue, + IPublicTypeJSExpression, + InterpretDataSourceConfig, + isJSExpression, + isJSFunction, +} from '@felce/lowcode-types'; +import changeCase from 'change-case'; + +import { CLASS_DEFINE_CHUNK_NAME, COMMON_CHUNK_NAME } from '../../../const/generator'; +import { Scope } from '../../../utils/Scope'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IScope, +} from '../../../types'; + +import { generateCompositeType } from '../../../utils/compositeType'; +import { parseExpressionConvertThis2Context } from '../../../utils/expressionParser'; +import { isContainerSchema } from '../../../utils/schema'; +import { RaxFrameworkOptions } from '../../project/framework/rax/types/RaxFrameworkOptions'; +import { RAX_CHUNK_NAME } from './const'; + +export interface PluginConfig extends RaxFrameworkOptions { + fileType?: string; + + /** + * 数据源的 handlers 的映射配置 + * @deprecated 请使用 datasourceConfig.handlersPackages 来配置 + */ + dataSourceHandlersPackageMap?: Record; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg: PluginConfig = { + fileType: FileType.JSX, + ...config, + dataSourceHandlersPackageMap: + config?.dataSourceHandlersPackageMap || config?.datasourceConfig?.handlersPackages, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const scope = Scope.createRootScope(); + const dataSourceConfig = isContainerSchema(pre.ir) ? pre.ir.dataSource : null; + const dataSourceItems: InterpretDataSourceConfig[] = + (dataSourceConfig && dataSourceConfig.list) || []; + const dataSourceEngineOptions = { runtimeConfig: true }; + if (dataSourceItems.length > 0) { + const requestHandlersMap: Record = {}; + + dataSourceItems.forEach((ds) => { + const dsType = ds.type || 'fetch'; + if (!(dsType in requestHandlersMap) && dsType !== 'custom') { + const handlerFactoryName = `__$$create${changeCase.pascal(dsType)}RequestHandler`; + + requestHandlersMap[dsType] = { + type: 'JSExpression', + value: `${handlerFactoryName}(${ + dsType === 'urlParams' ? '__$$getSearchParams()' : '' + })`, + }; + + const handlerFactoryExportName = `create${changeCase.pascal(dsType)}Handler`; + const handlerPkgName = + cfg.dataSourceHandlersPackageMap?.[dsType] || + `@alilc/lowcode-datasource-${changeCase.kebab(dsType)}-handler`; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: COMMON_CHUNK_NAME.ExternalDepsImport, + content: ` + import { ${handlerFactoryExportName} as ${handlerFactoryName} } from '${handlerPkgName}'; + `, + linkAfter: [], + }); + } + }); + + Object.assign(dataSourceEngineOptions, { requestHandlersMap }); + } + + const datasourceEnginePackageName = + cfg.datasourceConfig?.enginePackage || '@alilc/lowcode-datasource-engine'; + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: COMMON_CHUNK_NAME.ExternalDepsImport, + content: ` + import { create as __$$createDataSourceEngine } from '${datasourceEnginePackageName}/runtime'; + `, + linkAfter: [], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType!, + name: CLASS_DEFINE_CHUNK_NAME.InsVar, + content: ` + _dataSourceConfig = this._defineDataSourceConfig(); + _dataSourceEngine = __$$createDataSourceEngine( + this._dataSourceConfig, + this._context, + ${generateCompositeType(dataSourceEngineOptions, scope)} + );`, + linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType!, + name: RAX_CHUNK_NAME.ClassDidMountContent, + content: ` + this._dataSourceEngine.reloadDataSource(); + `, + linkAfter: [RAX_CHUNK_NAME.ClassDidMountBegin], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType!, + name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod, + content: ` +_defineDataSourceConfig() { + const __$$context = this._context; + return (${generateCompositeType( + { + ...dataSourceConfig, + list: [ + ...dataSourceItems.map((item) => ({ + // 数据源引擎默认的 errorHandler 是空的,而且并不会触发组件重新渲染…… + // 这会导致页面状态不能正常展示,故这里处理下: + errorHandler: { + type: 'JSFunction', + value: `function (err){ + setTimeout(() => { + this.setState({ __refresh: Date.now() + Math.random() }); + }, 0); + throw err; + }`, + }, + ...item, + isInit: + typeof item.isInit === 'boolean' || typeof item.isInit === 'undefined' + ? (item.isInit ?? true) + : wrapAsFunction(item.isInit, scope), + options: wrapAsFunction(item.options, scope), + })), + ], + }, + scope, + { + handlers: { + function: (jsFunc) => parseExpressionConvertThis2Context(jsFunc.value, '__$$context'), + expression: (jsExpr) => parseExpressionConvertThis2Context(jsExpr.value, '__$$context'), + }, + }, + )}); +} + `, + linkAfter: [RAX_CHUNK_NAME.ClassRenderEnd], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; + +function wrapAsFunction( + value: IPublicTypeCompositeValue, + scope: IScope, +): IPublicTypeCompositeValue { + if (isJSExpression(value) || isJSFunction(value)) { + return { + type: 'JSExpression', + value: `function(){ return ((${value.value}))}`, + }; + } + + return { + type: 'JSExpression', + value: `function(){return((${generateCompositeType(value, scope)}))}`, + }; +} diff --git a/modules/code-generator/src/plugins/component/rax/containerInjectUtils.ts b/modules/code-generator/src/plugins/component/rax/containerInjectUtils.ts new file mode 100644 index 0000000..32d3f4b --- /dev/null +++ b/modules/code-generator/src/plugins/component/rax/containerInjectUtils.ts @@ -0,0 +1,69 @@ +import { CLASS_DEFINE_CHUNK_NAME, COMMON_CHUNK_NAME } from '../../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IContainerInfo, +} from '../../../types'; +import { RAX_CHUNK_NAME } from './const'; + +export interface PluginConfig { + fileType: string; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg: PluginConfig = { + fileType: FileType.JSX, + ...config, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IContainerInfo; + const useRef = !!ir.analyzeResult?.isUsingRef; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: COMMON_CHUNK_NAME.InternalDepsImport, + // TODO: 下面这个路径有没有更好的方式来获取?而非写死 + content: ` + import __$$projectUtils${useRef ? ', { RefsManager }' : ''} from '../../utils'; + `, + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsVar, + content: '_utils = this._defineUtils();', + linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod, + + content: ` + _defineUtils() { + return { + ...__$$projectUtils, + }; + }`, + linkAfter: [RAX_CHUNK_NAME.ClassRenderEnd], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/rax/containerLifeCycle.ts b/modules/code-generator/src/plugins/component/rax/containerLifeCycle.ts new file mode 100644 index 0000000..5db7224 --- /dev/null +++ b/modules/code-generator/src/plugins/component/rax/containerLifeCycle.ts @@ -0,0 +1,146 @@ +import _ from 'lodash'; +import { isJSExpression, isJSFunction } from '@felce/lowcode-types'; + +import { CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator'; +import { RAX_CHUNK_NAME } from './const'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + FileType, + ChunkType, + ICodeStruct, + IContainerInfo, +} from '../../../types'; +import { debug } from '../../../utils/debug'; +import { isJSExpressionFn } from '../../../utils/common'; + +export interface PluginConfig { + fileType: string; + exportNameMapping: Record; + normalizeNameMapping: Record; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg: PluginConfig = { + fileType: FileType.JSX, + exportNameMapping: {}, + normalizeNameMapping: { + didMount: 'componentDidMount', + willUnmount: 'componentWillUnmount', + }, + ...config, + }; + + const exportNameMapping = new Map(Object.entries(cfg.exportNameMapping)); + const normalizeNameMapping = new Map(Object.entries(cfg.normalizeNameMapping)); + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + // Rax 先只支持 didMount 和 willUnmount 吧 + + const ir = next.ir as IContainerInfo; + const { lifeCycles } = ir; + + if (lifeCycles && !_.isEmpty(lifeCycles)) { + Object.entries(lifeCycles).forEach(([lifeCycleName, lifeCycleMethodExpr]) => { + // 过滤掉非法数据(有些场景下会误传入空字符串或 null) + if ( + !isJSFunction(lifeCycles[lifeCycleName]) && + !isJSExpressionFn(lifeCycles[lifeCycleName]) && + !isJSExpression(lifeCycles[lifeCycleName]) + ) { + return; + } + + const normalizeName = normalizeNameMapping.get(lifeCycleName) || lifeCycleName; + const exportName = exportNameMapping.get(lifeCycleName) || lifeCycleName; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: RAX_CHUNK_NAME.LifeCyclesContent, + content: `${exportName}: (${lifeCycleMethodExpr.value}),`, + linkAfter: [RAX_CHUNK_NAME.LifeCyclesBegin], + }); + + if (normalizeName === 'constructor') { + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent, + content: `this._lifeCycles.${exportName}();`, + linkAfter: [CLASS_DEFINE_CHUNK_NAME.ConstructorStart], + }); + } else if (normalizeName === 'componentDidMount') { + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: RAX_CHUNK_NAME.ClassDidMountContent, + content: `this._lifeCycles.${exportName}();`, + linkAfter: [RAX_CHUNK_NAME.ClassDidMountBegin], + }); + } else if (normalizeName === 'componentWillUnmount') { + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: RAX_CHUNK_NAME.ClassWillUnmountContent, + content: `this._lifeCycles.${exportName}();`, + linkAfter: [RAX_CHUNK_NAME.ClassWillUnmountBegin], + }); + } else { + debug(`[CodeGen]: unknown life cycle: ${lifeCycleName}`); + } + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsVar, + content: '_lifeCycles = this._defineLifeCycles();', + linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: RAX_CHUNK_NAME.LifeCyclesBegin, + content: ` + _defineLifeCycles() { + const __$$lifeCycles = ({ + `, + linkAfter: [RAX_CHUNK_NAME.ClassRenderEnd, CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: RAX_CHUNK_NAME.LifeCyclesEnd, + content: ` + }); + + // 为所有的方法绑定上下文 + Object.entries(__$$lifeCycles).forEach(([lifeCycleName, lifeCycleMethod]) => { + if (typeof lifeCycleMethod === 'function') { + __$$lifeCycles[lifeCycleName] = (...args) => { + return lifeCycleMethod.apply(this._context, args); + } + } + }); + + return __$$lifeCycles; + } + `, + linkAfter: [RAX_CHUNK_NAME.LifeCyclesBegin, RAX_CHUNK_NAME.LifeCyclesContent], + }); + } + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/rax/containerMethods.ts b/modules/code-generator/src/plugins/component/rax/containerMethods.ts new file mode 100644 index 0000000..6e23dc0 --- /dev/null +++ b/modules/code-generator/src/plugins/component/rax/containerMethods.ts @@ -0,0 +1,84 @@ +import { CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IContainerInfo, +} from '../../../types'; + +import { RAX_CHUNK_NAME } from './const'; + +export interface PluginConfig { + fileType: string; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg: PluginConfig = { + fileType: FileType.JSX, + ...config, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IContainerInfo; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsVar, + content: ` + _methods = this._defineMethods(); + `, + linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: RAX_CHUNK_NAME.MethodsBegin, + content: ` + _defineMethods() { + return ({ + `, + linkAfter: [ + RAX_CHUNK_NAME.ClassRenderEnd, + CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod, + RAX_CHUNK_NAME.LifeCyclesEnd, + ], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: RAX_CHUNK_NAME.MethodsEnd, + content: ` + }); + } + `, + linkAfter: [RAX_CHUNK_NAME.MethodsBegin, RAX_CHUNK_NAME.MethodsContent], + }); + + if (ir.methods && Object.keys(ir.methods).length > 0) { + Object.entries(ir.methods).forEach(([methodName, methodDefine]) => { + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: RAX_CHUNK_NAME.MethodsContent, + content: `${methodName}: (${methodDefine.value}),`, + linkAfter: [RAX_CHUNK_NAME.MethodsBegin], + }); + }); + } + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/rax/jsx.ts b/modules/code-generator/src/plugins/component/rax/jsx.ts new file mode 100644 index 0000000..9b10669 --- /dev/null +++ b/modules/code-generator/src/plugins/component/rax/jsx.ts @@ -0,0 +1,327 @@ +import { + IPublicTypeNodeSchema, + IPublicTypeJSExpression, + IPublicTypeNpmInfo, + IPublicTypeCompositeValue, + isJSExpression, +} from '@felce/lowcode-types'; + +import _ from 'lodash'; +import changeCase from 'change-case'; +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + CodePiece, + FileType, + ICodeChunk, + ICodeStruct, + IContainerInfo, + PIECE_TYPE, + HandlerSet, + IScope, + NodeGeneratorConfig, + NodePlugin, + AttrPlugin, +} from '../../../types'; + +import { RAX_CHUNK_NAME } from './const'; +import { COMMON_CHUNK_NAME } from '../../../const/generator'; + +import { generateExpression } from '../../../utils/jsExpression'; +import { + createNodeGenerator, + generateConditionReactCtrl, + generateReactExprInJS, +} from '../../../utils/nodeToJSX'; +import { generateCompositeType } from '../../../utils/compositeType'; +import { Scope } from '../../../utils/Scope'; +import { parseExpressionGetGlobalVariables } from '../../../utils/expressionParser'; +import { transformThis2Context } from '../../../core/jsx/handlers/transformThis2Context'; +import { transformJsExpr } from '../../../core/jsx/handlers/transformJsExpression'; + +export interface PluginConfig { + fileType: string; + + /** 是否要忽略小程序 */ + ignoreMiniApp?: boolean; +} + +// TODO: componentName 若并非大写字符打头,甚至并非是一个有效的 JS 标识符怎么办?? +// FIXME: 我想了下,这块应该放到解析阶段就去做掉,对所有 componentName 做 identifier validate,然后对不合法的做统一替换。 +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg: PluginConfig = { + fileType: FileType.JSX, + ...config, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IContainerInfo; + const rootScope = Scope.createRootScope(); + const { tolerateEvalErrors = true, evalErrorsHandler = '' } = next.contextData; + + // Rax 构建到小程序的时候,不能给组件起起别名,得直接引用,故这里将所有的别名替换掉 + // 先收集下所有的 alias 的映射 + const componentsNameAliasMap = new Map(); + next.chunks.forEach((chunk) => { + if (isImportAliasDefineChunk(chunk)) { + componentsNameAliasMap.set(chunk.ext.aliasName, chunk.ext.originalName); + } + }); + + // 注意:这里其实隐含了一个假设:schema 中的 componentName 应该是一个有效的 JS 标识符,而且是大写字母打头的 + // FIXME: 为了快速修复临时加的逻辑,需要用 pre-process 的方式替代处理。 + const mapComponentNameToAliasOrKeepIt = (componentName: string) => + componentsNameAliasMap.get(componentName) || componentName; + + // 然后过滤掉所有的别名 chunks + next.chunks = next.chunks.filter((chunk) => !isImportAliasDefineChunk(chunk)); + + // 如果直接按目前的 React 的方式之间出码 JSX 的话,会有 3 个问题: + // 1. 小程序出码的时候,循环变量没法拿到 + // 2. 小程序出码的时候,很容易出现 Uncaught TypeError: Cannot read property 'avatar' of undefined 这样的异常(如下图的 50 行) -- 因为若直接出码,Rax 构建到小程序的时候会立即计算所有在视图中用到的变量 + // 3. 通过 this.xxx 能拿到的东西太多了,而且自定义的 methods 可能会无意间破坏 Rax 框架或小程序框架在页面 this 上的东东 + const customHandlers: HandlerSet = { + expression(input: IPublicTypeJSExpression, scope: IScope) { + return transformJsExpr(generateExpression(input, scope), scope, { + dontWrapEval: !tolerateEvalErrors, + }); + }, + function(input, scope: IScope) { + return transformThis2Context(input.value || 'null', scope); + }, + }; + + // 创建代码生成器 + const commonNodeGenerator = createNodeGenerator({ + handlers: customHandlers, + tagMapping: mapComponentNameToAliasOrKeepIt, + nodePlugins: [generateReactExprInJS, generateConditionReactCtrl, generateRaxLoopCtrl], + attrPlugins: [generateNodeAttrForRax.bind({ cfg })], + }); + + // 生成 JSX 代码 + const jsxContent = commonNodeGenerator(ir, rootScope); + + if (!cfg.ignoreMiniApp) { + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: COMMON_CHUNK_NAME.ExternalDepsImport, + content: "import { isMiniApp as __$$isMiniApp } from 'universal-env';", + linkAfter: [], + }); + } + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: RAX_CHUNK_NAME.ClassRenderPre, + // TODO: setState, dataSourceMap, reloadDataSource, utils, i18n, i18nFormat, getLocale, setLocale 这些在 Rax 的编译模式下不能在视图中直接访问,需要转化成 this.xxx + content: ` + const __$$context = this._context; + const { state, setState, dataSourceMap, reloadDataSource, utils, constants, i18n, i18nFormat, getLocale, setLocale } = __$$context; + `, + linkAfter: [RAX_CHUNK_NAME.ClassRenderBegin], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: RAX_CHUNK_NAME.ClassRenderJSX, + content: `return ${jsxContent};`, + linkAfter: [RAX_CHUNK_NAME.ClassRenderBegin, RAX_CHUNK_NAME.ClassRenderPre], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: COMMON_CHUNK_NAME.CustomContent, + content: [ + tolerateEvalErrors && + ` + function __$$eval(expr) { + try { + return expr(); + } catch (error) { + ${evalErrorsHandler} + } + } + + function __$$evalArray(expr) { + const res = __$$eval(expr); + return Array.isArray(res) ? res : []; + } + `, + ` + function __$$createChildContext(oldContext, ext) { + return Object.assign({}, oldContext, ext); + } + `, + ] + .filter(Boolean) + .join('\n'), + linkAfter: [COMMON_CHUNK_NAME.FileExport], + }); + + return next; + + function generateRaxLoopCtrl( + nodeItem: IPublicTypeNodeSchema, + scope: IScope, + config?: NodeGeneratorConfig, + next?: NodePlugin, + ): CodePiece[] { + if (nodeItem.loop) { + const loopItemName = nodeItem.loopArgs?.[0] || 'item'; + const loopIndexName = nodeItem.loopArgs?.[1] || 'index'; + const subScope = scope.createSubScope([loopItemName, loopIndexName]); + const pieces: CodePiece[] = next ? next(nodeItem, subScope, config) : []; + + const loopDataExpr = tolerateEvalErrors + ? `__$$evalArray(() => (${transformThis2Context( + generateCompositeType(nodeItem.loop, scope, { handlers: config?.handlers }), + scope, + )}))` + : `(${transformThis2Context( + generateCompositeType(nodeItem.loop, scope, { handlers: config?.handlers }), + scope, + )})`; + + pieces.unshift({ + value: `${loopDataExpr}.map((${loopItemName}, ${loopIndexName}) => ((__$$context) => (`, + type: PIECE_TYPE.BEFORE, + }); + + pieces.push({ + value: `))(__$$createChildContext(__$$context, { ${loopItemName}, ${loopIndexName} })))`, + type: PIECE_TYPE.AFTER, + }); + + return pieces; + } + + return next ? next(nodeItem, scope, config) : []; + } + }; + + return plugin; +}; + +export default pluginFactory; + +function isImportAliasDefineChunk(chunk: ICodeChunk): chunk is ICodeChunk & { + ext: { + aliasName: string; + originalName: string; + dependency: IPublicTypeNpmInfo; + }; +} { + return ( + chunk.name === COMMON_CHUNK_NAME.ImportAliasDefine && + !!chunk.ext && + typeof chunk.ext.aliasName === 'string' && + typeof chunk.ext.originalName === 'string' && + !!(chunk.ext.dependency as IPublicTypeNpmInfo | null)?.componentName + ); +} + +function generateNodeAttrForRax( + this: { cfg: PluginConfig }, + attrData: { attrName: string; attrValue: IPublicTypeCompositeValue }, + scope: IScope, + config?: NodeGeneratorConfig, + next?: AttrPlugin, +): CodePiece[] { + if (!this.cfg.ignoreMiniApp && /^on/.test(attrData.attrName)) { + // else: onXxx 的都是事件处理函数需要特殊处理下 + return generateEventHandlerAttrForRax(attrData.attrName, attrData.attrValue, scope, config); + } + + if (attrData.attrName === 'ref') { + return [ + { + name: attrData.attrName, + value: `__$$context._refsManager.linkRef('${attrData.attrValue}')`, + type: PIECE_TYPE.ATTR, + }, + ]; + } + + return next ? next(attrData, scope, config) : []; +} + +function generateEventHandlerAttrForRax( + attrName: string, + attrValue: IPublicTypeCompositeValue, + scope: IScope, + config?: NodeGeneratorConfig, +): CodePiece[] { + // -- 事件处理函数中 JSExpression 转成 JSFunction 来处理,避免当 JSExpression 处理的时候多包一层 eval 而导致 Rax 转码成小程序的时候出问题 + const valueExpr = generateCompositeType( + isJSExpression(attrValue) ? { type: 'JSFunction', value: attrValue.value } : attrValue, + scope, + { + handlers: config?.handlers, + }, + ); + + // 查询当前作用域下的变量 + const currentScopeVariables = scope.bindings?.getAllBindings() || []; + if (currentScopeVariables.length <= 0) { + return [ + { + type: PIECE_TYPE.ATTR, + name: attrName, + value: valueExpr, + }, + ]; + } + + // 提取出所有的未定义的全局变量 + const undeclaredVariablesInValueExpr = parseExpressionGetGlobalVariables(valueExpr); + const referencedLocalVariables = _.intersection( + undeclaredVariablesInValueExpr, + currentScopeVariables, + ); + if (referencedLocalVariables.length <= 0) { + return [ + { + type: PIECE_TYPE.ATTR, + name: attrName, + value: valueExpr, + }, + ]; + } + + const wrappedAttrValueExpr = [ + '(...__$$args) => {', + ' if (__$$isMiniApp) {', + ' const __$$event = __$$args[0];', + ...referencedLocalVariables.map( + (localVar) => `const ${localVar} = __$$event.target.dataset.${localVar};`, + ), + ` return (${valueExpr}).apply(this, __$$args);`, + ' } else {', + ` return (${valueExpr}).apply(this, __$$args);`, + ' }', + '}', + ].join('\n'); + + return [ + ...referencedLocalVariables.map((localVar) => ({ + type: PIECE_TYPE.ATTR, + name: `data-${changeCase.snake(localVar)}`, + value: localVar, + })), + { + type: PIECE_TYPE.ATTR, + name: attrName, + value: wrappedAttrValueExpr, + }, + ]; +} diff --git a/modules/code-generator/src/plugins/component/react/const.ts b/modules/code-generator/src/plugins/component/react/const.ts new file mode 100644 index 0000000..6294668 --- /dev/null +++ b/modules/code-generator/src/plugins/component/react/const.ts @@ -0,0 +1,9 @@ +export const REACT_CHUNK_NAME = { + ClassRenderStart: 'ReactComponentClassRenderStart', + ClassRenderPre: 'ReactComponentClassRenderPre', + ClassRenderEnd: 'ReactComponentClassRenderEnd', + ClassRenderJSX: 'ReactComponentClassRenderJSX', + ClassDidMountStart: 'ReactComponentClassDidMountStart', + ClassDidMountEnd: 'ReactComponentClassDidMountEnd', + ClassDidMountContent: 'ReactComponentClassDidMountContent', +}; diff --git a/modules/code-generator/src/plugins/component/react/containerClass.ts b/modules/code-generator/src/plugins/component/react/containerClass.ts new file mode 100644 index 0000000..eab6cbe --- /dev/null +++ b/modules/code-generator/src/plugins/component/react/containerClass.ts @@ -0,0 +1,145 @@ +import changeCase from 'change-case'; +import { + COMMON_CHUNK_NAME, + CLASS_DEFINE_CHUNK_NAME, + DEFAULT_LINK_AFTER, +} from '../../../const/generator'; +import { REACT_CHUNK_NAME } from './const'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IContainerInfo, +} from '../../../types'; +import { ensureValidClassName } from '../../../utils/validate'; + +const pluginFactory: BuilderComponentPluginFactory = () => { + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IContainerInfo; + + // 将模块名转换成 PascalCase 的格式,并添加特定后缀,防止命名冲突 + const componentClassName = ensureValidClassName( + `${changeCase.pascalCase(ir.moduleName)}$$${ir.containerType}`, + ); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: CLASS_DEFINE_CHUNK_NAME.Start, + content: `class ${componentClassName} extends React.Component {`, + linkAfter: [ + COMMON_CHUNK_NAME.ExternalDepsImport, + COMMON_CHUNK_NAME.InternalDepsImport, + COMMON_CHUNK_NAME.ImportAliasDefine, + COMMON_CHUNK_NAME.FileVarDefine, + COMMON_CHUNK_NAME.FileUtilDefine, + ], + }); + + if (ir.containerType === 'Component') { + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: CLASS_DEFINE_CHUNK_NAME.InsVar, + content: `static displayName = '${ir.moduleName}';`, + linkAfter: [ + CLASS_DEFINE_CHUNK_NAME.Start, + ], + }); + } + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: CLASS_DEFINE_CHUNK_NAME.End, + content: '}', + linkAfter: [ + ...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.End], + REACT_CHUNK_NAME.ClassRenderEnd, + REACT_CHUNK_NAME.ClassDidMountEnd, + ], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: CLASS_DEFINE_CHUNK_NAME.ConstructorStart, + content: 'constructor(props, context) { super(props); ', + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorStart]], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: CLASS_DEFINE_CHUNK_NAME.ConstructorEnd, + content: '}', + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorEnd]], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: REACT_CHUNK_NAME.ClassDidMountStart, + content: 'componentDidMount() {', + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.End]], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: REACT_CHUNK_NAME.ClassDidMountEnd, + content: '}', + linkAfter: [REACT_CHUNK_NAME.ClassDidMountContent, REACT_CHUNK_NAME.ClassDidMountStart], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: REACT_CHUNK_NAME.ClassRenderStart, + content: 'render() {', + linkAfter: [ + ...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.End], + REACT_CHUNK_NAME.ClassDidMountEnd, + ], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: REACT_CHUNK_NAME.ClassRenderEnd, + content: '}', + linkAfter: [ + REACT_CHUNK_NAME.ClassRenderStart, + REACT_CHUNK_NAME.ClassRenderPre, + REACT_CHUNK_NAME.ClassRenderJSX, + ], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: COMMON_CHUNK_NAME.FileExport, + content: `export default ${componentClassName};`, + linkAfter: [ + COMMON_CHUNK_NAME.ExternalDepsImport, + COMMON_CHUNK_NAME.InternalDepsImport, + COMMON_CHUNK_NAME.ImportAliasDefine, + COMMON_CHUNK_NAME.FileVarDefine, + COMMON_CHUNK_NAME.FileUtilDefine, + CLASS_DEFINE_CHUNK_NAME.End, + ], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/react/containerInitState.ts b/modules/code-generator/src/plugins/component/react/containerInitState.ts new file mode 100644 index 0000000..d1dd0d1 --- /dev/null +++ b/modules/code-generator/src/plugins/component/react/containerInitState.ts @@ -0,0 +1,63 @@ +import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator'; + +import { generateCompositeType } from '../../../utils/compositeType'; +import { Scope } from '../../../utils/Scope'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IContainerInfo, +} from '../../../types'; + +export interface PluginConfig { + fileType?: string; + implementType: 'inConstructor' | 'insMember' | 'hooks'; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg: PluginConfig & { fileType: string } = { + fileType: FileType.JSX, + implementType: 'inConstructor', + ...config, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IContainerInfo; + const scope = Scope.createRootScope(); + + const state = ir.state || {}; + const fields = Object.keys(state).map((stateName) => { + const value = generateCompositeType(state[stateName], scope); + return `${stateName}: ${value},`; + }); + + if (cfg.implementType === 'inConstructor') { + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent, + content: `this.state = { ${fields.join('')} };`, + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorContent]], + }); + } else if (cfg.implementType === 'insMember') { + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsVar, + content: `state = { ${fields.join('')} };`, + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsVar]], + }); + } + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/react/containerInjectConstants.ts b/modules/code-generator/src/plugins/component/react/containerInjectConstants.ts new file mode 100644 index 0000000..92cd4a3 --- /dev/null +++ b/modules/code-generator/src/plugins/component/react/containerInjectConstants.ts @@ -0,0 +1,55 @@ +import { + CLASS_DEFINE_CHUNK_NAME, + COMMON_CHUNK_NAME, + DEFAULT_LINK_AFTER, +} from '../../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, +} from '../../../types'; + +export interface PluginConfig { + fileType: string; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg: PluginConfig = { + fileType: FileType.JSX, + ...config, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: COMMON_CHUNK_NAME.InternalDepsImport, + content: "import __$$constants from '../../constants';", + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsVar, + content: ` + get constants() { + return __$$constants || {}; + } + `, + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsVar]], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/react/containerInjectContext.ts b/modules/code-generator/src/plugins/component/react/containerInjectContext.ts new file mode 100644 index 0000000..434a5cf --- /dev/null +++ b/modules/code-generator/src/plugins/component/react/containerInjectContext.ts @@ -0,0 +1,91 @@ +import { CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator'; + +import { Scope } from '../../../utils/Scope'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IContainerInfo, +} from '../../../types'; +import { DEFAULT_LINK_AFTER } from '../../../const'; + +export interface PluginConfig { + fileType: string; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg: PluginConfig = { + fileType: FileType.JSX, + ...config, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IContainerInfo; + const scope = Scope.createRootScope(); + + const { inStrictMode } = next.contextData; + if (!inStrictMode) { + // 非严格模式下,上下文就是自己 + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsVar, + content: ` + _context = this; + `, + linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start], + }); + } else { + // 严格模式下的上下文只保留协议中规定的那些 + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsVar, + content: ` + _context = this._createContext(); + `, + linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod, + content: ` + _createContext() { + const self = this; + const context = { + get state() { return self.state; }, + setState(newState, callback) { self.setState(newState, callback); }, + get dataSourceMap() { return self._dataSourceEngine.dataSourceMap || {}; }, + async reloadDataSource() { await self._dataSourceEngine.reloadDataSource(); }, + get utils() { return self.utils; }, + get page() { return context; }, + get component() { return context; }, + get props() { return self.props; }, + get constants() { return self.constants; }, + get $() { return self.$ }, + get $$() { return self.$$ }, + ...this._methods, + }; + + return context; + } + `, + linkAfter: DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod], + }); + } + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/react/containerInjectDataSourceEngine.ts b/modules/code-generator/src/plugins/component/react/containerInjectDataSourceEngine.ts new file mode 100644 index 0000000..ac7aa72 --- /dev/null +++ b/modules/code-generator/src/plugins/component/react/containerInjectDataSourceEngine.ts @@ -0,0 +1,206 @@ +/* eslint-disable @typescript-eslint/indent */ + +import { + IPublicTypeCompositeValue, + IPublicTypeJSExpression, + InterpretDataSourceConfig, + isJSExpression, + isJSFunction, +} from '@felce/lowcode-types'; +import changeCase from 'change-case'; + +import { + CLASS_DEFINE_CHUNK_NAME, + COMMON_CHUNK_NAME, + DEFAULT_LINK_AFTER, +} from '../../../const/generator'; +import { Scope } from '../../../utils/Scope'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IScope, +} from '../../../types'; + +import { generateCompositeType } from '../../../utils/compositeType'; +import { parseExpressionConvertThis2Context } from '../../../utils/expressionParser'; +import { isValidContainerType } from '../../../utils/schema'; +import { REACT_CHUNK_NAME } from './const'; +import { isJSExpressionFn } from '../../../utils/common'; + +export interface PluginConfig { + fileType?: string; + + /** + * 数据源配置 + */ + datasourceConfig?: { + /** 数据源引擎的版本 */ + engineVersion?: string; + + /** 数据源引擎的包名 */ + enginePackage?: string; + + /** 数据源 handlers 的版本 */ + handlersVersion?: { + [key: string]: string; + }; + + /** 数据源 handlers 的包名 */ + handlersPackages?: { + [key: string]: string; + }; + }; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg = { + ...config, + fileType: config?.fileType || FileType.JSX, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const scope = Scope.createRootScope(); + const dataSourceConfig = isValidContainerType(pre.ir) ? pre.ir.dataSource : null; + const dataSourceItems: InterpretDataSourceConfig[] = + (dataSourceConfig && dataSourceConfig.list) || []; + const dataSourceEngineOptions = { runtimeConfig: true }; + if (dataSourceItems.length > 0) { + const requestHandlersMap: Record = {}; + + dataSourceItems.forEach((ds) => { + const dsType = ds.type || 'fetch'; + if (!(dsType in requestHandlersMap) && dsType !== 'custom') { + const handlerFactoryName = `__$$create${changeCase.pascal(dsType)}RequestHandler`; + + requestHandlersMap[dsType] = { + type: 'JSExpression', + value: + handlerFactoryName + (dsType === 'urlParams' ? '(window.location.search)' : '()'), + }; + + const handlerFactoryExportName = `create${changeCase.pascal(dsType)}Handler`; + const handlerPkgName = + cfg.datasourceConfig?.handlersPackages?.[dsType] || + `@alilc/lowcode-datasource-${changeCase.kebab(dsType)}-handler`; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: COMMON_CHUNK_NAME.ExternalDepsImport, + content: ` + import { ${handlerFactoryExportName} as ${handlerFactoryName} } from '${handlerPkgName}'; + `, + linkAfter: [], + }); + } + }); + + Object.assign(dataSourceEngineOptions, { requestHandlersMap }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: COMMON_CHUNK_NAME.ExternalDepsImport, + content: ` + import { create as __$$createDataSourceEngine } from '@alilc/lowcode-datasource-engine/runtime'; + `, + linkAfter: [], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsVar, + content: ` + _dataSourceConfig = this._defineDataSourceConfig(); + _dataSourceEngine = __$$createDataSourceEngine( + this._dataSourceConfig, + this, + ${generateCompositeType(dataSourceEngineOptions, scope)} + ); + + get dataSourceMap() { + return this._dataSourceEngine.dataSourceMap || {}; + } + + reloadDataSource = async () => { + await this._dataSourceEngine.reloadDataSource(); + } + + `, + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsVar]], + }); + + next.chunks.unshift({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: REACT_CHUNK_NAME.ClassDidMountContent, + content: ` + this._dataSourceEngine.reloadDataSource(); + `, + linkAfter: [REACT_CHUNK_NAME.ClassDidMountStart], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsMethod, + content: ` + _defineDataSourceConfig() { + const _this = this; + return (${generateCompositeType( + { + ...dataSourceConfig, + list: [ + ...dataSourceItems.map((item) => ({ + ...item, + isInit: wrapAsFunction(item.isInit, scope), + options: wrapAsFunction(item.options, scope), + })), + ], + }, + scope, + { + handlers: { + function: (jsFunc) => parseExpressionConvertThis2Context(jsFunc.value, '_this'), + expression: (jsExpr) => parseExpressionConvertThis2Context(jsExpr.value, '_this'), + }, + }, + )}); + } + `, + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]], + }); + } + + return next; + }; + return plugin; +}; + +export default pluginFactory; + +function wrapAsFunction( + value: IPublicTypeCompositeValue, + scope: IScope, +): IPublicTypeCompositeValue { + if (isJSExpression(value) || isJSFunction(value) || isJSExpressionFn(value)) { + return { + type: 'JSExpression', + value: `function(){ return ((${value.value}))}.bind(this)`, + }; + } + + return { + type: 'JSExpression', + value: `function(){return((${generateCompositeType(value, scope)}))}.bind(this)`, + }; +} diff --git a/modules/code-generator/src/plugins/component/react/containerInjectI18n.ts b/modules/code-generator/src/plugins/component/react/containerInjectI18n.ts new file mode 100644 index 0000000..aff42af --- /dev/null +++ b/modules/code-generator/src/plugins/component/react/containerInjectI18n.ts @@ -0,0 +1,56 @@ +import { + CLASS_DEFINE_CHUNK_NAME, + COMMON_CHUNK_NAME, + DEFAULT_LINK_AFTER, +} from '../../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, +} from '../../../types'; +import { getSlotRelativePath } from '../../../utils/pathHelper'; + +export interface PluginConfig { + fileType: string; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg: PluginConfig = { + fileType: FileType.JSX, + ...config, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: COMMON_CHUNK_NAME.InternalDepsImport, + content: ` + import * as __$$i18n from '${getSlotRelativePath({ contextData: next.contextData, from: 'components', to: 'i18n' })}'; + `, + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent, + content: ` + __$$i18n._inject2(this); + `, + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorContent]], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/react/containerInjectUtils.ts b/modules/code-generator/src/plugins/component/react/containerInjectUtils.ts new file mode 100644 index 0000000..d9eb14f --- /dev/null +++ b/modules/code-generator/src/plugins/component/react/containerInjectUtils.ts @@ -0,0 +1,125 @@ +import { + CLASS_DEFINE_CHUNK_NAME, + COMMON_CHUNK_NAME, + DEFAULT_LINK_AFTER, +} from '../../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IContainerInfo, +} from '../../../types'; +import { getSlotRelativePath } from '../../../utils/pathHelper'; + +export interface PluginConfig { + fileType?: string; + + /** prefer using class property to define utils */ + preferClassProperty?: boolean; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg: PluginConfig & { fileType: string } = { + fileType: FileType.JSX, + ...config, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IContainerInfo; + next.contextData.useRefApi = true; + const useRef = !!ir.analyzeResult?.isUsingRef; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: COMMON_CHUNK_NAME.InternalDepsImport, + content: ` + import utils${useRef ? ', { RefsManager }' : ''} from '${getSlotRelativePath({ contextData: next.contextData, from: 'components', to: 'utils' })}'; + `, + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport], + }); + + if (cfg.preferClassProperty) { + // mode: class property + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsVar, + content: 'utils = utils;', + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsVar]], + }); + } else { + // mode: assign in constructor + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent, + content: 'this.utils = utils;', + linkAfter: [CLASS_DEFINE_CHUNK_NAME.ConstructorStart], + }); + } + + if (useRef) { + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent, + content: 'this._refsManager = new RefsManager();', + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorContent]], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsMethod, + content: ` + $ = (refName) => { + return this._refsManager.get(refName); + } + `, + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsMethod, + content: ` + $$ = (refName) => { + return this._refsManager.getAll(refName); + } + `, + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]], + }); + } else { + // useRef 为 false 的时候是指没有组件在 props 中配置 ref 属性,但这个时候其实也可能有代码访问 this.$/$$ 所以还是加上个空的代码 + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsMethod, + content: ' $ = () => null; ', + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsMethod, + content: ' $$ = () => []; ', + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]], + }); + } + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/react/containerLifeCycle.ts b/modules/code-generator/src/plugins/component/react/containerLifeCycle.ts new file mode 100644 index 0000000..ec4c46e --- /dev/null +++ b/modules/code-generator/src/plugins/component/react/containerLifeCycle.ts @@ -0,0 +1,117 @@ +import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator'; +import { REACT_CHUNK_NAME } from './const'; + +import { generateFunction } from '../../../utils/jsExpression'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeChunk, + ICodeStruct, + IContainerInfo, +} from '../../../types'; +import { isJSFunction, isJSExpression } from '@felce/lowcode-types'; +import { isJSExpressionFn } from '../../../utils/common'; + +export interface PluginConfig { + fileType?: string; + exportNameMapping?: Record; + normalizeNameMapping?: Record; + exclude?: string[]; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg = { + fileType: FileType.JSX, + exportNameMapping: {}, + normalizeNameMapping: {}, + ...config, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IContainerInfo; + + if (ir.lifeCycles) { + const { lifeCycles } = ir; + const chunks = Object.keys(lifeCycles) + .map((lifeCycleName) => { + // 过滤掉非法数据(有些场景下会误传入空字符串或 null) + if ( + !isJSFunction(lifeCycles[lifeCycleName]) && + !isJSExpressionFn(lifeCycles[lifeCycleName]) && + !isJSExpression(lifeCycles[lifeCycleName]) + ) { + return null; + } + + let normalizeName; + // constructor会取到对象的构造函数 + if (lifeCycleName === 'constructor') { + normalizeName = lifeCycleName; + } else { + normalizeName = cfg.normalizeNameMapping[lifeCycleName] || lifeCycleName; + } + + if (cfg?.exclude?.includes(normalizeName)) { + return null; + } + + const exportName = cfg.exportNameMapping[lifeCycleName] || lifeCycleName; + if (normalizeName === 'constructor') { + return { + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent, + content: generateFunction(lifeCycles[lifeCycleName], { isBlock: true }), + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorStart]], + }; + } + + if (normalizeName === 'componentDidMount') { + return { + type: ChunkType.STRING, + fileType: cfg.fileType, + name: REACT_CHUNK_NAME.ClassDidMountContent, + content: generateFunction(lifeCycles[lifeCycleName], { isBlock: true }), + linkAfter: [REACT_CHUNK_NAME.ClassDidMountStart], + }; + } + + if (normalizeName === 'render') { + return { + type: ChunkType.STRING, + fileType: cfg.fileType, + name: REACT_CHUNK_NAME.ClassRenderPre, + content: generateFunction(lifeCycles[lifeCycleName], { isBlock: true }), + linkAfter: [REACT_CHUNK_NAME.ClassRenderStart], + }; + } + + return { + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsMethod, + content: generateFunction(lifeCycles[lifeCycleName], { + name: exportName, + isMember: true, + }), + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]], + }; + }) + .filter((i) => !!i); + + next.chunks.push(...chunks.filter((x): x is ICodeChunk => x !== null)); + } + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/react/containerMethod.ts b/modules/code-generator/src/plugins/component/react/containerMethod.ts new file mode 100644 index 0000000..fc4a387 --- /dev/null +++ b/modules/code-generator/src/plugins/component/react/containerMethod.ts @@ -0,0 +1,70 @@ +import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator'; + +import { generateFunction } from '../../../utils/jsExpression'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeChunk, + ICodeStruct, + IContainerInfo, +} from '../../../types'; +import { isValidIdentifier } from '../../../utils/validate'; + +export interface PluginConfig { + fileType: string; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg: PluginConfig = { + fileType: FileType.JSX, + ...config, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IContainerInfo; + const { inStrictMode } = next.contextData; + + if (!ir.methods) { + return next; + } + + // 将这些 methods 都定义到 class 上 + const { methods } = ir; + const chunks = Object.keys(methods).map((methodName) => ({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsMethod, + content: generateFunction(methods[methodName], { name: methodName, isMember: true }), + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]], + })); + next.chunks.push(...chunks); + + // 严格模式下需要将这些方法都挂到上下文中 + if (inStrictMode) { + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent, + content: Object.keys(ir.methods) + .map((methodName) => + isValidIdentifier(methodName) ? `.${methodName}` : `[${JSON.stringify(methodName)}]`, + ) + .map((method) => `this._context${method} = this${method};`) + .join('\n'), + linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorContent]], + }); + } + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/react/jsx.ts b/modules/code-generator/src/plugins/component/react/jsx.ts new file mode 100644 index 0000000..f8a46c4 --- /dev/null +++ b/modules/code-generator/src/plugins/component/react/jsx.ts @@ -0,0 +1,153 @@ +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + HandlerSet, + ICodeStruct, + IContainerInfo, + IScope, + NodeGeneratorConfig, + PIECE_TYPE, +} from '../../../types'; + +import { REACT_CHUNK_NAME } from './const'; +import { COMMON_CHUNK_NAME } from '../../../const/generator'; + +import { createReactNodeGenerator } from '../../../utils/nodeToJSX'; +import { Scope } from '../../../utils/Scope'; +import { IPublicTypeJSExpression } from '@felce/lowcode-types'; +import { generateExpression } from '../../../utils/jsExpression'; +import { transformJsExpr } from '../../../core/jsx/handlers/transformJsExpression'; +import { transformThis2Context } from '../../../core/jsx/handlers/transformThis2Context'; +import { generateCompositeType } from '../../../utils/compositeType'; + +export interface PluginConfig { + fileType?: string; + nodeTypeMapping?: Record; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg = { + fileType: FileType.JSX, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + nodeTypeMapping: {} as Record, + ...config, + }; + + const { nodeTypeMapping } = cfg; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const { tolerateEvalErrors = true, evalErrorsHandler = '' } = next.contextData; + + // 这里会将内部的一些子上下文的访问(this.xxx)转换为 __$$context.xxx 的形式 + // 与 Rax 所不同的是,这里不会将最顶层的 this 转换掉 + const customHandlers: HandlerSet = { + expression(input: IPublicTypeJSExpression, scope: IScope, config) { + return transformJsExpr(generateExpression(input, scope), scope, { + dontWrapEval: !(config?.tolerateEvalErrors ?? tolerateEvalErrors), + dontTransformThis2ContextAtRootScope: true, + }); + }, + function(input, scope: IScope) { + return transformThis2Context( + generateCompositeType( + { + type: 'JSFunction', + value: input.value || 'function () {}', + }, + Scope.createRootScope(), + ), + scope, + { ignoreRootScope: true }, + ); + }, + }; + + const generatorPlugins: NodeGeneratorConfig = { + handlers: customHandlers, + tagMapping: (v) => nodeTypeMapping[v] || v, + tolerateEvalErrors, + }; + + if (next.contextData.useRefApi) { + generatorPlugins.attrPlugins = [ + (attrData, scope, pluginCfg, nextFunc) => { + if (attrData.attrName === 'ref') { + return [ + { + name: attrData.attrName, + value: `this._refsManager.linkRef('${attrData.attrValue}')`, + type: PIECE_TYPE.ATTR, + }, + ]; + } + + return nextFunc ? nextFunc(attrData, scope, pluginCfg) : []; + }, + ]; + } + + const generator = createReactNodeGenerator(generatorPlugins); + + const ir = next.ir as IContainerInfo; + const scope: IScope = Scope.createRootScope(); + const jsxContent = generator(ir, scope); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: REACT_CHUNK_NAME.ClassRenderJSX, + content: ` + const __$$context = this._context || this; + const { state } = __$$context; + return ${jsxContent}; + `, + linkAfter: [REACT_CHUNK_NAME.ClassRenderStart, REACT_CHUNK_NAME.ClassRenderPre], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: COMMON_CHUNK_NAME.CustomContent, + content: [ + tolerateEvalErrors && + ` + function __$$eval(expr) { + try { + return expr(); + } catch (error) { + ${evalErrorsHandler} + } + } + + function __$$evalArray(expr) { + const res = __$$eval(expr); + return Array.isArray(res) ? res : []; + } + `, + ` + function __$$createChildContext(oldContext, ext) { + const childContext = { + ...oldContext, + ...ext, + }; + childContext.__proto__ = oldContext; + return childContext; + } + `, + ] + .filter(Boolean) + .join('\n'), + linkAfter: [COMMON_CHUNK_NAME.FileExport], + }); + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/react/reactCommonDeps.ts b/modules/code-generator/src/plugins/component/react/reactCommonDeps.ts new file mode 100644 index 0000000..f42aaf6 --- /dev/null +++ b/modules/code-generator/src/plugins/component/react/reactCommonDeps.ts @@ -0,0 +1,33 @@ +import { COMMON_CHUNK_NAME } from '../../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, +} from '../../../types'; + +const pluginFactory: BuilderComponentPluginFactory = () => { + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: COMMON_CHUNK_NAME.ExternalDepsImport, + content: ` +// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。 +// 例外:react 框架的导出名和各种组件名除外。 +import React from \'react\';`, + linkAfter: [], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/component/style/css.ts b/modules/code-generator/src/plugins/component/style/css.ts new file mode 100644 index 0000000..4ef94fd --- /dev/null +++ b/modules/code-generator/src/plugins/component/style/css.ts @@ -0,0 +1,52 @@ +import { COMMON_CHUNK_NAME } from '../../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IContainerInfo, +} from '../../../types'; + +export interface PluginConfig { + fileType: string; + moduleFileType: string; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg: PluginConfig = { + fileType: FileType.CSS, + moduleFileType: FileType.JSX, + ...config, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IContainerInfo; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: COMMON_CHUNK_NAME.StyleCssContent, + content: ir.css, + linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.moduleFileType, + name: COMMON_CHUNK_NAME.InternalDepsImport, + content: `import './index.${cfg.fileType}';`, + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/project/constants.ts b/modules/code-generator/src/plugins/project/constants.ts new file mode 100644 index 0000000..18b286c --- /dev/null +++ b/modules/code-generator/src/plugins/project/constants.ts @@ -0,0 +1,59 @@ +import { COMMON_CHUNK_NAME } from '../../const/generator'; +import { generateCompositeType } from '../../utils/compositeType'; +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IProjectInfo, +} from '../../types'; +import { Scope } from '../../utils/Scope'; + +const pluginFactory: BuilderComponentPluginFactory = () => { + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IProjectInfo; + const scope = Scope.createRootScope(); + const constantStr = generateCompositeType(ir.constants || {}, scope); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JS, + name: COMMON_CHUNK_NAME.FileVarDefine, + content: ` + const __$$constants = (${constantStr}); + `, + linkAfter: [ + COMMON_CHUNK_NAME.ExternalDepsImport, + COMMON_CHUNK_NAME.InternalDepsImport, + COMMON_CHUNK_NAME.ImportAliasDefine, + ], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JS, + name: COMMON_CHUNK_NAME.FileExport, + content: ` + export default __$$constants; + `, + linkAfter: [ + COMMON_CHUNK_NAME.ExternalDepsImport, + COMMON_CHUNK_NAME.InternalDepsImport, + COMMON_CHUNK_NAME.ImportAliasDefine, + COMMON_CHUNK_NAME.FileVarDefine, + COMMON_CHUNK_NAME.FileUtilDefine, + COMMON_CHUNK_NAME.FileMainContent, + ], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/project/framework/icejs/index.ts b/modules/code-generator/src/plugins/project/framework/icejs/index.ts new file mode 100644 index 0000000..e9c8f25 --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/index.ts @@ -0,0 +1,17 @@ +import template from './template'; +import entry from './plugins/entry'; +import entryHtml from './plugins/entryHtml'; +import globalStyle from './plugins/globalStyle'; +import packageJSON from './plugins/packageJSON'; +import router from './plugins/router'; + +export default { + template, + plugins: { + entry, + entryHtml, + globalStyle, + packageJSON, + router, + }, +}; diff --git a/modules/code-generator/src/plugins/project/framework/icejs/plugins/entry.ts b/modules/code-generator/src/plugins/project/framework/icejs/plugins/entry.ts new file mode 100644 index 0000000..b5dc2d8 --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/plugins/entry.ts @@ -0,0 +1,56 @@ +import { COMMON_CHUNK_NAME } from '../../../../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, +} from '../../../../../types'; + +const pluginFactory: BuilderComponentPluginFactory = () => { + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JS, + name: COMMON_CHUNK_NAME.ExternalDepsImport, + content: ` + import { createApp } from 'ice'; + `, + linkAfter: [], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JS, + name: COMMON_CHUNK_NAME.FileMainContent, + content: ` + const appConfig = { + app: { + rootId: 'app', + }, + router: { + type: 'hash', + }, + }; + createApp(appConfig); + `, + linkAfter: [ + COMMON_CHUNK_NAME.ExternalDepsImport, + COMMON_CHUNK_NAME.InternalDepsImport, + COMMON_CHUNK_NAME.ImportAliasDefine, + COMMON_CHUNK_NAME.FileVarDefine, + COMMON_CHUNK_NAME.FileUtilDefine, + ], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/project/framework/icejs/plugins/entryHtml.ts b/modules/code-generator/src/plugins/project/framework/icejs/plugins/entryHtml.ts new file mode 100644 index 0000000..e5837a8 --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/plugins/entryHtml.ts @@ -0,0 +1,46 @@ +import { COMMON_CHUNK_NAME } from '../../../../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IProjectInfo, +} from '../../../../../types'; + +const pluginFactory: BuilderComponentPluginFactory = () => { + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IProjectInfo; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.HTML, + name: COMMON_CHUNK_NAME.HtmlContent, + content: ` + + + + + + + ${ir?.meta?.name || 'Ice App'} + + +
+ + + `, + linkAfter: [], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/project/framework/icejs/plugins/globalStyle.ts b/modules/code-generator/src/plugins/project/framework/icejs/plugins/globalStyle.ts new file mode 100644 index 0000000..3daaeec --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/plugins/globalStyle.ts @@ -0,0 +1,56 @@ +import { COMMON_CHUNK_NAME } from '../../../../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IProjectInfo, +} from '../../../../../types'; + +const pluginFactory: BuilderComponentPluginFactory = () => { + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IProjectInfo; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.SCSS, + name: COMMON_CHUNK_NAME.StyleDepsImport, + content: ` + // 引入默认全局样式 + @import '@alifd/next/reset.scss'; + `, + linkAfter: [], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.SCSS, + name: COMMON_CHUNK_NAME.StyleCssContent, + content: ` + body { + -webkit-font-smoothing: antialiased; + } + `, + linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.SCSS, + name: COMMON_CHUNK_NAME.StyleCssContent, + content: ir.css || '', + linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/project/framework/icejs/plugins/packageJSON.ts b/modules/code-generator/src/plugins/project/framework/icejs/plugins/packageJSON.ts new file mode 100644 index 0000000..cc8003c --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/plugins/packageJSON.ts @@ -0,0 +1,125 @@ +import { PackageJSON } from '@felce/lowcode-types'; + +import { COMMON_CHUNK_NAME } from '../../../../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IProjectInfo, +} from '../../../../../types'; +import { buildDataSourceDependencies } from '../../../../../utils/dataSource'; + +interface IIceJsPackageJSON extends PackageJSON { + ideMode: { + name: string; + }; + iceworks: { + type: string; + adapter: string; + }; + originTemplate: string; +} + +export type IceJsPackageJsonPluginConfig = { + /** + * 数据源配置 + */ + datasourceConfig?: { + /** 数据源引擎的版本 */ + engineVersion?: string; + /** 数据源引擎的包名 */ + enginePackage?: string; + /** 数据源 handlers 的版本 */ + handlersVersion?: { + [key: string]: string; + }; + /** 数据源 handlers 的包名 */ + handlersPackages?: { + [key: string]: string; + }; + }; + /** 包名 */ + packageName?: string; + /** 版本 */ + packageVersion?: string; +}; + +const pluginFactory: BuilderComponentPluginFactory = (cfg) => { + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IProjectInfo; + + const packageJson: IIceJsPackageJSON = { + name: cfg?.packageName || 'icejs-demo-app', + version: cfg?.packageVersion || '0.1.5', + description: '轻量级模板,使用 JavaScript,仅包含基础的 Layout。', + dependencies: { + moment: '^2.24.0', + react: '^16.4.1', + 'react-dom': '^16.4.1', + 'react-router': '^5.2.1', + '@alifd/theme-design-pro': '^0.x', + 'intl-messageformat': '^9.3.6', + '@ice/store': '^1.4.3', + '@loadable/component': '^5.15.2', + + // 数据源相关的依赖: + ...buildDataSourceDependencies(ir, cfg?.datasourceConfig), + }, + devDependencies: { + '@ice/spec': '^1.0.0', + 'build-plugin-fusion': '^0.1.0', + 'build-plugin-moment-locales': '^0.1.0', + eslint: '^6.0.1', + 'ice.js': '^1.0.0', + stylelint: '^13.2.0', + }, + scripts: { + start: 'icejs start', + build: 'icejs build', + lint: 'npm run eslint && npm run stylelint', + eslint: 'eslint --cache --ext .js,.jsx ./', + stylelint: 'stylelint ./**/*.scss', + }, + ideMode: { + name: 'ice-react', + }, + iceworks: { + type: 'react', + adapter: 'adapter-react-v3', + }, + engines: { + node: '>=8.0.0', + }, + repository: { + type: 'git', + url: 'http://gitlab.xxx.com/msd/leak-scan/tree/master', + }, + private: true, + originTemplate: '@alifd/scaffold-lite-js', + }; + + ir.packages.forEach((packageInfo) => { + packageJson.dependencies[packageInfo.package] = packageInfo.version; + }); + + next.chunks.push({ + type: ChunkType.JSON, + fileType: FileType.JSON, + name: COMMON_CHUNK_NAME.FileMainContent, + content: packageJson, + linkAfter: [], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/project/framework/icejs/plugins/router.ts b/modules/code-generator/src/plugins/project/framework/icejs/plugins/router.ts new file mode 100644 index 0000000..0e2e8c1 --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/plugins/router.ts @@ -0,0 +1,84 @@ +import { COMMON_CHUNK_NAME } from '../../../../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, + IRouterInfo, +} from '../../../../../types'; + +const pluginFactory: BuilderComponentPluginFactory = () => { + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + const ir = next.ir as IRouterInfo; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JS, + name: COMMON_CHUNK_NAME.InternalDepsImport, + content: ` + import BasicLayout from '@/layouts/BasicLayout'; + `, + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JS, + name: COMMON_CHUNK_NAME.FileVarDefine, + content: ` + const routerConfig = [ + { + path: '/', + component: BasicLayout, + children: [ + ${ir.routes + .map( + (route) => ` + { + path: '${route.path}', + component: ${route.componentName}, + } + `, + ) + .join(',')} + ], + }, + ]; + `, + linkAfter: [ + COMMON_CHUNK_NAME.ExternalDepsImport, + COMMON_CHUNK_NAME.InternalDepsImport, + COMMON_CHUNK_NAME.ImportAliasDefine, + COMMON_CHUNK_NAME.FileUtilDefine, + ], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JS, + name: COMMON_CHUNK_NAME.FileExport, + content: ` + export default routerConfig; + `, + linkAfter: [ + COMMON_CHUNK_NAME.ExternalDepsImport, + COMMON_CHUNK_NAME.InternalDepsImport, + COMMON_CHUNK_NAME.FileUtilDefine, + COMMON_CHUNK_NAME.ImportAliasDefine, + COMMON_CHUNK_NAME.FileVarDefine, + COMMON_CHUNK_NAME.FileMainContent, + ], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/modules/code-generator/src/plugins/project/framework/icejs/template/files/README.md.ts b/modules/code-generator/src/plugins/project/framework/icejs/template/files/README.md.ts new file mode 100644 index 0000000..1a0af6c --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/template/files/README.md.ts @@ -0,0 +1,73 @@ +import { ResultFile } from '@felce/lowcode-types'; +import { createResultFile } from '../../../../../../utils/resultHelper'; + +export default function getFile(): [string[], ResultFile] { + const file = createResultFile( + 'README', + 'md', + ` +## Scaffold Lite + +> 轻量级模板,使用 JavaScript,仅包含基础的 Layout。 + +## 使用 + +\`\`\`bash +# 安装依赖 +$ npm install + +# 启动服务 +$ npm start # visit http://localhost:3333 +\`\`\` + +[More docs](https://ice.work/docs/guide/about). + +## 目录 + +\`\`\`md +├── build/ # 构建产物 +├── mock/ # 本地模拟数据 +│ ├── index.[j,t]s +├── public/ +│ ├── index.html # 应用入口 HTML +│ └── favicon.png # Favicon +├── src/ # 源码路径 +│ ├── components/ # 自定义业务组件 +│ │ └── Guide/ +│ │ ├── index.[j,t]sx +│ │ ├── index.module.scss +│ ├── layouts/ # 布局组件 +│ │ └── BasicLayout/ +│ │ ├── index.[j,t]sx +│ │ └── index.module.scss +│ ├── pages/ # 页面 +│ │ └── Home/ # home 页面,约定路由转成小写 +│ │ ├── components/ # 页面级自定义业务组件 +│ │ ├── models.[j,t]sx # 页面级数据状态 +│ │ ├── index.[j,t]sx # 页面入口 +│ │ └── index.module.scss # 页面样式文件 +│ ├── configs/ # [可选] 配置文件 +│ │ └── menu.[j,t]s # [可选] 菜单配置 +│ ├── models/ # [可选] 应用级数据状态 +│ │ └── user.[j,t]s +│ ├── utils/ # [可选] 工具库 +│ ├── global.scss # 全局样式 +│ ├── routes.[j,t]s # 路由配置 +│ └── app.[j,t]s[x] # 应用入口脚本 +├── build.json # 工程配置 +├── README.md +├── package.json +├── .editorconfig +├── .eslintignore +├── .eslintrc.[j,t]s +├── .gitignore +├── .stylelintignore +├── .stylelintrc.[j,t]s +├── .gitignore +└── [j,t]sconfig.json +\`\`\` + `, + ); + + return [[], file]; +} diff --git a/modules/code-generator/src/plugins/project/framework/icejs/template/files/abc.json.ts b/modules/code-generator/src/plugins/project/framework/icejs/template/files/abc.json.ts new file mode 100644 index 0000000..64c69e8 --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/template/files/abc.json.ts @@ -0,0 +1,17 @@ +import { ResultFile } from '@felce/lowcode-types'; + +export default function getFile(): [string[], ResultFile] { + return [ + [], + { + name: 'abc', + ext: 'json', + content: ` +{ + "type": "ice-app", + "builder": "@ali/builder-ice-app" +} + `, + }, + ]; +} diff --git a/modules/code-generator/src/plugins/project/framework/icejs/template/files/build.json.ts b/modules/code-generator/src/plugins/project/framework/icejs/template/files/build.json.ts new file mode 100644 index 0000000..38baba4 --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/template/files/build.json.ts @@ -0,0 +1,32 @@ +import { ResultFile } from '@felce/lowcode-types'; + +export default function getFile(): [string[], ResultFile] { + return [ + [], + { + name: 'build', + ext: 'json', + content: ` +{ + "entry": "src/app.js", + "plugins": [ + [ + "build-plugin-fusion", + { + "themePackage": "@alifd/theme-design-pro" + } + ], + [ + "build-plugin-moment-locales", + { + "locales": [ + "zh-cn" + ] + } + ] + ] +} + `, + }, + ]; +} diff --git a/modules/code-generator/src/plugins/project/framework/icejs/template/files/editorconfig.ts b/modules/code-generator/src/plugins/project/framework/icejs/template/files/editorconfig.ts new file mode 100644 index 0000000..047a28d --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/template/files/editorconfig.ts @@ -0,0 +1,25 @@ +import { ResultFile } from '@felce/lowcode-types'; +import { createResultFile } from '../../../../../../utils/resultHelper'; + +export default function getFile(): [string[], ResultFile] { + const file = createResultFile( + '.editorconfig', + '', + ` +# http://editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false + `, + ); + + return [[], file]; +} diff --git a/modules/code-generator/src/plugins/project/framework/icejs/template/files/eslintignore.ts b/modules/code-generator/src/plugins/project/framework/icejs/template/files/eslintignore.ts new file mode 100644 index 0000000..6f21722 --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/template/files/eslintignore.ts @@ -0,0 +1,28 @@ +import { ResultFile } from '@felce/lowcode-types'; +import { createResultFile } from '../../../../../../utils/resultHelper'; + +export default function getFile(): [string[], ResultFile] { + const file = createResultFile( + '.eslintignore', + '', + ` +# 忽略目录 +build/ +tests/ +demo/ +.ice/ + +# node 覆盖率文件 +coverage/ + +# 忽略文件 +**/*-min.js +**/*.min.js + +package-lock.json +yarn.lock + `, + ); + + return [[], file]; +} diff --git a/modules/code-generator/src/plugins/project/framework/icejs/template/files/eslintrc.js.ts b/modules/code-generator/src/plugins/project/framework/icejs/template/files/eslintrc.js.ts new file mode 100644 index 0000000..2d28389 --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/template/files/eslintrc.js.ts @@ -0,0 +1,16 @@ +import { ResultFile } from '@felce/lowcode-types'; +import { createResultFile } from '../../../../../../utils/resultHelper'; + +export default function getFile(): [string[], ResultFile] { + const file = createResultFile( + '.eslintrc', + 'js', + ` +const { eslint } = require('@ice/spec'); + +module.exports = eslint; + `, + ); + + return [[], file]; +} diff --git a/modules/code-generator/src/plugins/project/framework/icejs/template/files/gitignore.ts b/modules/code-generator/src/plugins/project/framework/icejs/template/files/gitignore.ts new file mode 100644 index 0000000..5f93665 --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/template/files/gitignore.ts @@ -0,0 +1,36 @@ +import { ResultFile } from '@felce/lowcode-types'; +import { createResultFile } from '../../../../../../utils/resultHelper'; + +export default function getFile(): [string[], ResultFile] { + const file = createResultFile( + '.gitignore', + '', + ` +# See https://help.github.com/ignore-files/ for more about ignoring files. + +# dependencies +node_modules/ + +# production +build/ +dist/ +tmp/ +lib/ + +# misc +.idea/ +.happypack +.DS_Store +*.swp +*.dia~ +.ice + +npm-debug.log* +yarn-debug.log* +yarn-error.log* +index.module.scss.d.ts + `, + ); + + return [[], file]; +} diff --git a/modules/code-generator/src/plugins/project/framework/icejs/template/files/jsconfig.json.ts b/modules/code-generator/src/plugins/project/framework/icejs/template/files/jsconfig.json.ts new file mode 100644 index 0000000..a859c38 --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/template/files/jsconfig.json.ts @@ -0,0 +1,24 @@ +import { ResultFile } from '@felce/lowcode-types'; +import { createResultFile } from '../../../../../../utils/resultHelper'; + +export default function getFile(): [string[], ResultFile] { + const file = createResultFile( + 'jsconfig', + 'json', + ` +{ + "compilerOptions": { + "baseUrl": ".", + "jsx": "react", + "paths": { + "@/*": ["./src/*"], + "ice": [".ice/index.ts"], + "ice/*": [".ice/pages/*"] + } + } +} + `, + ); + + return [[], file]; +} diff --git a/modules/code-generator/src/plugins/project/framework/icejs/template/files/prettierignore.ts b/modules/code-generator/src/plugins/project/framework/icejs/template/files/prettierignore.ts new file mode 100644 index 0000000..18e55fd --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/template/files/prettierignore.ts @@ -0,0 +1,22 @@ +import { ResultFile } from '@felce/lowcode-types'; +import { createResultFile } from '../../../../../../utils/resultHelper'; + +export default function getFile(): [string[], ResultFile] { + const file = createResultFile( + '.prettierignore', + '', + ` +build/ +tests/ +demo/ +.ice/ +coverage/ +**/*-min.js +**/*.min.js +package-lock.json +yarn.lock + `, + ); + + return [[], file]; +} diff --git a/modules/code-generator/src/plugins/project/framework/icejs/template/files/prettierrc.js.ts b/modules/code-generator/src/plugins/project/framework/icejs/template/files/prettierrc.js.ts new file mode 100644 index 0000000..ae48aaa --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/template/files/prettierrc.js.ts @@ -0,0 +1,16 @@ +import { ResultFile } from '@felce/lowcode-types'; +import { createResultFile } from '../../../../../../utils/resultHelper'; + +export default function getFile(): [string[], ResultFile] { + const file = createResultFile( + '.prettierrc', + 'js', + ` +const { prettier } = require('@ice/spec'); + +module.exports = prettier; + `, + ); + + return [[], file]; +} diff --git a/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.jsx.ts b/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.jsx.ts new file mode 100644 index 0000000..ae5b302 --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.jsx.ts @@ -0,0 +1,25 @@ +import { ResultFile } from '@felce/lowcode-types'; +import { createResultFile } from '../../../../../../../../../../../utils/resultHelper'; + +export default function getFile(): [string[], ResultFile] { + const file = createResultFile( + 'index', + 'jsx', + ` +import React from 'react'; +import styles from './index.module.scss'; + +export default function Footer() { + return ( +

+ Alibaba Fusion +
+ © 2019-现在 Alibaba Fusion & ICE +

+ ); +} + `, + ); + + return [['src', 'layouts', 'BasicLayout', 'components', 'Footer'], file]; +} diff --git a/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.style.ts b/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.style.ts new file mode 100644 index 0000000..7204e99 --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.style.ts @@ -0,0 +1,26 @@ +import { ResultFile } from '@felce/lowcode-types'; +import { createResultFile } from '../../../../../../../../../../../utils/resultHelper'; + +export default function getFile(): [string[], ResultFile] { + const file = createResultFile( + 'index', + 'module.scss', + ` +.footer { + line-height: 20px; + text-align: center; +} + +.logo { + font-weight: bold; + font-size: 16px; +} + +.copyright { + font-size: 12px; +} + `, + ); + + return [['src', 'layouts', 'BasicLayout', 'components', 'Footer'], file]; +} diff --git a/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.jsx.ts b/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.jsx.ts new file mode 100644 index 0000000..bce1af8 --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.jsx.ts @@ -0,0 +1,27 @@ +import { ResultFile } from '@felce/lowcode-types'; +import { createResultFile } from '../../../../../../../../../../../utils/resultHelper'; + +export default function getFile(): [string[], ResultFile] { + const file = createResultFile( + 'index', + 'jsx', + ` +import React from 'react'; +import { Link } from 'ice'; +import styles from './index.module.scss'; + +export default function Logo({ image, text, url }) { + return ( +
+ + {image && logo} + {text} + +
+ ); +} + `, + ); + + return [['src', 'layouts', 'BasicLayout', 'components', 'Logo'], file]; +} diff --git a/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.style.ts b/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.style.ts new file mode 100644 index 0000000..50fa8d0 --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.style.ts @@ -0,0 +1,31 @@ +import { ResultFile } from '@felce/lowcode-types'; +import { createResultFile } from '../../../../../../../../../../../utils/resultHelper'; + +export default function getFile(): [string[], ResultFile] { + const file = createResultFile( + 'index', + 'module.scss', + ` +.logo{ + display: flex; + align-items: center; + justify-content: center; + color: $color-text1-1; + font-weight: bold; + font-size: 14px; + line-height: 22px; + + &:visited, &:link { + color: $color-text1-1; + } + + img { + height: 24px; + margin-right: 10px; + } +} + `, + ); + + return [['src', 'layouts', 'BasicLayout', 'components', 'Logo'], file]; +} diff --git a/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/PageNav/index.jsx.ts b/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/PageNav/index.jsx.ts new file mode 100644 index 0000000..02b8791 --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/PageNav/index.jsx.ts @@ -0,0 +1,81 @@ +import { ResultFile } from '@felce/lowcode-types'; +import { createResultFile } from '../../../../../../../../../../../utils/resultHelper'; + +export default function getFile(): [string[], ResultFile] { + const file = createResultFile( + 'index', + 'jsx', + ` +import React from 'react'; +import PropTypes from 'prop-types'; +import { Link, withRouter } from 'ice'; +import { Nav } from '@alifd/next'; +import { asideMenuConfig } from '../../menuConfig'; + +const { SubNav } = Nav; +const NavItem = Nav.Item; + +function getNavMenuItems(menusData) { + if (!menusData) { + return []; + } + + return menusData + .filter(item => item.name && !item.hideInMenu) + .map((item, index) => getSubMenuOrItem(item, index)); +} + +function getSubMenuOrItem(item, index) { + if (item.children && item.children.some(child => child.name)) { + const childrenItems = getNavMenuItems(item.children); + + if (childrenItems && childrenItems.length > 0) { + const subNav = ( + + {childrenItems} + + ); + return subNav; + } + + return null; + } + + const navItem = ( + + {item.name} + + ); + return navItem; +} + +const Navigation = (props, context) => { + const { location } = props; + const { pathname } = location; + const { isCollapse } = context; + return ( + + ); +}; + +Navigation.contextTypes = { + isCollapse: PropTypes.bool, +}; +const PageNav = withRouter(Navigation); +export default PageNav; + `, + ); + + return [['src', 'layouts', 'BasicLayout', 'components', 'PageNav'], file]; +} diff --git a/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/index.jsx.ts b/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/index.jsx.ts new file mode 100644 index 0000000..c544e96 --- /dev/null +++ b/modules/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/index.jsx.ts @@ -0,0 +1,92 @@ +import { ResultFile } from '@felce/lowcode-types'; +import { createResultFile } from '../../../../../../../../../utils/resultHelper'; + +export default function getFile(): [string[], ResultFile] { + const file = createResultFile( + 'index', + 'jsx', + ` +import React, { useState } from 'react'; +import { Shell, ConfigProvider } from '@alifd/next'; +import PageNav from './components/PageNav'; +import Logo from './components/Logo'; +import Footer from './components/Footer'; + +(function() { + const throttle = function(type, name, obj = window) { + let running = false; + + const func = () => { + if (running) { + return; + } + + running = true; + requestAnimationFrame(() => { + obj.dispatchEvent(new CustomEvent(name)); + running = false; + }); + }; + + obj.addEventListener(type, func); + }; + + throttle('resize', 'optimizedResize'); +})(); + +export default function BasicLayout({ children }) { + const getDevice = width => { + const isPhone = + typeof navigator !== 'undefined' && navigator && navigator.userAgent.match(/phone/gi); + + if (width < 680 || isPhone) { + return 'phone'; + } + if (width < 1280 && width > 680) { + return 'tablet'; + } + return 'desktop'; + }; + + const [device, setDevice] = useState(getDevice(NaN)); + window.addEventListener('optimizedResize', e => { + setDevice(getDevice(e && e.target && e.target.innerWidth)); + }); + return ( + + + + + + + + + + + + {children} + +