@modern-js/module-tools-docs 2.0.2 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/doc_build/api/config/build-config.html +332 -0
- package/doc_build/api/config/build-preset.html +43 -0
- package/doc_build/api/config/design-system.html +103 -0
- package/doc_build/api/config/plugins.html +7 -0
- package/doc_build/api/config/testing.html +21 -0
- package/doc_build/api/index.html +1 -0
- package/doc_build/api/plugin-api/plugin-hooks.html +113 -0
- package/doc_build/en/api/config/build-config.html +316 -0
- package/doc_build/en/api/config/build-preset.html +43 -0
- package/doc_build/en/api/config/design-system.html +117 -0
- package/doc_build/en/api/config/plugins.html +7 -0
- package/doc_build/en/api/config/testing.html +21 -0
- package/doc_build/en/api/index.html +1 -0
- package/doc_build/en/api/plugin-api/plugin-hooks.html +113 -0
- package/doc_build/en/guide/advance/asset.html +25 -0
- package/doc_build/en/guide/advance/build-umd.html +32 -0
- package/doc_build/en/guide/advance/copy.html +42 -0
- package/doc_build/en/guide/advance/external-dependency.html +31 -0
- package/doc_build/en/guide/advance/in-depth-about-build.html +112 -0
- package/doc_build/en/guide/advance/in-depth-about-dev-command.html +12 -0
- package/doc_build/en/guide/advance/theme-config.html +29 -0
- package/doc_build/en/guide/basic/before-getting-started.html +89 -0
- package/doc_build/en/guide/basic/command-preview.html +63 -0
- package/doc_build/en/guide/basic/modify-output-product.html +98 -0
- package/doc_build/en/guide/basic/publish-your-project.html +50 -0
- package/doc_build/en/guide/basic/test-your-project.html +31 -0
- package/doc_build/en/guide/basic/use-micro-generator.html +29 -0
- package/doc_build/en/guide/basic/using-storybook.html +66 -0
- package/doc_build/en/guide/best-practices/components.html +111 -0
- package/doc_build/en/guide/intro/getting-started.html +36 -0
- package/doc_build/en/guide/intro/welcome.html +13 -0
- package/doc_build/en/guide/intro/why-module-engineering-solution.html +9 -0
- package/doc_build/en/index.html +1 -0
- package/doc_build/en/plugins/guide/getting-started.html +15 -0
- package/doc_build/en/plugins/guide/plugin-object.html +14 -0
- package/doc_build/en/plugins/guide/setup-function.html +30 -0
- package/doc_build/en/plugins/official-list/overview.html +3 -0
- package/doc_build/guide/advance/asset.html +25 -0
- package/doc_build/guide/advance/build-umd.html +32 -0
- package/doc_build/guide/advance/copy.html +42 -0
- package/doc_build/guide/advance/external-dependency.html +31 -0
- package/doc_build/guide/advance/in-depth-about-build.html +112 -0
- package/doc_build/guide/advance/in-depth-about-dev-command.html +14 -0
- package/doc_build/guide/advance/theme-config.html +28 -0
- package/doc_build/guide/basic/before-getting-started.html +89 -0
- package/doc_build/guide/basic/command-preview.html +63 -0
- package/doc_build/guide/basic/modify-output-product.html +97 -0
- package/doc_build/guide/basic/publish-your-project.html +52 -0
- package/doc_build/guide/basic/test-your-project.html +32 -0
- package/doc_build/guide/basic/use-micro-generator.html +27 -0
- package/doc_build/guide/basic/using-storybook.html +67 -0
- package/doc_build/guide/best-practices/components.html +111 -0
- package/doc_build/guide/intro/getting-started.html +39 -0
- package/doc_build/guide/intro/welcome.html +13 -0
- package/doc_build/guide/intro/why-module-engineering-solution.html +9 -0
- package/doc_build/index.html +1 -0
- package/doc_build/plugins/guide/getting-started.html +15 -0
- package/doc_build/plugins/guide/plugin-object.html +14 -0
- package/doc_build/plugins/guide/setup-function.html +30 -0
- package/doc_build/plugins/official-list/overview.html +3 -0
- package/doc_build/static/css/main.edaad072.css +1 -0
- package/doc_build/static/js/1607.70af642a.js +2 -0
- package/doc_build/static/js/1607.70af642a.js.LICENSE.txt +23 -0
- package/doc_build/static/js/async/3799.e31e8293.js +1 -0
- package/doc_build/static/js/async/8652.6fbf1cb7.js +1 -0
- package/doc_build/static/js/async/en_api_config_build-config.367a5701.js +1 -0
- package/doc_build/static/js/async/en_api_config_build-preset.0d78b268.js +1 -0
- package/doc_build/static/js/async/en_api_config_design-system.b28d6723.js +1 -0
- package/doc_build/static/js/async/en_api_config_plugins.fc95fb77.js +1 -0
- package/doc_build/static/js/async/en_api_config_testing.8bc7f316.js +1 -0
- package/doc_build/static/js/async/en_api_index.669f0a56.js +1 -0
- package/doc_build/static/js/async/en_api_plugin-api_plugin-hooks.60d0260c.js +1 -0
- package/doc_build/static/js/async/en_guide_advance_asset.5ff1d623.js +1 -0
- package/doc_build/static/js/async/en_guide_advance_build-umd.c254ed46.js +1 -0
- package/doc_build/static/js/async/en_guide_advance_copy.45c0a51d.js +1 -0
- package/doc_build/static/js/async/en_guide_advance_external-dependency.a52d3247.js +1 -0
- package/doc_build/static/js/async/en_guide_advance_in-depth-about-build.51bf3569.js +1 -0
- package/doc_build/static/js/async/en_guide_advance_in-depth-about-dev-command.aec0b4e1.js +1 -0
- package/doc_build/static/js/async/en_guide_advance_theme-config.db0ad9fc.js +1 -0
- package/doc_build/static/js/async/en_guide_basic_before-getting-started.a22fc49a.js +1 -0
- package/doc_build/static/js/async/en_guide_basic_command-preview.1707ed29.js +1 -0
- package/doc_build/static/js/async/en_guide_basic_modify-output-product.ad453d13.js +1 -0
- package/doc_build/static/js/async/en_guide_basic_publish-your-project.08c5112f.js +1 -0
- package/doc_build/static/js/async/en_guide_basic_test-your-project.f5f6b204.js +1 -0
- package/doc_build/static/js/async/en_guide_basic_use-micro-generator.56325139.js +1 -0
- package/doc_build/static/js/async/en_guide_basic_using-storybook.9d721554.js +1 -0
- package/doc_build/static/js/async/en_guide_best-practices_components.45155af9.js +1 -0
- package/doc_build/static/js/async/en_guide_intro_getting-started.f8682be3.js +1 -0
- package/doc_build/static/js/async/en_guide_intro_welcome.9cc45924.js +1 -0
- package/doc_build/static/js/async/en_guide_intro_why-module-engineering-solution.7f2dae5c.js +1 -0
- package/doc_build/static/js/async/en_index.7bd869c4.js +1 -0
- package/doc_build/static/js/async/en_plugins_guide_getting-started.b850249c.js +1 -0
- package/doc_build/static/js/async/en_plugins_guide_plugin-object.bf6c6221.js +1 -0
- package/doc_build/static/js/async/en_plugins_guide_setup-function.80a2bd97.js +1 -0
- package/doc_build/static/js/async/en_plugins_official-list_overview.84e5cea0.js +1 -0
- package/doc_build/static/js/async/zh_api_config_build-config.048fd5ec.js +1 -0
- package/doc_build/static/js/async/zh_api_config_build-preset.7c13584d.js +1 -0
- package/doc_build/static/js/async/zh_api_config_design-system.1eecd474.js +1 -0
- package/doc_build/static/js/async/zh_api_config_plugins.c22dc4be.js +1 -0
- package/doc_build/static/js/async/zh_api_config_testing.a9888eed.js +1 -0
- package/doc_build/static/js/async/zh_api_index.22957707.js +1 -0
- package/doc_build/static/js/async/zh_api_plugin-api_plugin-hooks.a4d81bf6.js +1 -0
- package/doc_build/static/js/async/zh_guide_advance_asset.5b936003.js +1 -0
- package/doc_build/static/js/async/zh_guide_advance_build-umd.b6d541ff.js +1 -0
- package/doc_build/static/js/async/zh_guide_advance_copy.21a1aea4.js +1 -0
- package/doc_build/static/js/async/zh_guide_advance_external-dependency.c7cf5d4b.js +1 -0
- package/doc_build/static/js/async/zh_guide_advance_in-depth-about-build.64e795f3.js +1 -0
- package/doc_build/static/js/async/zh_guide_advance_in-depth-about-dev-command.168ce7dd.js +1 -0
- package/doc_build/static/js/async/zh_guide_advance_theme-config.b9570109.js +1 -0
- package/doc_build/static/js/async/zh_guide_basic_before-getting-started.6b06b54a.js +1 -0
- package/doc_build/static/js/async/zh_guide_basic_command-preview.1199124a.js +1 -0
- package/doc_build/static/js/async/zh_guide_basic_modify-output-product.8ccbc8d1.js +1 -0
- package/doc_build/static/js/async/zh_guide_basic_publish-your-project.bf11b1c4.js +1 -0
- package/doc_build/static/js/async/zh_guide_basic_test-your-project.ae52c47a.js +1 -0
- package/doc_build/static/js/async/zh_guide_basic_use-micro-generator.a091d57d.js +1 -0
- package/doc_build/static/js/async/zh_guide_basic_using-storybook.27829e44.js +1 -0
- package/doc_build/static/js/async/zh_guide_best-practices_components.7454d916.js +1 -0
- package/doc_build/static/js/async/zh_guide_intro_getting-started.a4c00d9a.js +1 -0
- package/doc_build/static/js/async/zh_guide_intro_welcome.71c3fe16.js +1 -0
- package/doc_build/static/js/async/zh_guide_intro_why-module-engineering-solution.6f8b5ff6.js +1 -0
- package/doc_build/static/js/async/zh_index.c19f9dcf.js +1 -0
- package/doc_build/static/js/async/zh_plugins_guide_getting-started.099dfaea.js +1 -0
- package/doc_build/static/js/async/zh_plugins_guide_plugin-object.963289d5.js +1 -0
- package/doc_build/static/js/async/zh_plugins_guide_setup-function.67d07b91.js +1 -0
- package/doc_build/static/js/async/zh_plugins_official-list_overview.a7635714.js +1 -0
- package/doc_build/static/js/lib-lodash.c5845536.js +1 -0
- package/doc_build/static/js/lib-polyfill.b3038509.js +1 -0
- package/doc_build/static/js/lib-react.d41ace5e.js +2 -0
- package/doc_build/static/js/lib-react.d41ace5e.js.LICENSE.txt +29 -0
- package/doc_build/static/js/main.2d3257a4.js +1 -0
- package/doc_build/static/search_index.json +1 -0
- package/docs/en/api/config/build-config.md +15 -5
- package/docs/en/api/config/build-preset.md +3 -2
- package/docs/en/api/config/design-system.md +623 -615
- package/docs/en/api/config/plugins.md +2 -2
- package/docs/en/api/config/testing.md +2 -1
- package/docs/en/guide/advance/asset.mdx +0 -4
- package/docs/en/guide/advance/build-umd.mdx +3 -3
- package/docs/en/guide/advance/in-depth-about-build.md +14 -13
- package/docs/en/guide/advance/in-depth-about-dev-command.md +2 -1
- package/docs/en/guide/basic/before-getting-started.md +16 -9
- package/docs/en/guide/basic/command-preview.md +2 -2
- package/docs/en/guide/basic/modify-output-product.md +65 -69
- package/docs/en/guide/basic/test-your-project.mdx +1 -3
- package/docs/en/guide/basic/use-micro-generator.md +4 -0
- package/docs/en/guide/basic/using-storybook.mdx +1 -13
- package/docs/en/plugins/guide/getting-started.mdx +2 -2
- package/docs/en/plugins/guide/plugin-object.mdx +5 -5
- package/docs/zh/api/config/build-config.md +18 -6
- package/docs/zh/api/config/build-preset.md +3 -2
- package/docs/zh/api/config/design-system.md +2 -2
- package/docs/zh/api/config/plugins.md +2 -2
- package/docs/zh/api/config/testing.md +3 -2
- package/docs/zh/guide/advance/asset.mdx +0 -5
- package/docs/zh/guide/advance/build-umd.mdx +3 -3
- package/docs/zh/guide/advance/in-depth-about-build.md +14 -13
- package/docs/zh/guide/advance/in-depth-about-dev-command.md +2 -1
- package/docs/zh/guide/basic/before-getting-started.md +15 -8
- package/docs/zh/guide/basic/command-preview.md +2 -2
- package/docs/zh/guide/basic/modify-output-product.md +17 -19
- package/docs/zh/guide/basic/test-your-project.mdx +1 -3
- package/docs/zh/guide/basic/use-micro-generator.md +5 -1
- package/docs/zh/guide/basic/using-storybook.mdx +9 -19
- package/docs/zh/guide/intro/getting-started.md +1 -1
- package/docs/zh/plugins/guide/getting-started.mdx +2 -2
- package/docs/zh/plugins/guide/plugin-object.mdx +5 -5
- package/modern.config.ts +11 -5
- package/package.json +3 -3
- package/LICENSE +0 -144
- package/doc_build/html/main/index.html +0 -16
- package/doc_build/route.json +0 -10
- package/doc_build/static/css/main.css +0 -3370
- package/doc_build/static/css/main.css.map +0 -1
- package/doc_build/static/css/vendors-node_modules_pnpm_remix-run_router_1_2_0_node_modules_remix-run_router_dist_router_js-9d5e9c.css +0 -85
- package/doc_build/static/css/vendors-node_modules_pnpm_remix-run_router_1_2_0_node_modules_remix-run_router_dist_router_js-9d5e9c.css.map +0 -1
- package/doc_build/static/js/async/api_.js +0 -56
- package/doc_build/static/js/async/api_.js.map +0 -1
- package/doc_build/static/js/async/api_config_build-config.js +0 -11309
- package/doc_build/static/js/async/api_config_build-config.js.map +0 -1
- package/doc_build/static/js/async/api_config_build-preset.js +0 -7849
- package/doc_build/static/js/async/api_config_build-preset.js.map +0 -1
- package/doc_build/static/js/async/api_config_design-system.js +0 -48708
- package/doc_build/static/js/async/api_config_design-system.js.map +0 -1
- package/doc_build/static/js/async/api_config_plugins.js +0 -1492
- package/doc_build/static/js/async/api_config_plugins.js.map +0 -1
- package/doc_build/static/js/async/api_config_testing.js +0 -2130
- package/doc_build/static/js/async/api_config_testing.js.map +0 -1
- package/doc_build/static/js/async/api_plugin-api_plugin-hooks.js +0 -14394
- package/doc_build/static/js/async/api_plugin-api_plugin-hooks.js.map +0 -1
- package/doc_build/static/js/async/en_.js +0 -85
- package/doc_build/static/js/async/en_.js.map +0 -1
- package/doc_build/static/js/async/en_api_.js +0 -55
- package/doc_build/static/js/async/en_api_.js.map +0 -1
- package/doc_build/static/js/async/en_api_config_build-config.js +0 -8363
- package/doc_build/static/js/async/en_api_config_build-config.js.map +0 -1
- package/doc_build/static/js/async/en_api_config_build-preset.js +0 -7845
- package/doc_build/static/js/async/en_api_config_build-preset.js.map +0 -1
- package/doc_build/static/js/async/en_api_config_design-system.js +0 -16345
- package/doc_build/static/js/async/en_api_config_design-system.js.map +0 -1
- package/doc_build/static/js/async/en_api_config_plugins.js +0 -1492
- package/doc_build/static/js/async/en_api_config_plugins.js.map +0 -1
- package/doc_build/static/js/async/en_api_config_testing.js +0 -2137
- package/doc_build/static/js/async/en_api_config_testing.js.map +0 -1
- package/doc_build/static/js/async/en_api_plugin-api_plugin-hooks.js +0 -14362
- package/doc_build/static/js/async/en_api_plugin-api_plugin-hooks.js.map +0 -1
- package/doc_build/static/js/async/en_guide_advance_asset.js +0 -3997
- package/doc_build/static/js/async/en_guide_advance_asset.js.map +0 -1
- package/doc_build/static/js/async/en_guide_advance_build-umd.js +0 -9861
- package/doc_build/static/js/async/en_guide_advance_build-umd.js.map +0 -1
- package/doc_build/static/js/async/en_guide_advance_copy.js +0 -6539
- package/doc_build/static/js/async/en_guide_advance_copy.js.map +0 -1
- package/doc_build/static/js/async/en_guide_advance_external-dependency.js +0 -3810
- package/doc_build/static/js/async/en_guide_advance_external-dependency.js.map +0 -1
- package/doc_build/static/js/async/en_guide_advance_in-depth-about-build.js +0 -5046
- package/doc_build/static/js/async/en_guide_advance_in-depth-about-build.js.map +0 -1
- package/doc_build/static/js/async/en_guide_advance_in-depth-about-dev-command.js +0 -150
- package/doc_build/static/js/async/en_guide_advance_in-depth-about-dev-command.js.map +0 -1
- package/doc_build/static/js/async/en_guide_advance_theme-config.js +0 -2484
- package/doc_build/static/js/async/en_guide_advance_theme-config.js.map +0 -1
- package/doc_build/static/js/async/en_guide_basic_before-getting-started.js +0 -3671
- package/doc_build/static/js/async/en_guide_basic_before-getting-started.js.map +0 -1
- package/doc_build/static/js/async/en_guide_basic_command-preview.js +0 -3961
- package/doc_build/static/js/async/en_guide_basic_command-preview.js.map +0 -1
- package/doc_build/static/js/async/en_guide_basic_modify-output-product.js +0 -2970
- package/doc_build/static/js/async/en_guide_basic_modify-output-product.js.map +0 -1
- package/doc_build/static/js/async/en_guide_basic_publish-your-project.js +0 -2182
- package/doc_build/static/js/async/en_guide_basic_publish-your-project.js.map +0 -1
- package/doc_build/static/js/async/en_guide_basic_test-your-project.js +0 -3892
- package/doc_build/static/js/async/en_guide_basic_test-your-project.js.map +0 -1
- package/doc_build/static/js/async/en_guide_basic_use-micro-generator.js +0 -168
- package/doc_build/static/js/async/en_guide_basic_use-micro-generator.js.map +0 -1
- package/doc_build/static/js/async/en_guide_basic_using-storybook.js +0 -4762
- package/doc_build/static/js/async/en_guide_basic_using-storybook.js.map +0 -1
- package/doc_build/static/js/async/en_guide_best-practices_components.js +0 -21388
- package/doc_build/static/js/async/en_guide_best-practices_components.js.map +0 -1
- package/doc_build/static/js/async/en_guide_intro_getting-started.js +0 -1906
- package/doc_build/static/js/async/en_guide_intro_getting-started.js.map +0 -1
- package/doc_build/static/js/async/en_guide_intro_welcome.js +0 -148
- package/doc_build/static/js/async/en_guide_intro_welcome.js.map +0 -1
- package/doc_build/static/js/async/en_guide_intro_why-module-engineering-solution.js +0 -92
- package/doc_build/static/js/async/en_guide_intro_why-module-engineering-solution.js.map +0 -1
- package/doc_build/static/js/async/en_plugins_guide_getting-started.js +0 -2560
- package/doc_build/static/js/async/en_plugins_guide_getting-started.js.map +0 -1
- package/doc_build/static/js/async/en_plugins_guide_plugin-object.js +0 -4177
- package/doc_build/static/js/async/en_plugins_guide_plugin-object.js.map +0 -1
- package/doc_build/static/js/async/en_plugins_guide_setup-function.js +0 -3819
- package/doc_build/static/js/async/en_plugins_guide_setup-function.js.map +0 -1
- package/doc_build/static/js/async/en_plugins_official-list_overview.js +0 -70
- package/doc_build/static/js/async/en_plugins_official-list_overview.js.map +0 -1
- package/doc_build/static/js/async/guide_advance_asset.js +0 -3997
- package/doc_build/static/js/async/guide_advance_asset.js.map +0 -1
- package/doc_build/static/js/async/guide_advance_build-umd.js +0 -9863
- package/doc_build/static/js/async/guide_advance_build-umd.js.map +0 -1
- package/doc_build/static/js/async/guide_advance_copy.js +0 -6539
- package/doc_build/static/js/async/guide_advance_copy.js.map +0 -1
- package/doc_build/static/js/async/guide_advance_external-dependency.js +0 -3812
- package/doc_build/static/js/async/guide_advance_external-dependency.js.map +0 -1
- package/doc_build/static/js/async/guide_advance_in-depth-about-build.js +0 -5046
- package/doc_build/static/js/async/guide_advance_in-depth-about-build.js.map +0 -1
- package/doc_build/static/js/async/guide_advance_in-depth-about-dev-command.js +0 -152
- package/doc_build/static/js/async/guide_advance_in-depth-about-dev-command.js.map +0 -1
- package/doc_build/static/js/async/guide_advance_theme-config.js +0 -2475
- package/doc_build/static/js/async/guide_advance_theme-config.js.map +0 -1
- package/doc_build/static/js/async/guide_basic_before-getting-started.js +0 -3662
- package/doc_build/static/js/async/guide_basic_before-getting-started.js.map +0 -1
- package/doc_build/static/js/async/guide_basic_command-preview.js +0 -3793
- package/doc_build/static/js/async/guide_basic_command-preview.js.map +0 -1
- package/doc_build/static/js/async/guide_basic_modify-output-product.js +0 -2949
- package/doc_build/static/js/async/guide_basic_modify-output-product.js.map +0 -1
- package/doc_build/static/js/async/guide_basic_publish-your-project.js +0 -2243
- package/doc_build/static/js/async/guide_basic_publish-your-project.js.map +0 -1
- package/doc_build/static/js/async/guide_basic_test-your-project.js +0 -3892
- package/doc_build/static/js/async/guide_basic_test-your-project.js.map +0 -1
- package/doc_build/static/js/async/guide_basic_use-micro-generator.js +0 -172
- package/doc_build/static/js/async/guide_basic_use-micro-generator.js.map +0 -1
- package/doc_build/static/js/async/guide_basic_using-storybook.js +0 -4762
- package/doc_build/static/js/async/guide_basic_using-storybook.js.map +0 -1
- package/doc_build/static/js/async/guide_best-practices_components.js +0 -21088
- package/doc_build/static/js/async/guide_best-practices_components.js.map +0 -1
- package/doc_build/static/js/async/guide_intro_getting-started.js +0 -1782
- package/doc_build/static/js/async/guide_intro_getting-started.js.map +0 -1
- package/doc_build/static/js/async/guide_intro_welcome.js +0 -148
- package/doc_build/static/js/async/guide_intro_welcome.js.map +0 -1
- package/doc_build/static/js/async/guide_intro_why-module-engineering-solution.js +0 -92
- package/doc_build/static/js/async/guide_intro_why-module-engineering-solution.js.map +0 -1
- package/doc_build/static/js/async/index.js +0 -85
- package/doc_build/static/js/async/index.js.map +0 -1
- package/doc_build/static/js/async/packages_cli_doc-core_src_theme-default_components_Search_logic_search_ts.js +0 -447
- package/doc_build/static/js/async/packages_cli_doc-core_src_theme-default_components_Search_logic_search_ts.js.map +0 -1
- package/doc_build/static/js/async/plugins_guide_getting-started.js +0 -2608
- package/doc_build/static/js/async/plugins_guide_getting-started.js.map +0 -1
- package/doc_build/static/js/async/plugins_guide_plugin-object.js +0 -4173
- package/doc_build/static/js/async/plugins_guide_plugin-object.js.map +0 -1
- package/doc_build/static/js/async/plugins_guide_setup-function.js +0 -3819
- package/doc_build/static/js/async/plugins_guide_setup-function.js.map +0 -1
- package/doc_build/static/js/async/plugins_official-list_overview.js +0 -70
- package/doc_build/static/js/async/plugins_official-list_overview.js.map +0 -1
- package/doc_build/static/js/async/vendors-node_modules_pnpm_code-hike_mdx_0_7_4_react_18_2_0_node_modules_code-hike_mdx_dist_co-06dd41.js +0 -6656
- package/doc_build/static/js/async/vendors-node_modules_pnpm_code-hike_mdx_0_7_4_react_18_2_0_node_modules_code-hike_mdx_dist_co-06dd41.js.map +0 -1
- package/doc_build/static/js/async/vendors-node_modules_pnpm_flexsearch_0_6_32_node_modules_flexsearch_dist_flexsearch_min_js.js +0 -54
- package/doc_build/static/js/async/vendors-node_modules_pnpm_flexsearch_0_6_32_node_modules_flexsearch_dist_flexsearch_min_js.js.map +0 -1
- package/doc_build/static/js/builder-runtime.js +0 -1375
- package/doc_build/static/js/builder-runtime.js.map +0 -1
- package/doc_build/static/js/lib-lodash.js +0 -4907
- package/doc_build/static/js/lib-lodash.js.map +0 -1
- package/doc_build/static/js/lib-polyfill.js +0 -24769
- package/doc_build/static/js/lib-polyfill.js.map +0 -1
- package/doc_build/static/js/lib-react.js +0 -39510
- package/doc_build/static/js/lib-react.js.map +0 -1
- package/doc_build/static/js/main.js +0 -9237
- package/doc_build/static/js/main.js.map +0 -1
- package/doc_build/static/js/vendors-node_modules_pnpm_remix-run_router_1_2_0_node_modules_remix-run_router_dist_router_js-9d5e9c.js +0 -8532
- package/doc_build/static/js/vendors-node_modules_pnpm_remix-run_router_1_2_0_node_modules_remix-run_router_dist_router_js-9d5e9c.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"static/js/vendors-node_modules_pnpm_remix-run_router_1_2_0_node_modules_remix-run_router_dist_router_js-9d5e9c.js","mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;AC7jHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;ACrRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AClHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AChDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC1OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;ACtCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;ACRA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AC3dA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;ACzFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACjmBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;ACXA;;;;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;ACznBA;AACA;AACA;AAGA;AACA;;;;;;;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;ACtCA;;;;;;;;;;;;;;;;;;ACCA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA","sources":["webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/@remix-run+router@1.2.0/node_modules/@remix-run/router/dist/router.js","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/body-scroll-lock@4.0.0-beta.0/node_modules/body-scroll-lock/lib/bodyScrollLock.esm.js","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/copy-to-clipboard@3.3.3/node_modules/copy-to-clipboard/index.js","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/invariant@2.2.4/node_modules/invariant/browser.js","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/mini-css-extract-plugin@2.7.0_webpack@5.75.0/node_modules/mini-css-extract-plugin/dist/hmr/hotModuleReplacement.js","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/mini-css-extract-plugin@2.7.0_webpack@5.75.0/node_modules/mini-css-extract-plugin/dist/hmr/normalize-url.js","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/nprogress@0.2.0/node_modules/nprogress/nprogress.css?c410","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/nprogress@0.2.0/node_modules/nprogress/nprogress.js","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/object-assign@4.1.1/node_modules/object-assign/index.js","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/prop-types@15.8.1/node_modules/prop-types/checkPropTypes.js","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/prop-types@15.8.1/node_modules/prop-types/factoryWithTypeCheckers.js","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/prop-types@15.8.1/node_modules/prop-types/index.js","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/prop-types@15.8.1/node_modules/prop-types/lib/ReactPropTypesSecret.js","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/prop-types@15.8.1/node_modules/prop-types/lib/has.js","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/scheduler@0.23.0/node_modules/scheduler/cjs/scheduler.development.js","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/scheduler@0.23.0/node_modules/scheduler/index.js","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/shallowequal@1.1.0/node_modules/shallowequal/index.js","webpack://@modern-js/module-tools-docs/../../node_modules/.pnpm/toggle-selection@1.0.6/node_modules/toggle-selection/index.js","webpack://@modern-js/module-tools-docs/../../packages/cli/doc-core/node_modules/virtual-site-data","webpack://@modern-js/module-tools-docs/../../packages/cli/doc-core/node_modules/virtual-routes.js"],"sourcesContent":["/**\n * @remix-run/router v1.2.0\n *\n * Copyright (c) Remix Software Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE.md file in the root directory of this source tree.\n *\n * @license MIT\n */\nfunction _extends() {\n _extends = Object.assign ? Object.assign.bind() : function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n\n return target;\n };\n return _extends.apply(this, arguments);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Types and Constants\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Actions represent the type of change to a location value.\n */\nvar Action;\n\n(function (Action) {\n /**\n * A POP indicates a change to an arbitrary index in the history stack, such\n * as a back or forward navigation. It does not describe the direction of the\n * navigation, only that the current index changed.\n *\n * Note: This is the default action for newly created history objects.\n */\n Action[\"Pop\"] = \"POP\";\n /**\n * A PUSH indicates a new entry being added to the history stack, such as when\n * a link is clicked and a new page loads. When this happens, all subsequent\n * entries in the stack are lost.\n */\n\n Action[\"Push\"] = \"PUSH\";\n /**\n * A REPLACE indicates the entry at the current index in the history stack\n * being replaced by a new one.\n */\n\n Action[\"Replace\"] = \"REPLACE\";\n})(Action || (Action = {}));\n\nconst PopStateEventType = \"popstate\";\n/**\n * Memory history stores the current location in memory. It is designed for use\n * in stateful non-browser environments like tests and React Native.\n */\n\nfunction createMemoryHistory(options) {\n if (options === void 0) {\n options = {};\n }\n\n let {\n initialEntries = [\"/\"],\n initialIndex,\n v5Compat = false\n } = options;\n let entries; // Declare so we can access from createMemoryLocation\n\n entries = initialEntries.map((entry, index) => createMemoryLocation(entry, typeof entry === \"string\" ? null : entry.state, index === 0 ? \"default\" : undefined));\n let index = clampIndex(initialIndex == null ? entries.length - 1 : initialIndex);\n let action = Action.Pop;\n let listener = null;\n\n function clampIndex(n) {\n return Math.min(Math.max(n, 0), entries.length - 1);\n }\n\n function getCurrentLocation() {\n return entries[index];\n }\n\n function createMemoryLocation(to, state, key) {\n if (state === void 0) {\n state = null;\n }\n\n let location = createLocation(entries ? getCurrentLocation().pathname : \"/\", to, state, key);\n warning$1(location.pathname.charAt(0) === \"/\", \"relative pathnames are not supported in memory history: \" + JSON.stringify(to));\n return location;\n }\n\n let history = {\n get index() {\n return index;\n },\n\n get action() {\n return action;\n },\n\n get location() {\n return getCurrentLocation();\n },\n\n createHref(to) {\n return typeof to === \"string\" ? to : createPath(to);\n },\n\n encodeLocation(to) {\n let path = typeof to === \"string\" ? parsePath(to) : to;\n return {\n pathname: path.pathname || \"\",\n search: path.search || \"\",\n hash: path.hash || \"\"\n };\n },\n\n push(to, state) {\n action = Action.Push;\n let nextLocation = createMemoryLocation(to, state);\n index += 1;\n entries.splice(index, entries.length, nextLocation);\n\n if (v5Compat && listener) {\n listener({\n action,\n location: nextLocation\n });\n }\n },\n\n replace(to, state) {\n action = Action.Replace;\n let nextLocation = createMemoryLocation(to, state);\n entries[index] = nextLocation;\n\n if (v5Compat && listener) {\n listener({\n action,\n location: nextLocation\n });\n }\n },\n\n go(delta) {\n action = Action.Pop;\n index = clampIndex(index + delta);\n\n if (listener) {\n listener({\n action,\n location: getCurrentLocation()\n });\n }\n },\n\n listen(fn) {\n listener = fn;\n return () => {\n listener = null;\n };\n }\n\n };\n return history;\n}\n/**\n * Browser history stores the location in regular URLs. This is the standard for\n * most web apps, but it requires some configuration on the server to ensure you\n * serve the same app at multiple URLs.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory\n */\n\nfunction createBrowserHistory(options) {\n if (options === void 0) {\n options = {};\n }\n\n function createBrowserLocation(window, globalHistory) {\n let {\n pathname,\n search,\n hash\n } = window.location;\n return createLocation(\"\", {\n pathname,\n search,\n hash\n }, // state defaults to `null` because `window.history.state` does\n globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || \"default\");\n }\n\n function createBrowserHref(window, to) {\n return typeof to === \"string\" ? to : createPath(to);\n }\n\n return getUrlBasedHistory(createBrowserLocation, createBrowserHref, null, options);\n}\n/**\n * Hash history stores the location in window.location.hash. This makes it ideal\n * for situations where you don't want to send the location to the server for\n * some reason, either because you do cannot configure it or the URL space is\n * reserved for something else.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory\n */\n\nfunction createHashHistory(options) {\n if (options === void 0) {\n options = {};\n }\n\n function createHashLocation(window, globalHistory) {\n let {\n pathname = \"/\",\n search = \"\",\n hash = \"\"\n } = parsePath(window.location.hash.substr(1));\n return createLocation(\"\", {\n pathname,\n search,\n hash\n }, // state defaults to `null` because `window.history.state` does\n globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || \"default\");\n }\n\n function createHashHref(window, to) {\n let base = window.document.querySelector(\"base\");\n let href = \"\";\n\n if (base && base.getAttribute(\"href\")) {\n let url = window.location.href;\n let hashIndex = url.indexOf(\"#\");\n href = hashIndex === -1 ? url : url.slice(0, hashIndex);\n }\n\n return href + \"#\" + (typeof to === \"string\" ? to : createPath(to));\n }\n\n function validateHashLocation(location, to) {\n warning$1(location.pathname.charAt(0) === \"/\", \"relative pathnames are not supported in hash history.push(\" + JSON.stringify(to) + \")\");\n }\n\n return getUrlBasedHistory(createHashLocation, createHashHref, validateHashLocation, options);\n}\nfunction invariant(value, message) {\n if (value === false || value === null || typeof value === \"undefined\") {\n throw new Error(message);\n }\n}\n\nfunction warning$1(cond, message) {\n if (!cond) {\n // eslint-disable-next-line no-console\n if (typeof console !== \"undefined\") console.warn(message);\n\n try {\n // Welcome to debugging history!\n //\n // This error is thrown as a convenience so you can more easily\n // find the source for a warning that appears in the console by\n // enabling \"pause on exceptions\" in your JavaScript debugger.\n throw new Error(message); // eslint-disable-next-line no-empty\n } catch (e) {}\n }\n}\n\nfunction createKey() {\n return Math.random().toString(36).substr(2, 8);\n}\n/**\n * For browser-based histories, we combine the state and key into an object\n */\n\n\nfunction getHistoryState(location) {\n return {\n usr: location.state,\n key: location.key\n };\n}\n/**\n * Creates a Location object with a unique key from the given Path\n */\n\n\nfunction createLocation(current, to, state, key) {\n if (state === void 0) {\n state = null;\n }\n\n let location = _extends({\n pathname: typeof current === \"string\" ? current : current.pathname,\n search: \"\",\n hash: \"\"\n }, typeof to === \"string\" ? parsePath(to) : to, {\n state,\n // TODO: This could be cleaned up. push/replace should probably just take\n // full Locations now and avoid the need to run through this flow at all\n // But that's a pretty big refactor to the current test suite so going to\n // keep as is for the time being and just let any incoming keys take precedence\n key: to && to.key || key || createKey()\n });\n\n return location;\n}\n/**\n * Creates a string URL path from the given pathname, search, and hash components.\n */\n\nfunction createPath(_ref) {\n let {\n pathname = \"/\",\n search = \"\",\n hash = \"\"\n } = _ref;\n if (search && search !== \"?\") pathname += search.charAt(0) === \"?\" ? search : \"?\" + search;\n if (hash && hash !== \"#\") pathname += hash.charAt(0) === \"#\" ? hash : \"#\" + hash;\n return pathname;\n}\n/**\n * Parses a string URL path into its separate pathname, search, and hash components.\n */\n\nfunction parsePath(path) {\n let parsedPath = {};\n\n if (path) {\n let hashIndex = path.indexOf(\"#\");\n\n if (hashIndex >= 0) {\n parsedPath.hash = path.substr(hashIndex);\n path = path.substr(0, hashIndex);\n }\n\n let searchIndex = path.indexOf(\"?\");\n\n if (searchIndex >= 0) {\n parsedPath.search = path.substr(searchIndex);\n path = path.substr(0, searchIndex);\n }\n\n if (path) {\n parsedPath.pathname = path;\n }\n }\n\n return parsedPath;\n}\nfunction createClientSideURL(location) {\n // window.location.origin is \"null\" (the literal string value) in Firefox\n // under certain conditions, notably when serving from a local HTML file\n // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297\n let base = typeof window !== \"undefined\" && typeof window.location !== \"undefined\" && window.location.origin !== \"null\" ? window.location.origin : window.location.href;\n let href = typeof location === \"string\" ? location : createPath(location);\n invariant(base, \"No window.location.(origin|href) available to create URL for href: \" + href);\n return new URL(href, base);\n}\n\nfunction getUrlBasedHistory(getLocation, createHref, validateLocation, options) {\n if (options === void 0) {\n options = {};\n }\n\n let {\n window = document.defaultView,\n v5Compat = false\n } = options;\n let globalHistory = window.history;\n let action = Action.Pop;\n let listener = null;\n\n function handlePop() {\n action = Action.Pop;\n\n if (listener) {\n listener({\n action,\n location: history.location\n });\n }\n }\n\n function push(to, state) {\n action = Action.Push;\n let location = createLocation(history.location, to, state);\n if (validateLocation) validateLocation(location, to);\n let historyState = getHistoryState(location);\n let url = history.createHref(location); // try...catch because iOS limits us to 100 pushState calls :/\n\n try {\n globalHistory.pushState(historyState, \"\", url);\n } catch (error) {\n // They are going to lose state here, but there is no real\n // way to warn them about it since the page will refresh...\n window.location.assign(url);\n }\n\n if (v5Compat && listener) {\n listener({\n action,\n location: history.location\n });\n }\n }\n\n function replace(to, state) {\n action = Action.Replace;\n let location = createLocation(history.location, to, state);\n if (validateLocation) validateLocation(location, to);\n let historyState = getHistoryState(location);\n let url = history.createHref(location);\n globalHistory.replaceState(historyState, \"\", url);\n\n if (v5Compat && listener) {\n listener({\n action,\n location: history.location\n });\n }\n }\n\n let history = {\n get action() {\n return action;\n },\n\n get location() {\n return getLocation(window, globalHistory);\n },\n\n listen(fn) {\n if (listener) {\n throw new Error(\"A history only accepts one active listener\");\n }\n\n window.addEventListener(PopStateEventType, handlePop);\n listener = fn;\n return () => {\n window.removeEventListener(PopStateEventType, handlePop);\n listener = null;\n };\n },\n\n createHref(to) {\n return createHref(window, to);\n },\n\n encodeLocation(to) {\n // Encode a Location the same way window.location would\n let url = createClientSideURL(typeof to === \"string\" ? to : createPath(to));\n return {\n pathname: url.pathname,\n search: url.search,\n hash: url.hash\n };\n },\n\n push,\n replace,\n\n go(n) {\n return globalHistory.go(n);\n }\n\n };\n return history;\n} //#endregion\n\nvar ResultType;\n\n(function (ResultType) {\n ResultType[\"data\"] = \"data\";\n ResultType[\"deferred\"] = \"deferred\";\n ResultType[\"redirect\"] = \"redirect\";\n ResultType[\"error\"] = \"error\";\n})(ResultType || (ResultType = {}));\n\nfunction isIndexRoute(route) {\n return route.index === true;\n} // Walk the route tree generating unique IDs where necessary so we are working\n// solely with AgnosticDataRouteObject's within the Router\n\n\nfunction convertRoutesToDataRoutes(routes, parentPath, allIds) {\n if (parentPath === void 0) {\n parentPath = [];\n }\n\n if (allIds === void 0) {\n allIds = new Set();\n }\n\n return routes.map((route, index) => {\n let treePath = [...parentPath, index];\n let id = typeof route.id === \"string\" ? route.id : treePath.join(\"-\");\n invariant(route.index !== true || !route.children, \"Cannot specify children on an index route\");\n invariant(!allIds.has(id), \"Found a route id collision on id \\\"\" + id + \"\\\". Route \" + \"id's must be globally unique within Data Router usages\");\n allIds.add(id);\n\n if (isIndexRoute(route)) {\n let indexRoute = _extends({}, route, {\n id\n });\n\n return indexRoute;\n } else {\n let pathOrLayoutRoute = _extends({}, route, {\n id,\n children: route.children ? convertRoutesToDataRoutes(route.children, treePath, allIds) : undefined\n });\n\n return pathOrLayoutRoute;\n }\n });\n}\n/**\n * Matches the given routes to a location and returns the match data.\n *\n * @see https://reactrouter.com/utils/match-routes\n */\n\nfunction matchRoutes(routes, locationArg, basename) {\n if (basename === void 0) {\n basename = \"/\";\n }\n\n let location = typeof locationArg === \"string\" ? parsePath(locationArg) : locationArg;\n let pathname = stripBasename(location.pathname || \"/\", basename);\n\n if (pathname == null) {\n return null;\n }\n\n let branches = flattenRoutes(routes);\n rankRouteBranches(branches);\n let matches = null;\n\n for (let i = 0; matches == null && i < branches.length; ++i) {\n matches = matchRouteBranch(branches[i], // Incoming pathnames are generally encoded from either window.location\n // or from router.navigate, but we want to match against the unencoded\n // paths in the route definitions. Memory router locations won't be\n // encoded here but there also shouldn't be anything to decode so this\n // should be a safe operation. This avoids needing matchRoutes to be\n // history-aware.\n safelyDecodeURI(pathname));\n }\n\n return matches;\n}\n\nfunction flattenRoutes(routes, branches, parentsMeta, parentPath) {\n if (branches === void 0) {\n branches = [];\n }\n\n if (parentsMeta === void 0) {\n parentsMeta = [];\n }\n\n if (parentPath === void 0) {\n parentPath = \"\";\n }\n\n let flattenRoute = (route, index, relativePath) => {\n let meta = {\n relativePath: relativePath === undefined ? route.path || \"\" : relativePath,\n caseSensitive: route.caseSensitive === true,\n childrenIndex: index,\n route\n };\n\n if (meta.relativePath.startsWith(\"/\")) {\n invariant(meta.relativePath.startsWith(parentPath), \"Absolute route path \\\"\" + meta.relativePath + \"\\\" nested under path \" + (\"\\\"\" + parentPath + \"\\\" is not valid. An absolute child route path \") + \"must start with the combined path of all its parent routes.\");\n meta.relativePath = meta.relativePath.slice(parentPath.length);\n }\n\n let path = joinPaths([parentPath, meta.relativePath]);\n let routesMeta = parentsMeta.concat(meta); // Add the children before adding this route to the array so we traverse the\n // route tree depth-first and child routes appear before their parents in\n // the \"flattened\" version.\n\n if (route.children && route.children.length > 0) {\n invariant( // Our types know better, but runtime JS may not!\n // @ts-expect-error\n route.index !== true, \"Index routes must not have child routes. Please remove \" + (\"all child routes from route path \\\"\" + path + \"\\\".\"));\n flattenRoutes(route.children, branches, routesMeta, path);\n } // Routes without a path shouldn't ever match by themselves unless they are\n // index routes, so don't add them to the list of possible branches.\n\n\n if (route.path == null && !route.index) {\n return;\n }\n\n branches.push({\n path,\n score: computeScore(path, route.index),\n routesMeta\n });\n };\n\n routes.forEach((route, index) => {\n var _route$path;\n\n // coarse-grain check for optional params\n if (route.path === \"\" || !((_route$path = route.path) != null && _route$path.includes(\"?\"))) {\n flattenRoute(route, index);\n } else {\n for (let exploded of explodeOptionalSegments(route.path)) {\n flattenRoute(route, index, exploded);\n }\n }\n });\n return branches;\n}\n/**\n * Computes all combinations of optional path segments for a given path,\n * excluding combinations that are ambiguous and of lower priority.\n *\n * For example, `/one/:two?/three/:four?/:five?` explodes to:\n * - `/one/three`\n * - `/one/:two/three`\n * - `/one/three/:four`\n * - `/one/three/:five`\n * - `/one/:two/three/:four`\n * - `/one/:two/three/:five`\n * - `/one/three/:four/:five`\n * - `/one/:two/three/:four/:five`\n */\n\n\nfunction explodeOptionalSegments(path) {\n let segments = path.split(\"/\");\n if (segments.length === 0) return [];\n let [first, ...rest] = segments; // Optional path segments are denoted by a trailing `?`\n\n let isOptional = first.endsWith(\"?\"); // Compute the corresponding required segment: `foo?` -> `foo`\n\n let required = first.replace(/\\?$/, \"\");\n\n if (rest.length === 0) {\n // Intepret empty string as omitting an optional segment\n // `[\"one\", \"\", \"three\"]` corresponds to omitting `:two` from `/one/:two?/three` -> `/one/three`\n return isOptional ? [required, \"\"] : [required];\n }\n\n let restExploded = explodeOptionalSegments(rest.join(\"/\"));\n let result = []; // All child paths with the prefix. Do this for all children before the\n // optional version for all children so we get consistent ordering where the\n // parent optional aspect is preferred as required. Otherwise, we can get\n // child sections interspersed where deeper optional segments are higher than\n // parent optional segments, where for example, /:two would explodes _earlier_\n // then /:one. By always including the parent as required _for all children_\n // first, we avoid this issue\n\n result.push(...restExploded.map(subpath => subpath === \"\" ? required : [required, subpath].join(\"/\"))); // Then if this is an optional value, add all child versions without\n\n if (isOptional) {\n result.push(...restExploded);\n } // for absolute paths, ensure `/` instead of empty segment\n\n\n return result.map(exploded => path.startsWith(\"/\") && exploded === \"\" ? \"/\" : exploded);\n}\n\nfunction rankRouteBranches(branches) {\n branches.sort((a, b) => a.score !== b.score ? b.score - a.score // Higher score first\n : compareIndexes(a.routesMeta.map(meta => meta.childrenIndex), b.routesMeta.map(meta => meta.childrenIndex)));\n}\n\nconst paramRe = /^:\\w+$/;\nconst dynamicSegmentValue = 3;\nconst indexRouteValue = 2;\nconst emptySegmentValue = 1;\nconst staticSegmentValue = 10;\nconst splatPenalty = -2;\n\nconst isSplat = s => s === \"*\";\n\nfunction computeScore(path, index) {\n let segments = path.split(\"/\");\n let initialScore = segments.length;\n\n if (segments.some(isSplat)) {\n initialScore += splatPenalty;\n }\n\n if (index) {\n initialScore += indexRouteValue;\n }\n\n return segments.filter(s => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === \"\" ? emptySegmentValue : staticSegmentValue), initialScore);\n}\n\nfunction compareIndexes(a, b) {\n let siblings = a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);\n return siblings ? // If two routes are siblings, we should try to match the earlier sibling\n // first. This allows people to have fine-grained control over the matching\n // behavior by simply putting routes with identical paths in the order they\n // want them tried.\n a[a.length - 1] - b[b.length - 1] : // Otherwise, it doesn't really make sense to rank non-siblings by index,\n // so they sort equally.\n 0;\n}\n\nfunction matchRouteBranch(branch, pathname) {\n let {\n routesMeta\n } = branch;\n let matchedParams = {};\n let matchedPathname = \"/\";\n let matches = [];\n\n for (let i = 0; i < routesMeta.length; ++i) {\n let meta = routesMeta[i];\n let end = i === routesMeta.length - 1;\n let remainingPathname = matchedPathname === \"/\" ? pathname : pathname.slice(matchedPathname.length) || \"/\";\n let match = matchPath({\n path: meta.relativePath,\n caseSensitive: meta.caseSensitive,\n end\n }, remainingPathname);\n if (!match) return null;\n Object.assign(matchedParams, match.params);\n let route = meta.route;\n matches.push({\n // TODO: Can this as be avoided?\n params: matchedParams,\n pathname: joinPaths([matchedPathname, match.pathname]),\n pathnameBase: normalizePathname(joinPaths([matchedPathname, match.pathnameBase])),\n route\n });\n\n if (match.pathnameBase !== \"/\") {\n matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);\n }\n }\n\n return matches;\n}\n/**\n * Returns a path with params interpolated.\n *\n * @see https://reactrouter.com/utils/generate-path\n */\n\n\nfunction generatePath(originalPath, params) {\n if (params === void 0) {\n params = {};\n }\n\n let path = originalPath;\n\n if (path.endsWith(\"*\") && path !== \"*\" && !path.endsWith(\"/*\")) {\n warning(false, \"Route path \\\"\" + path + \"\\\" will be treated as if it were \" + (\"\\\"\" + path.replace(/\\*$/, \"/*\") + \"\\\" because the `*` character must \") + \"always follow a `/` in the pattern. To get rid of this warning, \" + (\"please change the route path to \\\"\" + path.replace(/\\*$/, \"/*\") + \"\\\".\"));\n path = path.replace(/\\*$/, \"/*\");\n }\n\n return path.replace(/^:(\\w+)/g, (_, key) => {\n invariant(params[key] != null, \"Missing \\\":\" + key + \"\\\" param\");\n return params[key];\n }).replace(/\\/:(\\w+)/g, (_, key) => {\n invariant(params[key] != null, \"Missing \\\":\" + key + \"\\\" param\");\n return \"/\" + params[key];\n }).replace(/(\\/?)\\*/, (_, prefix, __, str) => {\n const star = \"*\";\n\n if (params[star] == null) {\n // If no splat was provided, trim the trailing slash _unless_ it's\n // the entire path\n return str === \"/*\" ? \"/\" : \"\";\n } // Apply the splat\n\n\n return \"\" + prefix + params[star];\n });\n}\n/**\n * Performs pattern matching on a URL pathname and returns information about\n * the match.\n *\n * @see https://reactrouter.com/utils/match-path\n */\n\nfunction matchPath(pattern, pathname) {\n if (typeof pattern === \"string\") {\n pattern = {\n path: pattern,\n caseSensitive: false,\n end: true\n };\n }\n\n let [matcher, paramNames] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);\n let match = pathname.match(matcher);\n if (!match) return null;\n let matchedPathname = match[0];\n let pathnameBase = matchedPathname.replace(/(.)\\/+$/, \"$1\");\n let captureGroups = match.slice(1);\n let params = paramNames.reduce((memo, paramName, index) => {\n // We need to compute the pathnameBase here using the raw splat value\n // instead of using params[\"*\"] later because it will be decoded then\n if (paramName === \"*\") {\n let splatValue = captureGroups[index] || \"\";\n pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\\/+$/, \"$1\");\n }\n\n memo[paramName] = safelyDecodeURIComponent(captureGroups[index] || \"\", paramName);\n return memo;\n }, {});\n return {\n params,\n pathname: matchedPathname,\n pathnameBase,\n pattern\n };\n}\n\nfunction compilePath(path, caseSensitive, end) {\n if (caseSensitive === void 0) {\n caseSensitive = false;\n }\n\n if (end === void 0) {\n end = true;\n }\n\n warning(path === \"*\" || !path.endsWith(\"*\") || path.endsWith(\"/*\"), \"Route path \\\"\" + path + \"\\\" will be treated as if it were \" + (\"\\\"\" + path.replace(/\\*$/, \"/*\") + \"\\\" because the `*` character must \") + \"always follow a `/` in the pattern. To get rid of this warning, \" + (\"please change the route path to \\\"\" + path.replace(/\\*$/, \"/*\") + \"\\\".\"));\n let paramNames = [];\n let regexpSource = \"^\" + path.replace(/\\/*\\*?$/, \"\") // Ignore trailing / and /*, we'll handle it below\n .replace(/^\\/*/, \"/\") // Make sure it has a leading /\n .replace(/[\\\\.*+^$?{}|()[\\]]/g, \"\\\\$&\") // Escape special regex chars\n .replace(/\\/:(\\w+)/g, (_, paramName) => {\n paramNames.push(paramName);\n return \"/([^\\\\/]+)\";\n });\n\n if (path.endsWith(\"*\")) {\n paramNames.push(\"*\");\n regexpSource += path === \"*\" || path === \"/*\" ? \"(.*)$\" // Already matched the initial /, just match the rest\n : \"(?:\\\\/(.+)|\\\\/*)$\"; // Don't include the / in params[\"*\"]\n } else if (end) {\n // When matching to the end, ignore trailing slashes\n regexpSource += \"\\\\/*$\";\n } else if (path !== \"\" && path !== \"/\") {\n // If our path is non-empty and contains anything beyond an initial slash,\n // then we have _some_ form of path in our regex so we should expect to\n // match only if we find the end of this path segment. Look for an optional\n // non-captured trailing slash (to match a portion of the URL) or the end\n // of the path (if we've matched to the end). We used to do this with a\n // word boundary but that gives false positives on routes like\n // /user-preferences since `-` counts as a word boundary.\n regexpSource += \"(?:(?=\\\\/|$))\";\n } else ;\n\n let matcher = new RegExp(regexpSource, caseSensitive ? undefined : \"i\");\n return [matcher, paramNames];\n}\n\nfunction safelyDecodeURI(value) {\n try {\n return decodeURI(value);\n } catch (error) {\n warning(false, \"The URL path \\\"\" + value + \"\\\" could not be decoded because it is is a \" + \"malformed URL segment. This is probably due to a bad percent \" + (\"encoding (\" + error + \").\"));\n return value;\n }\n}\n\nfunction safelyDecodeURIComponent(value, paramName) {\n try {\n return decodeURIComponent(value);\n } catch (error) {\n warning(false, \"The value for the URL param \\\"\" + paramName + \"\\\" will not be decoded because\" + (\" the string \\\"\" + value + \"\\\" is a malformed URL segment. This is probably\") + (\" due to a bad percent encoding (\" + error + \").\"));\n return value;\n }\n}\n/**\n * @private\n */\n\n\nfunction stripBasename(pathname, basename) {\n if (basename === \"/\") return pathname;\n\n if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {\n return null;\n } // We want to leave trailing slash behavior in the user's control, so if they\n // specify a basename with a trailing slash, we should support it\n\n\n let startIndex = basename.endsWith(\"/\") ? basename.length - 1 : basename.length;\n let nextChar = pathname.charAt(startIndex);\n\n if (nextChar && nextChar !== \"/\") {\n // pathname does not start with basename/\n return null;\n }\n\n return pathname.slice(startIndex) || \"/\";\n}\n/**\n * @private\n */\n\nfunction warning(cond, message) {\n if (!cond) {\n // eslint-disable-next-line no-console\n if (typeof console !== \"undefined\") console.warn(message);\n\n try {\n // Welcome to debugging React Router!\n //\n // This error is thrown as a convenience so you can more easily\n // find the source for a warning that appears in the console by\n // enabling \"pause on exceptions\" in your JavaScript debugger.\n throw new Error(message); // eslint-disable-next-line no-empty\n } catch (e) {}\n }\n}\n/**\n * Returns a resolved path object relative to the given pathname.\n *\n * @see https://reactrouter.com/utils/resolve-path\n */\n\nfunction resolvePath(to, fromPathname) {\n if (fromPathname === void 0) {\n fromPathname = \"/\";\n }\n\n let {\n pathname: toPathname,\n search = \"\",\n hash = \"\"\n } = typeof to === \"string\" ? parsePath(to) : to;\n let pathname = toPathname ? toPathname.startsWith(\"/\") ? toPathname : resolvePathname(toPathname, fromPathname) : fromPathname;\n return {\n pathname,\n search: normalizeSearch(search),\n hash: normalizeHash(hash)\n };\n}\n\nfunction resolvePathname(relativePath, fromPathname) {\n let segments = fromPathname.replace(/\\/+$/, \"\").split(\"/\");\n let relativeSegments = relativePath.split(\"/\");\n relativeSegments.forEach(segment => {\n if (segment === \"..\") {\n // Keep the root \"\" segment so the pathname starts at /\n if (segments.length > 1) segments.pop();\n } else if (segment !== \".\") {\n segments.push(segment);\n }\n });\n return segments.length > 1 ? segments.join(\"/\") : \"/\";\n}\n\nfunction getInvalidPathError(char, field, dest, path) {\n return \"Cannot include a '\" + char + \"' character in a manually specified \" + (\"`to.\" + field + \"` field [\" + JSON.stringify(path) + \"]. Please separate it out to the \") + (\"`to.\" + dest + \"` field. Alternatively you may provide the full path as \") + \"a string in <Link to=\\\"...\\\"> and the router will parse it for you.\";\n}\n/**\n * @private\n *\n * When processing relative navigation we want to ignore ancestor routes that\n * do not contribute to the path, such that index/pathless layout routes don't\n * interfere.\n *\n * For example, when moving a route element into an index route and/or a\n * pathless layout route, relative link behavior contained within should stay\n * the same. Both of the following examples should link back to the root:\n *\n * <Route path=\"/\">\n * <Route path=\"accounts\" element={<Link to=\"..\"}>\n * </Route>\n *\n * <Route path=\"/\">\n * <Route path=\"accounts\">\n * <Route element={<AccountsLayout />}> // <-- Does not contribute\n * <Route index element={<Link to=\"..\"} /> // <-- Does not contribute\n * </Route\n * </Route>\n * </Route>\n */\n\n\nfunction getPathContributingMatches(matches) {\n return matches.filter((match, index) => index === 0 || match.route.path && match.route.path.length > 0);\n}\n/**\n * @private\n */\n\nfunction resolveTo(toArg, routePathnames, locationPathname, isPathRelative) {\n if (isPathRelative === void 0) {\n isPathRelative = false;\n }\n\n let to;\n\n if (typeof toArg === \"string\") {\n to = parsePath(toArg);\n } else {\n to = _extends({}, toArg);\n invariant(!to.pathname || !to.pathname.includes(\"?\"), getInvalidPathError(\"?\", \"pathname\", \"search\", to));\n invariant(!to.pathname || !to.pathname.includes(\"#\"), getInvalidPathError(\"#\", \"pathname\", \"hash\", to));\n invariant(!to.search || !to.search.includes(\"#\"), getInvalidPathError(\"#\", \"search\", \"hash\", to));\n }\n\n let isEmptyPath = toArg === \"\" || to.pathname === \"\";\n let toPathname = isEmptyPath ? \"/\" : to.pathname;\n let from; // Routing is relative to the current pathname if explicitly requested.\n //\n // If a pathname is explicitly provided in `to`, it should be relative to the\n // route context. This is explained in `Note on `<Link to>` values` in our\n // migration guide from v5 as a means of disambiguation between `to` values\n // that begin with `/` and those that do not. However, this is problematic for\n // `to` values that do not provide a pathname. `to` can simply be a search or\n // hash string, in which case we should assume that the navigation is relative\n // to the current location's pathname and *not* the route pathname.\n\n if (isPathRelative || toPathname == null) {\n from = locationPathname;\n } else {\n let routePathnameIndex = routePathnames.length - 1;\n\n if (toPathname.startsWith(\"..\")) {\n let toSegments = toPathname.split(\"/\"); // Each leading .. segment means \"go up one route\" instead of \"go up one\n // URL segment\". This is a key difference from how <a href> works and a\n // major reason we call this a \"to\" value instead of a \"href\".\n\n while (toSegments[0] === \"..\") {\n toSegments.shift();\n routePathnameIndex -= 1;\n }\n\n to.pathname = toSegments.join(\"/\");\n } // If there are more \"..\" segments than parent routes, resolve relative to\n // the root / URL.\n\n\n from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : \"/\";\n }\n\n let path = resolvePath(to, from); // Ensure the pathname has a trailing slash if the original \"to\" had one\n\n let hasExplicitTrailingSlash = toPathname && toPathname !== \"/\" && toPathname.endsWith(\"/\"); // Or if this was a link to the current path which has a trailing slash\n\n let hasCurrentTrailingSlash = (isEmptyPath || toPathname === \".\") && locationPathname.endsWith(\"/\");\n\n if (!path.pathname.endsWith(\"/\") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) {\n path.pathname += \"/\";\n }\n\n return path;\n}\n/**\n * @private\n */\n\nfunction getToPathname(to) {\n // Empty strings should be treated the same as / paths\n return to === \"\" || to.pathname === \"\" ? \"/\" : typeof to === \"string\" ? parsePath(to).pathname : to.pathname;\n}\n/**\n * @private\n */\n\nconst joinPaths = paths => paths.join(\"/\").replace(/\\/\\/+/g, \"/\");\n/**\n * @private\n */\n\nconst normalizePathname = pathname => pathname.replace(/\\/+$/, \"\").replace(/^\\/*/, \"/\");\n/**\n * @private\n */\n\nconst normalizeSearch = search => !search || search === \"?\" ? \"\" : search.startsWith(\"?\") ? search : \"?\" + search;\n/**\n * @private\n */\n\nconst normalizeHash = hash => !hash || hash === \"#\" ? \"\" : hash.startsWith(\"#\") ? hash : \"#\" + hash;\n/**\n * This is a shortcut for creating `application/json` responses. Converts `data`\n * to JSON and sets the `Content-Type` header.\n */\n\nconst json = function json(data, init) {\n if (init === void 0) {\n init = {};\n }\n\n let responseInit = typeof init === \"number\" ? {\n status: init\n } : init;\n let headers = new Headers(responseInit.headers);\n\n if (!headers.has(\"Content-Type\")) {\n headers.set(\"Content-Type\", \"application/json; charset=utf-8\");\n }\n\n return new Response(JSON.stringify(data), _extends({}, responseInit, {\n headers\n }));\n};\nclass AbortedDeferredError extends Error {}\nclass DeferredData {\n constructor(data) {\n this.pendingKeys = new Set();\n this.subscriber = undefined;\n invariant(data && typeof data === \"object\" && !Array.isArray(data), \"defer() only accepts plain objects\"); // Set up an AbortController + Promise we can race against to exit early\n // cancellation\n\n let reject;\n this.abortPromise = new Promise((_, r) => reject = r);\n this.controller = new AbortController();\n\n let onAbort = () => reject(new AbortedDeferredError(\"Deferred data aborted\"));\n\n this.unlistenAbortSignal = () => this.controller.signal.removeEventListener(\"abort\", onAbort);\n\n this.controller.signal.addEventListener(\"abort\", onAbort);\n this.data = Object.entries(data).reduce((acc, _ref) => {\n let [key, value] = _ref;\n return Object.assign(acc, {\n [key]: this.trackPromise(key, value)\n });\n }, {});\n }\n\n trackPromise(key, value) {\n if (!(value instanceof Promise)) {\n return value;\n }\n\n this.pendingKeys.add(key); // We store a little wrapper promise that will be extended with\n // _data/_error props upon resolve/reject\n\n let promise = Promise.race([value, this.abortPromise]).then(data => this.onSettle(promise, key, null, data), error => this.onSettle(promise, key, error)); // Register rejection listeners to avoid uncaught promise rejections on\n // errors or aborted deferred values\n\n promise.catch(() => {});\n Object.defineProperty(promise, \"_tracked\", {\n get: () => true\n });\n return promise;\n }\n\n onSettle(promise, key, error, data) {\n if (this.controller.signal.aborted && error instanceof AbortedDeferredError) {\n this.unlistenAbortSignal();\n Object.defineProperty(promise, \"_error\", {\n get: () => error\n });\n return Promise.reject(error);\n }\n\n this.pendingKeys.delete(key);\n\n if (this.done) {\n // Nothing left to abort!\n this.unlistenAbortSignal();\n }\n\n const subscriber = this.subscriber;\n\n if (error) {\n Object.defineProperty(promise, \"_error\", {\n get: () => error\n });\n subscriber && subscriber(false);\n return Promise.reject(error);\n }\n\n Object.defineProperty(promise, \"_data\", {\n get: () => data\n });\n subscriber && subscriber(false);\n return data;\n }\n\n subscribe(fn) {\n this.subscriber = fn;\n }\n\n cancel() {\n this.controller.abort();\n this.pendingKeys.forEach((v, k) => this.pendingKeys.delete(k));\n let subscriber = this.subscriber;\n subscriber && subscriber(true);\n }\n\n async resolveData(signal) {\n let aborted = false;\n\n if (!this.done) {\n let onAbort = () => this.cancel();\n\n signal.addEventListener(\"abort\", onAbort);\n aborted = await new Promise(resolve => {\n this.subscribe(aborted => {\n signal.removeEventListener(\"abort\", onAbort);\n\n if (aborted || this.done) {\n resolve(aborted);\n }\n });\n });\n }\n\n return aborted;\n }\n\n get done() {\n return this.pendingKeys.size === 0;\n }\n\n get unwrappedData() {\n invariant(this.data !== null && this.done, \"Can only unwrap data on initialized and settled deferreds\");\n return Object.entries(this.data).reduce((acc, _ref2) => {\n let [key, value] = _ref2;\n return Object.assign(acc, {\n [key]: unwrapTrackedPromise(value)\n });\n }, {});\n }\n\n}\n\nfunction isTrackedPromise(value) {\n return value instanceof Promise && value._tracked === true;\n}\n\nfunction unwrapTrackedPromise(value) {\n if (!isTrackedPromise(value)) {\n return value;\n }\n\n if (value._error) {\n throw value._error;\n }\n\n return value._data;\n}\n\nfunction defer(data) {\n return new DeferredData(data);\n}\n/**\n * A redirect response. Sets the status code and the `Location` header.\n * Defaults to \"302 Found\".\n */\n\nconst redirect = function redirect(url, init) {\n if (init === void 0) {\n init = 302;\n }\n\n let responseInit = init;\n\n if (typeof responseInit === \"number\") {\n responseInit = {\n status: responseInit\n };\n } else if (typeof responseInit.status === \"undefined\") {\n responseInit.status = 302;\n }\n\n let headers = new Headers(responseInit.headers);\n headers.set(\"Location\", url);\n return new Response(null, _extends({}, responseInit, {\n headers\n }));\n};\n/**\n * @private\n * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies\n */\n\nclass ErrorResponse {\n constructor(status, statusText, data, internal) {\n if (internal === void 0) {\n internal = false;\n }\n\n this.status = status;\n this.statusText = statusText || \"\";\n this.internal = internal;\n\n if (data instanceof Error) {\n this.data = data.toString();\n this.error = data;\n } else {\n this.data = data;\n }\n }\n\n}\n/**\n * Check if the given error is an ErrorResponse generated from a 4xx/5xx\n * Response throw from an action/loader\n */\n\nfunction isRouteErrorResponse(e) {\n return e instanceof ErrorResponse;\n}\n\nconst validMutationMethodsArr = [\"post\", \"put\", \"patch\", \"delete\"];\nconst validMutationMethods = new Set(validMutationMethodsArr);\nconst validRequestMethodsArr = [\"get\", ...validMutationMethodsArr];\nconst validRequestMethods = new Set(validRequestMethodsArr);\nconst redirectStatusCodes = new Set([301, 302, 303, 307, 308]);\nconst redirectPreserveMethodStatusCodes = new Set([307, 308]);\nconst IDLE_NAVIGATION = {\n state: \"idle\",\n location: undefined,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined\n};\nconst IDLE_FETCHER = {\n state: \"idle\",\n data: undefined,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined\n};\nconst isBrowser = typeof window !== \"undefined\" && typeof window.document !== \"undefined\" && typeof window.document.createElement !== \"undefined\";\nconst isServer = !isBrowser; //#endregion\n////////////////////////////////////////////////////////////////////////////////\n//#region createRouter\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Create a router and listen to history POP navigations\n */\n\nfunction createRouter(init) {\n invariant(init.routes.length > 0, \"You must provide a non-empty routes array to createRouter\");\n let dataRoutes = convertRoutesToDataRoutes(init.routes); // Cleanup function for history\n\n let unlistenHistory = null; // Externally-provided functions to call on all state changes\n\n let subscribers = new Set(); // Externally-provided object to hold scroll restoration locations during routing\n\n let savedScrollPositions = null; // Externally-provided function to get scroll restoration keys\n\n let getScrollRestorationKey = null; // Externally-provided function to get current scroll position\n\n let getScrollPosition = null; // One-time flag to control the initial hydration scroll restoration. Because\n // we don't get the saved positions from <ScrollRestoration /> until _after_\n // the initial render, we need to manually trigger a separate updateState to\n // send along the restoreScrollPosition\n // Set to true if we have `hydrationData` since we assume we were SSR'd and that\n // SSR did the initial scroll restoration.\n\n let initialScrollRestored = init.hydrationData != null;\n let initialMatches = matchRoutes(dataRoutes, init.history.location, init.basename);\n let initialErrors = null;\n\n if (initialMatches == null) {\n // If we do not match a user-provided-route, fall back to the root\n // to allow the error boundary to take over\n let error = getInternalRouterError(404, {\n pathname: init.history.location.pathname\n });\n let {\n matches,\n route\n } = getShortCircuitMatches(dataRoutes);\n initialMatches = matches;\n initialErrors = {\n [route.id]: error\n };\n }\n\n let initialized = !initialMatches.some(m => m.route.loader) || init.hydrationData != null;\n let router;\n let state = {\n historyAction: init.history.action,\n location: init.history.location,\n matches: initialMatches,\n initialized,\n navigation: IDLE_NAVIGATION,\n // Don't restore on initial updateState() if we were SSR'd\n restoreScrollPosition: init.hydrationData != null ? false : null,\n preventScrollReset: false,\n revalidation: \"idle\",\n loaderData: init.hydrationData && init.hydrationData.loaderData || {},\n actionData: init.hydrationData && init.hydrationData.actionData || null,\n errors: init.hydrationData && init.hydrationData.errors || initialErrors,\n fetchers: new Map()\n }; // -- Stateful internal variables to manage navigations --\n // Current navigation in progress (to be committed in completeNavigation)\n\n let pendingAction = Action.Pop; // Should the current navigation prevent the scroll reset if scroll cannot\n // be restored?\n\n let pendingPreventScrollReset = false; // AbortController for the active navigation\n\n let pendingNavigationController; // We use this to avoid touching history in completeNavigation if a\n // revalidation is entirely uninterrupted\n\n let isUninterruptedRevalidation = false; // Use this internal flag to force revalidation of all loaders:\n // - submissions (completed or interrupted)\n // - useRevalidate()\n // - X-Remix-Revalidate (from redirect)\n\n let isRevalidationRequired = false; // Use this internal array to capture routes that require revalidation due\n // to a cancelled deferred on action submission\n\n let cancelledDeferredRoutes = []; // Use this internal array to capture fetcher loads that were cancelled by an\n // action navigation and require revalidation\n\n let cancelledFetcherLoads = []; // AbortControllers for any in-flight fetchers\n\n let fetchControllers = new Map(); // Track loads based on the order in which they started\n\n let incrementingLoadId = 0; // Track the outstanding pending navigation data load to be compared against\n // the globally incrementing load when a fetcher load lands after a completed\n // navigation\n\n let pendingNavigationLoadId = -1; // Fetchers that triggered data reloads as a result of their actions\n\n let fetchReloadIds = new Map(); // Fetchers that triggered redirect navigations from their actions\n\n let fetchRedirectIds = new Set(); // Most recent href/match for fetcher.load calls for fetchers\n\n let fetchLoadMatches = new Map(); // Store DeferredData instances for active route matches. When a\n // route loader returns defer() we stick one in here. Then, when a nested\n // promise resolves we update loaderData. If a new navigation starts we\n // cancel active deferreds for eliminated routes.\n\n let activeDeferreds = new Map(); // Initialize the router, all side effects should be kicked off from here.\n // Implemented as a Fluent API for ease of:\n // let router = createRouter(init).initialize();\n\n function initialize() {\n // If history informs us of a POP navigation, start the navigation but do not update\n // state. We'll update our own state once the navigation completes\n unlistenHistory = init.history.listen(_ref => {\n let {\n action: historyAction,\n location\n } = _ref;\n return startNavigation(historyAction, location);\n }); // Kick off initial data load if needed. Use Pop to avoid modifying history\n\n if (!state.initialized) {\n startNavigation(Action.Pop, state.location);\n }\n\n return router;\n } // Clean up a router and it's side effects\n\n\n function dispose() {\n if (unlistenHistory) {\n unlistenHistory();\n }\n\n subscribers.clear();\n pendingNavigationController && pendingNavigationController.abort();\n state.fetchers.forEach((_, key) => deleteFetcher(key));\n } // Subscribe to state updates for the router\n\n\n function subscribe(fn) {\n subscribers.add(fn);\n return () => subscribers.delete(fn);\n } // Update our state and notify the calling context of the change\n\n\n function updateState(newState) {\n state = _extends({}, state, newState);\n subscribers.forEach(subscriber => subscriber(state));\n } // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION\n // and setting state.[historyAction/location/matches] to the new route.\n // - Location is a required param\n // - Navigation will always be set to IDLE_NAVIGATION\n // - Can pass any other state in newState\n\n\n function completeNavigation(location, newState) {\n var _state$navigation$for;\n\n // Deduce if we're in a loading/actionReload state:\n // - We have committed actionData in the store\n // - The current navigation was a submission\n // - We're past the submitting state and into the loading state\n // - The location we've finished loading is different from the submission\n // location, indicating we redirected from the action (avoids false\n // positives for loading/submissionRedirect when actionData returned\n // on a prior submission)\n let isActionReload = state.actionData != null && state.navigation.formMethod != null && state.navigation.state === \"loading\" && ((_state$navigation$for = state.navigation.formAction) == null ? void 0 : _state$navigation$for.split(\"?\")[0]) === location.pathname;\n let actionData;\n\n if (newState.actionData) {\n if (Object.keys(newState.actionData).length > 0) {\n actionData = newState.actionData;\n } else {\n // Empty actionData -> clear prior actionData due to an action error\n actionData = null;\n }\n } else if (isActionReload) {\n // Keep the current data if we're wrapping up the action reload\n actionData = state.actionData;\n } else {\n // Clear actionData on any other completed navigations\n actionData = null;\n } // Always preserve any existing loaderData from re-used routes\n\n\n let loaderData = newState.loaderData ? mergeLoaderData(state.loaderData, newState.loaderData, newState.matches || [], newState.errors) : state.loaderData;\n updateState(_extends({}, newState, {\n actionData,\n loaderData,\n historyAction: pendingAction,\n location,\n initialized: true,\n navigation: IDLE_NAVIGATION,\n revalidation: \"idle\",\n // Don't restore on submission navigations\n restoreScrollPosition: state.navigation.formData ? false : getSavedScrollPosition(location, newState.matches || state.matches),\n preventScrollReset: pendingPreventScrollReset\n }));\n\n if (isUninterruptedRevalidation) ; else if (pendingAction === Action.Pop) ; else if (pendingAction === Action.Push) {\n init.history.push(location, location.state);\n } else if (pendingAction === Action.Replace) {\n init.history.replace(location, location.state);\n } // Reset stateful navigation vars\n\n\n pendingAction = Action.Pop;\n pendingPreventScrollReset = false;\n isUninterruptedRevalidation = false;\n isRevalidationRequired = false;\n cancelledDeferredRoutes = [];\n cancelledFetcherLoads = [];\n } // Trigger a navigation event, which can either be a numerical POP or a PUSH\n // replace with an optional submission\n\n\n async function navigate(to, opts) {\n if (typeof to === \"number\") {\n init.history.go(to);\n return;\n }\n\n let {\n path,\n submission,\n error\n } = normalizeNavigateOptions(to, opts);\n let location = createLocation(state.location, path, opts && opts.state); // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded\n // URL from window.location, so we need to encode it here so the behavior\n // remains the same as POP and non-data-router usages. new URL() does all\n // the same encoding we'd get from a history.pushState/window.location read\n // without having to touch history\n\n location = _extends({}, location, init.history.encodeLocation(location));\n let userReplace = opts && opts.replace != null ? opts.replace : undefined;\n let historyAction = Action.Push;\n\n if (userReplace === true) {\n historyAction = Action.Replace;\n } else if (userReplace === false) ; else if (submission != null && isMutationMethod(submission.formMethod) && submission.formAction === state.location.pathname + state.location.search) {\n // By default on submissions to the current location we REPLACE so that\n // users don't have to double-click the back button to get to the prior\n // location. If the user redirects to a different location from the\n // action/loader this will be ignored and the redirect will be a PUSH\n historyAction = Action.Replace;\n }\n\n let preventScrollReset = opts && \"preventScrollReset\" in opts ? opts.preventScrollReset === true : undefined;\n return await startNavigation(historyAction, location, {\n submission,\n // Send through the formData serialization error if we have one so we can\n // render at the right error boundary after we match routes\n pendingError: error,\n preventScrollReset,\n replace: opts && opts.replace\n });\n } // Revalidate all current loaders. If a navigation is in progress or if this\n // is interrupted by a navigation, allow this to \"succeed\" by calling all\n // loaders during the next loader round\n\n\n function revalidate() {\n interruptActiveLoads();\n updateState({\n revalidation: \"loading\"\n }); // If we're currently submitting an action, we don't need to start a new\n // navigation, we'll just let the follow up loader execution call all loaders\n\n if (state.navigation.state === \"submitting\") {\n return;\n } // If we're currently in an idle state, start a new navigation for the current\n // action/location and mark it as uninterrupted, which will skip the history\n // update in completeNavigation\n\n\n if (state.navigation.state === \"idle\") {\n startNavigation(state.historyAction, state.location, {\n startUninterruptedRevalidation: true\n });\n return;\n } // Otherwise, if we're currently in a loading state, just start a new\n // navigation to the navigation.location but do not trigger an uninterrupted\n // revalidation so that history correctly updates once the navigation completes\n\n\n startNavigation(pendingAction || state.historyAction, state.navigation.location, {\n overrideNavigation: state.navigation\n });\n } // Start a navigation to the given action/location. Can optionally provide a\n // overrideNavigation which will override the normalLoad in the case of a redirect\n // navigation\n\n\n async function startNavigation(historyAction, location, opts) {\n // Abort any in-progress navigations and start a new one. Unset any ongoing\n // uninterrupted revalidations unless told otherwise, since we want this\n // new navigation to update history normally\n pendingNavigationController && pendingNavigationController.abort();\n pendingNavigationController = null;\n pendingAction = historyAction;\n isUninterruptedRevalidation = (opts && opts.startUninterruptedRevalidation) === true; // Save the current scroll position every time we start a new navigation,\n // and track whether we should reset scroll on completion\n\n saveScrollPosition(state.location, state.matches);\n pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;\n let loadingNavigation = opts && opts.overrideNavigation;\n let matches = matchRoutes(dataRoutes, location, init.basename); // Short circuit with a 404 on the root error boundary if we match nothing\n\n if (!matches) {\n let error = getInternalRouterError(404, {\n pathname: location.pathname\n });\n let {\n matches: notFoundMatches,\n route\n } = getShortCircuitMatches(dataRoutes); // Cancel all pending deferred on 404s since we don't keep any routes\n\n cancelActiveDeferreds();\n completeNavigation(location, {\n matches: notFoundMatches,\n loaderData: {},\n errors: {\n [route.id]: error\n }\n });\n return;\n } // Short circuit if it's only a hash change\n\n\n if (isHashChangeOnly(state.location, location)) {\n completeNavigation(location, {\n matches\n });\n return;\n } // Create a controller/Request for this navigation\n\n\n pendingNavigationController = new AbortController();\n let request = createClientSideRequest(location, pendingNavigationController.signal, opts && opts.submission);\n let pendingActionData;\n let pendingError;\n\n if (opts && opts.pendingError) {\n // If we have a pendingError, it means the user attempted a GET submission\n // with binary FormData so assign here and skip to handleLoaders. That\n // way we handle calling loaders above the boundary etc. It's not really\n // different from an actionError in that sense.\n pendingError = {\n [findNearestBoundary(matches).route.id]: opts.pendingError\n };\n } else if (opts && opts.submission && isMutationMethod(opts.submission.formMethod)) {\n // Call action if we received an action submission\n let actionOutput = await handleAction(request, location, opts.submission, matches, {\n replace: opts.replace\n });\n\n if (actionOutput.shortCircuited) {\n return;\n }\n\n pendingActionData = actionOutput.pendingActionData;\n pendingError = actionOutput.pendingActionError;\n\n let navigation = _extends({\n state: \"loading\",\n location\n }, opts.submission);\n\n loadingNavigation = navigation; // Create a GET request for the loaders\n\n request = new Request(request.url, {\n signal: request.signal\n });\n } // Call loaders\n\n\n let {\n shortCircuited,\n loaderData,\n errors\n } = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.replace, pendingActionData, pendingError);\n\n if (shortCircuited) {\n return;\n } // Clean up now that the action/loaders have completed. Don't clean up if\n // we short circuited because pendingNavigationController will have already\n // been assigned to a new controller for the next navigation\n\n\n pendingNavigationController = null;\n completeNavigation(location, _extends({\n matches\n }, pendingActionData ? {\n actionData: pendingActionData\n } : {}, {\n loaderData,\n errors\n }));\n } // Call the action matched by the leaf route for this navigation and handle\n // redirects/errors\n\n\n async function handleAction(request, location, submission, matches, opts) {\n interruptActiveLoads(); // Put us in a submitting state\n\n let navigation = _extends({\n state: \"submitting\",\n location\n }, submission);\n\n updateState({\n navigation\n }); // Call our action and get the result\n\n let result;\n let actionMatch = getTargetMatch(matches, location);\n\n if (!actionMatch.route.action) {\n result = {\n type: ResultType.error,\n error: getInternalRouterError(405, {\n method: request.method,\n pathname: location.pathname,\n routeId: actionMatch.route.id\n })\n };\n } else {\n result = await callLoaderOrAction(\"action\", request, actionMatch, matches, router.basename);\n\n if (request.signal.aborted) {\n return {\n shortCircuited: true\n };\n }\n }\n\n if (isRedirectResult(result)) {\n let replace;\n\n if (opts && opts.replace != null) {\n replace = opts.replace;\n } else {\n // If the user didn't explicity indicate replace behavior, replace if\n // we redirected to the exact same location we're currently at to avoid\n // double back-buttons\n replace = result.location === state.location.pathname + state.location.search;\n }\n\n await startRedirectNavigation(state, result, replace);\n return {\n shortCircuited: true\n };\n }\n\n if (isErrorResult(result)) {\n // Store off the pending error - we use it to determine which loaders\n // to call and will commit it when we complete the navigation\n let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id); // By default, all submissions are REPLACE navigations, but if the\n // action threw an error that'll be rendered in an errorElement, we fall\n // back to PUSH so that the user can use the back button to get back to\n // the pre-submission form location to try again\n\n if ((opts && opts.replace) !== true) {\n pendingAction = Action.Push;\n }\n\n return {\n // Send back an empty object we can use to clear out any prior actionData\n pendingActionData: {},\n pendingActionError: {\n [boundaryMatch.route.id]: result.error\n }\n };\n }\n\n if (isDeferredResult(result)) {\n throw new Error(\"defer() is not supported in actions\");\n }\n\n return {\n pendingActionData: {\n [actionMatch.route.id]: result.data\n }\n };\n } // Call all applicable loaders for the given matches, handling redirects,\n // errors, etc.\n\n\n async function handleLoaders(request, location, matches, overrideNavigation, submission, replace, pendingActionData, pendingError) {\n // Figure out the right navigation we want to use for data loading\n let loadingNavigation = overrideNavigation;\n\n if (!loadingNavigation) {\n let navigation = _extends({\n state: \"loading\",\n location,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined\n }, submission);\n\n loadingNavigation = navigation;\n }\n\n let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches); // Cancel pending deferreds for no-longer-matched routes or routes we're\n // about to reload. Note that if this is an action reload we would have\n // already cancelled all pending deferreds so this would be a no-op\n\n cancelActiveDeferreds(routeId => !(matches && matches.some(m => m.route.id === routeId)) || matchesToLoad && matchesToLoad.some(m => m.route.id === routeId)); // Short circuit if we have no loaders to run\n\n if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {\n completeNavigation(location, _extends({\n matches,\n loaderData: {},\n // Commit pending error if we're short circuiting\n errors: pendingError || null\n }, pendingActionData ? {\n actionData: pendingActionData\n } : {}));\n return {\n shortCircuited: true\n };\n } // If this is an uninterrupted revalidation, we remain in our current idle\n // state. If not, we need to switch to our loading state and load data,\n // preserving any new action data or existing action data (in the case of\n // a revalidation interrupting an actionReload)\n\n\n if (!isUninterruptedRevalidation) {\n revalidatingFetchers.forEach(_ref2 => {\n let [key] = _ref2;\n let fetcher = state.fetchers.get(key);\n let revalidatingFetcher = {\n state: \"loading\",\n data: fetcher && fetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true\n };\n state.fetchers.set(key, revalidatingFetcher);\n });\n let actionData = pendingActionData || state.actionData;\n updateState(_extends({\n navigation: loadingNavigation\n }, actionData ? Object.keys(actionData).length === 0 ? {\n actionData: null\n } : {\n actionData\n } : {}, revalidatingFetchers.length > 0 ? {\n fetchers: new Map(state.fetchers)\n } : {}));\n }\n\n pendingNavigationLoadId = ++incrementingLoadId;\n revalidatingFetchers.forEach(_ref3 => {\n let [key] = _ref3;\n return fetchControllers.set(key, pendingNavigationController);\n });\n let {\n results,\n loaderResults,\n fetcherResults\n } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, request);\n\n if (request.signal.aborted) {\n return {\n shortCircuited: true\n };\n } // Clean up _after_ loaders have completed. Don't clean up if we short\n // circuited because fetchControllers would have been aborted and\n // reassigned to new controllers for the next navigation\n\n\n revalidatingFetchers.forEach(_ref4 => {\n let [key] = _ref4;\n return fetchControllers.delete(key);\n }); // If any loaders returned a redirect Response, start a new REPLACE navigation\n\n let redirect = findRedirect(results);\n\n if (redirect) {\n await startRedirectNavigation(state, redirect, replace);\n return {\n shortCircuited: true\n };\n } // Process and commit output from loaders\n\n\n let {\n loaderData,\n errors\n } = processLoaderData(state, matches, matchesToLoad, loaderResults, pendingError, revalidatingFetchers, fetcherResults, activeDeferreds); // Wire up subscribers to update loaderData as promises settle\n\n activeDeferreds.forEach((deferredData, routeId) => {\n deferredData.subscribe(aborted => {\n // Note: No need to updateState here since the TrackedPromise on\n // loaderData is stable across resolve/reject\n // Remove this instance if we were aborted or if promises have settled\n if (aborted || deferredData.done) {\n activeDeferreds.delete(routeId);\n }\n });\n });\n markFetchRedirectsDone();\n let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);\n return _extends({\n loaderData,\n errors\n }, didAbortFetchLoads || revalidatingFetchers.length > 0 ? {\n fetchers: new Map(state.fetchers)\n } : {});\n }\n\n function getFetcher(key) {\n return state.fetchers.get(key) || IDLE_FETCHER;\n } // Trigger a fetcher load/submit for the given fetcher key\n\n\n function fetch(key, routeId, href, opts) {\n if (isServer) {\n throw new Error(\"router.fetch() was called during the server render, but it shouldn't be. \" + \"You are likely calling a useFetcher() method in the body of your component. \" + \"Try moving it to a useEffect or a callback.\");\n }\n\n if (fetchControllers.has(key)) abortFetcher(key);\n let matches = matchRoutes(dataRoutes, href, init.basename);\n\n if (!matches) {\n setFetcherError(key, routeId, getInternalRouterError(404, {\n pathname: href\n }));\n return;\n }\n\n let {\n path,\n submission\n } = normalizeNavigateOptions(href, opts, true);\n let match = getTargetMatch(matches, path);\n\n if (submission && isMutationMethod(submission.formMethod)) {\n handleFetcherAction(key, routeId, path, match, matches, submission);\n return;\n } // Store off the match so we can call it's shouldRevalidate on subsequent\n // revalidations\n\n\n fetchLoadMatches.set(key, [path, match, matches]);\n handleFetcherLoader(key, routeId, path, match, matches, submission);\n } // Call the action for the matched fetcher.submit(), and then handle redirects,\n // errors, and revalidation\n\n\n async function handleFetcherAction(key, routeId, path, match, requestMatches, submission) {\n interruptActiveLoads();\n fetchLoadMatches.delete(key);\n\n if (!match.route.action) {\n let error = getInternalRouterError(405, {\n method: submission.formMethod,\n pathname: path,\n routeId: routeId\n });\n setFetcherError(key, routeId, error);\n return;\n } // Put this fetcher into it's submitting state\n\n\n let existingFetcher = state.fetchers.get(key);\n\n let fetcher = _extends({\n state: \"submitting\"\n }, submission, {\n data: existingFetcher && existingFetcher.data,\n \" _hasFetcherDoneAnything \": true\n });\n\n state.fetchers.set(key, fetcher);\n updateState({\n fetchers: new Map(state.fetchers)\n }); // Call the action for the fetcher\n\n let abortController = new AbortController();\n let fetchRequest = createClientSideRequest(path, abortController.signal, submission);\n fetchControllers.set(key, abortController);\n let actionResult = await callLoaderOrAction(\"action\", fetchRequest, match, requestMatches, router.basename);\n\n if (fetchRequest.signal.aborted) {\n // We can delete this so long as we weren't aborted by ou our own fetcher\n // re-submit which would have put _new_ controller is in fetchControllers\n if (fetchControllers.get(key) === abortController) {\n fetchControllers.delete(key);\n }\n\n return;\n }\n\n if (isRedirectResult(actionResult)) {\n fetchControllers.delete(key);\n fetchRedirectIds.add(key);\n\n let loadingFetcher = _extends({\n state: \"loading\"\n }, submission, {\n data: undefined,\n \" _hasFetcherDoneAnything \": true\n });\n\n state.fetchers.set(key, loadingFetcher);\n updateState({\n fetchers: new Map(state.fetchers)\n });\n return startRedirectNavigation(state, actionResult, false, true);\n } // Process any non-redirect errors thrown\n\n\n if (isErrorResult(actionResult)) {\n setFetcherError(key, routeId, actionResult.error);\n return;\n }\n\n if (isDeferredResult(actionResult)) {\n invariant(false, \"defer() is not supported in actions\");\n } // Start the data load for current matches, or the next location if we're\n // in the middle of a navigation\n\n\n let nextLocation = state.navigation.location || state.location;\n let revalidationRequest = createClientSideRequest(nextLocation, abortController.signal);\n let matches = state.navigation.state !== \"idle\" ? matchRoutes(dataRoutes, state.navigation.location, init.basename) : state.matches;\n invariant(matches, \"Didn't find any matches after fetcher action\");\n let loadId = ++incrementingLoadId;\n fetchReloadIds.set(key, loadId);\n\n let loadFetcher = _extends({\n state: \"loading\",\n data: actionResult.data\n }, submission, {\n \" _hasFetcherDoneAnything \": true\n });\n\n state.fetchers.set(key, loadFetcher);\n let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, {\n [match.route.id]: actionResult.data\n }, undefined, // No need to send through errors since we short circuit above\n fetchLoadMatches); // Put all revalidating fetchers into the loading state, except for the\n // current fetcher which we want to keep in it's current loading state which\n // contains it's action submission info + action data\n\n revalidatingFetchers.filter(_ref5 => {\n let [staleKey] = _ref5;\n return staleKey !== key;\n }).forEach(_ref6 => {\n let [staleKey] = _ref6;\n let existingFetcher = state.fetchers.get(staleKey);\n let revalidatingFetcher = {\n state: \"loading\",\n data: existingFetcher && existingFetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true\n };\n state.fetchers.set(staleKey, revalidatingFetcher);\n fetchControllers.set(staleKey, abortController);\n });\n updateState({\n fetchers: new Map(state.fetchers)\n });\n let {\n results,\n loaderResults,\n fetcherResults\n } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, revalidationRequest);\n\n if (abortController.signal.aborted) {\n return;\n }\n\n fetchReloadIds.delete(key);\n fetchControllers.delete(key);\n revalidatingFetchers.forEach(_ref7 => {\n let [staleKey] = _ref7;\n return fetchControllers.delete(staleKey);\n });\n let redirect = findRedirect(results);\n\n if (redirect) {\n return startRedirectNavigation(state, redirect);\n } // Process and commit output from loaders\n\n\n let {\n loaderData,\n errors\n } = processLoaderData(state, state.matches, matchesToLoad, loaderResults, undefined, revalidatingFetchers, fetcherResults, activeDeferreds);\n let doneFetcher = {\n state: \"idle\",\n data: actionResult.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true\n };\n state.fetchers.set(key, doneFetcher);\n let didAbortFetchLoads = abortStaleFetchLoads(loadId); // If we are currently in a navigation loading state and this fetcher is\n // more recent than the navigation, we want the newer data so abort the\n // navigation and complete it with the fetcher data\n\n if (state.navigation.state === \"loading\" && loadId > pendingNavigationLoadId) {\n invariant(pendingAction, \"Expected pending action\");\n pendingNavigationController && pendingNavigationController.abort();\n completeNavigation(state.navigation.location, {\n matches,\n loaderData,\n errors,\n fetchers: new Map(state.fetchers)\n });\n } else {\n // otherwise just update with the fetcher data, preserving any existing\n // loaderData for loaders that did not need to reload. We have to\n // manually merge here since we aren't going through completeNavigation\n updateState(_extends({\n errors,\n loaderData: mergeLoaderData(state.loaderData, loaderData, matches, errors)\n }, didAbortFetchLoads ? {\n fetchers: new Map(state.fetchers)\n } : {}));\n isRevalidationRequired = false;\n }\n } // Call the matched loader for fetcher.load(), handling redirects, errors, etc.\n\n\n async function handleFetcherLoader(key, routeId, path, match, matches, submission) {\n let existingFetcher = state.fetchers.get(key); // Put this fetcher into it's loading state\n\n let loadingFetcher = _extends({\n state: \"loading\",\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined\n }, submission, {\n data: existingFetcher && existingFetcher.data,\n \" _hasFetcherDoneAnything \": true\n });\n\n state.fetchers.set(key, loadingFetcher);\n updateState({\n fetchers: new Map(state.fetchers)\n }); // Call the loader for this fetcher route match\n\n let abortController = new AbortController();\n let fetchRequest = createClientSideRequest(path, abortController.signal);\n fetchControllers.set(key, abortController);\n let result = await callLoaderOrAction(\"loader\", fetchRequest, match, matches, router.basename); // Deferred isn't supported or fetcher loads, await everything and treat it\n // as a normal load. resolveDeferredData will return undefined if this\n // fetcher gets aborted, so we just leave result untouched and short circuit\n // below if that happens\n\n if (isDeferredResult(result)) {\n result = (await resolveDeferredData(result, fetchRequest.signal, true)) || result;\n } // We can delete this so long as we weren't aborted by ou our own fetcher\n // re-load which would have put _new_ controller is in fetchControllers\n\n\n if (fetchControllers.get(key) === abortController) {\n fetchControllers.delete(key);\n }\n\n if (fetchRequest.signal.aborted) {\n return;\n } // If the loader threw a redirect Response, start a new REPLACE navigation\n\n\n if (isRedirectResult(result)) {\n await startRedirectNavigation(state, result);\n return;\n } // Process any non-redirect errors thrown\n\n\n if (isErrorResult(result)) {\n let boundaryMatch = findNearestBoundary(state.matches, routeId);\n state.fetchers.delete(key); // TODO: In remix, this would reset to IDLE_NAVIGATION if it was a catch -\n // do we need to behave any differently with our non-redirect errors?\n // What if it was a non-redirect Response?\n\n updateState({\n fetchers: new Map(state.fetchers),\n errors: {\n [boundaryMatch.route.id]: result.error\n }\n });\n return;\n }\n\n invariant(!isDeferredResult(result), \"Unhandled fetcher deferred data\"); // Put the fetcher back into an idle state\n\n let doneFetcher = {\n state: \"idle\",\n data: result.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true\n };\n state.fetchers.set(key, doneFetcher);\n updateState({\n fetchers: new Map(state.fetchers)\n });\n }\n /**\n * Utility function to handle redirects returned from an action or loader.\n * Normally, a redirect \"replaces\" the navigation that triggered it. So, for\n * example:\n *\n * - user is on /a\n * - user clicks a link to /b\n * - loader for /b redirects to /c\n *\n * In a non-JS app the browser would track the in-flight navigation to /b and\n * then replace it with /c when it encountered the redirect response. In\n * the end it would only ever update the URL bar with /c.\n *\n * In client-side routing using pushState/replaceState, we aim to emulate\n * this behavior and we also do not update history until the end of the\n * navigation (including processed redirects). This means that we never\n * actually touch history until we've processed redirects, so we just use\n * the history action from the original navigation (PUSH or REPLACE).\n */\n\n\n async function startRedirectNavigation(state, redirect, replace, isFetchActionRedirect) {\n var _window;\n\n if (redirect.revalidate) {\n isRevalidationRequired = true;\n }\n\n let redirectLocation = createLocation(state.location, redirect.location, // TODO: This can be removed once we get rid of useTransition in Remix v2\n _extends({\n _isRedirect: true\n }, isFetchActionRedirect ? {\n _isFetchActionRedirect: true\n } : {}));\n invariant(redirectLocation, \"Expected a location on the redirect navigation\"); // Check if this an external redirect that goes to a new origin\n\n if (typeof ((_window = window) == null ? void 0 : _window.location) !== \"undefined\") {\n let newOrigin = createClientSideURL(redirect.location).origin;\n\n if (window.location.origin !== newOrigin) {\n if (replace) {\n window.location.replace(redirect.location);\n } else {\n window.location.assign(redirect.location);\n }\n\n return;\n }\n } // There's no need to abort on redirects, since we don't detect the\n // redirect until the action/loaders have settled\n\n\n pendingNavigationController = null;\n let redirectHistoryAction = replace === true ? Action.Replace : Action.Push;\n let {\n formMethod,\n formAction,\n formEncType,\n formData\n } = state.navigation; // If this was a 307/308 submission we want to preserve the HTTP method and\n // re-submit the GET/POST/PUT/PATCH/DELETE as a submission navigation to the\n // redirected location\n\n if (redirectPreserveMethodStatusCodes.has(redirect.status) && formMethod && isMutationMethod(formMethod) && formEncType && formData) {\n await startNavigation(redirectHistoryAction, redirectLocation, {\n submission: {\n formMethod,\n formAction: redirect.location,\n formEncType,\n formData\n }\n });\n } else {\n // Otherwise, we kick off a new loading navigation, preserving the\n // submission info for the duration of this navigation\n await startNavigation(redirectHistoryAction, redirectLocation, {\n overrideNavigation: {\n state: \"loading\",\n location: redirectLocation,\n formMethod: formMethod || undefined,\n formAction: formAction || undefined,\n formEncType: formEncType || undefined,\n formData: formData || undefined\n }\n });\n }\n }\n\n async function callLoadersAndMaybeResolveData(currentMatches, matches, matchesToLoad, fetchersToLoad, request) {\n // Call all navigation loaders and revalidating fetcher loaders in parallel,\n // then slice off the results into separate arrays so we can handle them\n // accordingly\n let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction(\"loader\", request, match, matches, router.basename)), ...fetchersToLoad.map(_ref8 => {\n let [, href, match, fetchMatches] = _ref8;\n return callLoaderOrAction(\"loader\", createClientSideRequest(href, request.signal), match, fetchMatches, router.basename);\n })]);\n let loaderResults = results.slice(0, matchesToLoad.length);\n let fetcherResults = results.slice(matchesToLoad.length);\n await Promise.all([resolveDeferredResults(currentMatches, matchesToLoad, loaderResults, request.signal, false, state.loaderData), resolveDeferredResults(currentMatches, fetchersToLoad.map(_ref9 => {\n let [,, match] = _ref9;\n return match;\n }), fetcherResults, request.signal, true)]);\n return {\n results,\n loaderResults,\n fetcherResults\n };\n }\n\n function interruptActiveLoads() {\n // Every interruption triggers a revalidation\n isRevalidationRequired = true; // Cancel pending route-level deferreds and mark cancelled routes for\n // revalidation\n\n cancelledDeferredRoutes.push(...cancelActiveDeferreds()); // Abort in-flight fetcher loads\n\n fetchLoadMatches.forEach((_, key) => {\n if (fetchControllers.has(key)) {\n cancelledFetcherLoads.push(key);\n abortFetcher(key);\n }\n });\n }\n\n function setFetcherError(key, routeId, error) {\n let boundaryMatch = findNearestBoundary(state.matches, routeId);\n deleteFetcher(key);\n updateState({\n errors: {\n [boundaryMatch.route.id]: error\n },\n fetchers: new Map(state.fetchers)\n });\n }\n\n function deleteFetcher(key) {\n if (fetchControllers.has(key)) abortFetcher(key);\n fetchLoadMatches.delete(key);\n fetchReloadIds.delete(key);\n fetchRedirectIds.delete(key);\n state.fetchers.delete(key);\n }\n\n function abortFetcher(key) {\n let controller = fetchControllers.get(key);\n invariant(controller, \"Expected fetch controller: \" + key);\n controller.abort();\n fetchControllers.delete(key);\n }\n\n function markFetchersDone(keys) {\n for (let key of keys) {\n let fetcher = getFetcher(key);\n let doneFetcher = {\n state: \"idle\",\n data: fetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true\n };\n state.fetchers.set(key, doneFetcher);\n }\n }\n\n function markFetchRedirectsDone() {\n let doneKeys = [];\n\n for (let key of fetchRedirectIds) {\n let fetcher = state.fetchers.get(key);\n invariant(fetcher, \"Expected fetcher: \" + key);\n\n if (fetcher.state === \"loading\") {\n fetchRedirectIds.delete(key);\n doneKeys.push(key);\n }\n }\n\n markFetchersDone(doneKeys);\n }\n\n function abortStaleFetchLoads(landedId) {\n let yeetedKeys = [];\n\n for (let [key, id] of fetchReloadIds) {\n if (id < landedId) {\n let fetcher = state.fetchers.get(key);\n invariant(fetcher, \"Expected fetcher: \" + key);\n\n if (fetcher.state === \"loading\") {\n abortFetcher(key);\n fetchReloadIds.delete(key);\n yeetedKeys.push(key);\n }\n }\n }\n\n markFetchersDone(yeetedKeys);\n return yeetedKeys.length > 0;\n }\n\n function cancelActiveDeferreds(predicate) {\n let cancelledRouteIds = [];\n activeDeferreds.forEach((dfd, routeId) => {\n if (!predicate || predicate(routeId)) {\n // Cancel the deferred - but do not remove from activeDeferreds here -\n // we rely on the subscribers to do that so our tests can assert proper\n // cleanup via _internalActiveDeferreds\n dfd.cancel();\n cancelledRouteIds.push(routeId);\n activeDeferreds.delete(routeId);\n }\n });\n return cancelledRouteIds;\n } // Opt in to capturing and reporting scroll positions during navigations,\n // used by the <ScrollRestoration> component\n\n\n function enableScrollRestoration(positions, getPosition, getKey) {\n savedScrollPositions = positions;\n getScrollPosition = getPosition;\n\n getScrollRestorationKey = getKey || (location => location.key); // Perform initial hydration scroll restoration, since we miss the boat on\n // the initial updateState() because we've not yet rendered <ScrollRestoration/>\n // and therefore have no savedScrollPositions available\n\n\n if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) {\n initialScrollRestored = true;\n let y = getSavedScrollPosition(state.location, state.matches);\n\n if (y != null) {\n updateState({\n restoreScrollPosition: y\n });\n }\n }\n\n return () => {\n savedScrollPositions = null;\n getScrollPosition = null;\n getScrollRestorationKey = null;\n };\n }\n\n function saveScrollPosition(location, matches) {\n if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {\n let userMatches = matches.map(m => createUseMatchesMatch(m, state.loaderData));\n let key = getScrollRestorationKey(location, userMatches) || location.key;\n savedScrollPositions[key] = getScrollPosition();\n }\n }\n\n function getSavedScrollPosition(location, matches) {\n if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {\n let userMatches = matches.map(m => createUseMatchesMatch(m, state.loaderData));\n let key = getScrollRestorationKey(location, userMatches) || location.key;\n let y = savedScrollPositions[key];\n\n if (typeof y === \"number\") {\n return y;\n }\n }\n\n return null;\n }\n\n router = {\n get basename() {\n return init.basename;\n },\n\n get state() {\n return state;\n },\n\n get routes() {\n return dataRoutes;\n },\n\n initialize,\n subscribe,\n enableScrollRestoration,\n navigate,\n fetch,\n revalidate,\n // Passthrough to history-aware createHref used by useHref so we get proper\n // hash-aware URLs in DOM paths\n createHref: to => init.history.createHref(to),\n encodeLocation: to => init.history.encodeLocation(to),\n getFetcher,\n deleteFetcher,\n dispose,\n _internalFetchControllers: fetchControllers,\n _internalActiveDeferreds: activeDeferreds\n };\n return router;\n} //#endregion\n////////////////////////////////////////////////////////////////////////////////\n//#region createStaticHandler\n////////////////////////////////////////////////////////////////////////////////\n\nfunction createStaticHandler(routes, opts) {\n invariant(routes.length > 0, \"You must provide a non-empty routes array to createStaticHandler\");\n let dataRoutes = convertRoutesToDataRoutes(routes);\n let basename = (opts ? opts.basename : null) || \"/\";\n /**\n * The query() method is intended for document requests, in which we want to\n * call an optional action and potentially multiple loaders for all nested\n * routes. It returns a StaticHandlerContext object, which is very similar\n * to the router state (location, loaderData, actionData, errors, etc.) and\n * also adds SSR-specific information such as the statusCode and headers\n * from action/loaders Responses.\n *\n * It _should_ never throw and should report all errors through the\n * returned context.errors object, properly associating errors to their error\n * boundary. Additionally, it tracks _deepestRenderedBoundaryId which can be\n * used to emulate React error boundaries during SSr by performing a second\n * pass only down to the boundaryId.\n *\n * The one exception where we do not return a StaticHandlerContext is when a\n * redirect response is returned or thrown from any action/loader. We\n * propagate that out and return the raw Response so the HTTP server can\n * return it directly.\n */\n\n async function query(request, _temp) {\n let {\n requestContext\n } = _temp === void 0 ? {} : _temp;\n let url = new URL(request.url);\n let method = request.method.toLowerCase();\n let location = createLocation(\"\", createPath(url), null, \"default\");\n let matches = matchRoutes(dataRoutes, location, basename); // SSR supports HEAD requests while SPA doesn't\n\n if (!isValidMethod(method) && method !== \"head\") {\n let error = getInternalRouterError(405, {\n method\n });\n let {\n matches: methodNotAllowedMatches,\n route\n } = getShortCircuitMatches(dataRoutes);\n return {\n basename,\n location,\n matches: methodNotAllowedMatches,\n loaderData: {},\n actionData: null,\n errors: {\n [route.id]: error\n },\n statusCode: error.status,\n loaderHeaders: {},\n actionHeaders: {}\n };\n } else if (!matches) {\n let error = getInternalRouterError(404, {\n pathname: location.pathname\n });\n let {\n matches: notFoundMatches,\n route\n } = getShortCircuitMatches(dataRoutes);\n return {\n basename,\n location,\n matches: notFoundMatches,\n loaderData: {},\n actionData: null,\n errors: {\n [route.id]: error\n },\n statusCode: error.status,\n loaderHeaders: {},\n actionHeaders: {}\n };\n }\n\n let result = await queryImpl(request, location, matches, requestContext);\n\n if (isResponse(result)) {\n return result;\n } // When returning StaticHandlerContext, we patch back in the location here\n // since we need it for React Context. But this helps keep our submit and\n // loadRouteData operating on a Request instead of a Location\n\n\n return _extends({\n location,\n basename\n }, result);\n }\n /**\n * The queryRoute() method is intended for targeted route requests, either\n * for fetch ?_data requests or resource route requests. In this case, we\n * are only ever calling a single action or loader, and we are returning the\n * returned value directly. In most cases, this will be a Response returned\n * from the action/loader, but it may be a primitive or other value as well -\n * and in such cases the calling context should handle that accordingly.\n *\n * We do respect the throw/return differentiation, so if an action/loader\n * throws, then this method will throw the value. This is important so we\n * can do proper boundary identification in Remix where a thrown Response\n * must go to the Catch Boundary but a returned Response is happy-path.\n *\n * One thing to note is that any Router-initiated Errors that make sense\n * to associate with a status code will be thrown as an ErrorResponse\n * instance which include the raw Error, such that the calling context can\n * serialize the error as they see fit while including the proper response\n * code. Examples here are 404 and 405 errors that occur prior to reaching\n * any user-defined loaders.\n */\n\n\n async function queryRoute(request, _temp2) {\n let {\n routeId,\n requestContext\n } = _temp2 === void 0 ? {} : _temp2;\n let url = new URL(request.url);\n let method = request.method.toLowerCase();\n let location = createLocation(\"\", createPath(url), null, \"default\");\n let matches = matchRoutes(dataRoutes, location, basename); // SSR supports HEAD requests while SPA doesn't\n\n if (!isValidMethod(method) && method !== \"head\") {\n throw getInternalRouterError(405, {\n method\n });\n } else if (!matches) {\n throw getInternalRouterError(404, {\n pathname: location.pathname\n });\n }\n\n let match = routeId ? matches.find(m => m.route.id === routeId) : getTargetMatch(matches, location);\n\n if (routeId && !match) {\n throw getInternalRouterError(403, {\n pathname: location.pathname,\n routeId\n });\n } else if (!match) {\n // This should never hit I don't think?\n throw getInternalRouterError(404, {\n pathname: location.pathname\n });\n }\n\n let result = await queryImpl(request, location, matches, requestContext, match);\n\n if (isResponse(result)) {\n return result;\n }\n\n let error = result.errors ? Object.values(result.errors)[0] : undefined;\n\n if (error !== undefined) {\n // If we got back result.errors, that means the loader/action threw\n // _something_ that wasn't a Response, but it's not guaranteed/required\n // to be an `instanceof Error` either, so we have to use throw here to\n // preserve the \"error\" state outside of queryImpl.\n throw error;\n } // Pick off the right state value to return\n\n\n let routeData = [result.actionData, result.loaderData].find(v => v);\n return Object.values(routeData || {})[0];\n }\n\n async function queryImpl(request, location, matches, requestContext, routeMatch) {\n invariant(request.signal, \"query()/queryRoute() requests must contain an AbortController signal\");\n\n try {\n if (isMutationMethod(request.method.toLowerCase())) {\n let result = await submit(request, matches, routeMatch || getTargetMatch(matches, location), requestContext, routeMatch != null);\n return result;\n }\n\n let result = await loadRouteData(request, matches, requestContext, routeMatch);\n return isResponse(result) ? result : _extends({}, result, {\n actionData: null,\n actionHeaders: {}\n });\n } catch (e) {\n // If the user threw/returned a Response in callLoaderOrAction, we throw\n // it to bail out and then return or throw here based on whether the user\n // returned or threw\n if (isQueryRouteResponse(e)) {\n if (e.type === ResultType.error && !isRedirectResponse(e.response)) {\n throw e.response;\n }\n\n return e.response;\n } // Redirects are always returned since they don't propagate to catch\n // boundaries\n\n\n if (isRedirectResponse(e)) {\n return e;\n }\n\n throw e;\n }\n }\n\n async function submit(request, matches, actionMatch, requestContext, isRouteRequest) {\n let result;\n\n if (!actionMatch.route.action) {\n let error = getInternalRouterError(405, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: actionMatch.route.id\n });\n\n if (isRouteRequest) {\n throw error;\n }\n\n result = {\n type: ResultType.error,\n error\n };\n } else {\n result = await callLoaderOrAction(\"action\", request, actionMatch, matches, basename, true, isRouteRequest, requestContext);\n\n if (request.signal.aborted) {\n let method = isRouteRequest ? \"queryRoute\" : \"query\";\n throw new Error(method + \"() call aborted\");\n }\n }\n\n if (isRedirectResult(result)) {\n // Uhhhh - this should never happen, we should always throw these from\n // callLoaderOrAction, but the type narrowing here keeps TS happy and we\n // can get back on the \"throw all redirect responses\" train here should\n // this ever happen :/\n throw new Response(null, {\n status: result.status,\n headers: {\n Location: result.location\n }\n });\n }\n\n if (isDeferredResult(result)) {\n throw new Error(\"defer() is not supported in actions\");\n }\n\n if (isRouteRequest) {\n // Note: This should only be non-Response values if we get here, since\n // isRouteRequest should throw any Response received in callLoaderOrAction\n if (isErrorResult(result)) {\n throw result.error;\n }\n\n return {\n matches: [actionMatch],\n loaderData: {},\n actionData: {\n [actionMatch.route.id]: result.data\n },\n errors: null,\n // Note: statusCode + headers are unused here since queryRoute will\n // return the raw Response or value\n statusCode: 200,\n loaderHeaders: {},\n actionHeaders: {}\n };\n }\n\n if (isErrorResult(result)) {\n // Store off the pending error - we use it to determine which loaders\n // to call and will commit it when we complete the navigation\n let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);\n let context = await loadRouteData(request, matches, requestContext, undefined, {\n [boundaryMatch.route.id]: result.error\n }); // action status codes take precedence over loader status codes\n\n return _extends({}, context, {\n statusCode: isRouteErrorResponse(result.error) ? result.error.status : 500,\n actionData: null,\n actionHeaders: _extends({}, result.headers ? {\n [actionMatch.route.id]: result.headers\n } : {})\n });\n } // Create a GET request for the loaders\n\n\n let loaderRequest = new Request(request.url, {\n headers: request.headers,\n redirect: request.redirect,\n signal: request.signal\n });\n let context = await loadRouteData(loaderRequest, matches, requestContext);\n return _extends({}, context, result.statusCode ? {\n statusCode: result.statusCode\n } : {}, {\n actionData: {\n [actionMatch.route.id]: result.data\n },\n actionHeaders: _extends({}, result.headers ? {\n [actionMatch.route.id]: result.headers\n } : {})\n });\n }\n\n async function loadRouteData(request, matches, requestContext, routeMatch, pendingActionError) {\n let isRouteRequest = routeMatch != null; // Short circuit if we have no loaders to run (queryRoute())\n\n if (isRouteRequest && !(routeMatch != null && routeMatch.route.loader)) {\n throw getInternalRouterError(400, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: routeMatch == null ? void 0 : routeMatch.route.id\n });\n }\n\n let requestMatches = routeMatch ? [routeMatch] : getLoaderMatchesUntilBoundary(matches, Object.keys(pendingActionError || {})[0]);\n let matchesToLoad = requestMatches.filter(m => m.route.loader); // Short circuit if we have no loaders to run (query())\n\n if (matchesToLoad.length === 0) {\n return {\n matches,\n // Add a null for all matched routes for proper revalidation on the client\n loaderData: matches.reduce((acc, m) => Object.assign(acc, {\n [m.route.id]: null\n }), {}),\n errors: pendingActionError || null,\n statusCode: 200,\n loaderHeaders: {}\n };\n }\n\n let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction(\"loader\", request, match, matches, basename, true, isRouteRequest, requestContext))]);\n\n if (request.signal.aborted) {\n let method = isRouteRequest ? \"queryRoute\" : \"query\";\n throw new Error(method + \"() call aborted\");\n }\n\n let executedLoaders = new Set();\n results.forEach((result, i) => {\n executedLoaders.add(matchesToLoad[i].route.id); // Can't do anything with these without the Remix side of things, so just\n // cancel them for now\n\n if (isDeferredResult(result)) {\n result.deferredData.cancel();\n }\n }); // Process and commit output from loaders\n\n let context = processRouteLoaderData(matches, matchesToLoad, results, pendingActionError); // Add a null for any non-loader matches for proper revalidation on the client\n\n matches.forEach(match => {\n if (!executedLoaders.has(match.route.id)) {\n context.loaderData[match.route.id] = null;\n }\n });\n return _extends({}, context, {\n matches\n });\n }\n\n return {\n dataRoutes,\n query,\n queryRoute\n };\n} //#endregion\n////////////////////////////////////////////////////////////////////////////////\n//#region Helpers\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Given an existing StaticHandlerContext and an error thrown at render time,\n * provide an updated StaticHandlerContext suitable for a second SSR render\n */\n\nfunction getStaticContextFromError(routes, context, error) {\n let newContext = _extends({}, context, {\n statusCode: 500,\n errors: {\n [context._deepestRenderedBoundaryId || routes[0].id]: error\n }\n });\n\n return newContext;\n}\n\nfunction isSubmissionNavigation(opts) {\n return opts != null && \"formData\" in opts;\n} // Normalize navigation options by converting formMethod=GET formData objects to\n// URLSearchParams so they behave identically to links with query params\n\n\nfunction normalizeNavigateOptions(to, opts, isFetcher) {\n if (isFetcher === void 0) {\n isFetcher = false;\n }\n\n let path = typeof to === \"string\" ? to : createPath(to); // Return location verbatim on non-submission navigations\n\n if (!opts || !isSubmissionNavigation(opts)) {\n return {\n path\n };\n }\n\n if (opts.formMethod && !isValidMethod(opts.formMethod)) {\n return {\n path,\n error: getInternalRouterError(405, {\n method: opts.formMethod\n })\n };\n } // Create a Submission on non-GET navigations\n\n\n let submission;\n\n if (opts.formData) {\n submission = {\n formMethod: opts.formMethod || \"get\",\n formAction: stripHashFromPath(path),\n formEncType: opts && opts.formEncType || \"application/x-www-form-urlencoded\",\n formData: opts.formData\n };\n\n if (isMutationMethod(submission.formMethod)) {\n return {\n path,\n submission\n };\n }\n } // Flatten submission onto URLSearchParams for GET submissions\n\n\n let parsedPath = parsePath(path);\n\n try {\n let searchParams = convertFormDataToSearchParams(opts.formData); // Since fetcher GET submissions only run a single loader (as opposed to\n // navigation GET submissions which run all loaders), we need to preserve\n // any incoming ?index params\n\n if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) {\n searchParams.append(\"index\", \"\");\n }\n\n parsedPath.search = \"?\" + searchParams;\n } catch (e) {\n return {\n path,\n error: getInternalRouterError(400)\n };\n }\n\n return {\n path: createPath(parsedPath),\n submission\n };\n} // Filter out all routes below any caught error as they aren't going to\n// render so we don't need to load them\n\n\nfunction getLoaderMatchesUntilBoundary(matches, boundaryId) {\n let boundaryMatches = matches;\n\n if (boundaryId) {\n let index = matches.findIndex(m => m.route.id === boundaryId);\n\n if (index >= 0) {\n boundaryMatches = matches.slice(0, index);\n }\n }\n\n return boundaryMatches;\n}\n\nfunction getMatchesToLoad(state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches) {\n let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined; // Pick navigation matches that are net-new or qualify for revalidation\n\n let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;\n let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);\n let navigationMatches = boundaryMatches.filter((match, index) => match.route.loader != null && (isNewLoader(state.loaderData, state.matches[index], match) || // If this route had a pending deferred cancelled it must be revalidated\n cancelledDeferredRoutes.some(id => id === match.route.id) || shouldRevalidateLoader(state.location, state.matches[index], submission, location, match, isRevalidationRequired, actionResult))); // Pick fetcher.loads that need to be revalidated\n\n let revalidatingFetchers = [];\n fetchLoadMatches && fetchLoadMatches.forEach((_ref10, key) => {\n let [href, match, fetchMatches] = _ref10;\n\n // This fetcher was cancelled from a prior action submission - force reload\n if (cancelledFetcherLoads.includes(key)) {\n revalidatingFetchers.push([key, href, match, fetchMatches]);\n } else if (isRevalidationRequired) {\n let shouldRevalidate = shouldRevalidateLoader(href, match, submission, href, match, isRevalidationRequired, actionResult);\n\n if (shouldRevalidate) {\n revalidatingFetchers.push([key, href, match, fetchMatches]);\n }\n }\n });\n return [navigationMatches, revalidatingFetchers];\n}\n\nfunction isNewLoader(currentLoaderData, currentMatch, match) {\n let isNew = // [a] -> [a, b]\n !currentMatch || // [a, b] -> [a, c]\n match.route.id !== currentMatch.route.id; // Handle the case that we don't have data for a re-used route, potentially\n // from a prior error or from a cancelled pending deferred\n\n let isMissingData = currentLoaderData[match.route.id] === undefined; // Always load if this is a net-new route or we don't yet have data\n\n return isNew || isMissingData;\n}\n\nfunction isNewRouteInstance(currentMatch, match) {\n let currentPath = currentMatch.route.path;\n return (// param change for this match, /users/123 -> /users/456\n currentMatch.pathname !== match.pathname || // splat param changed, which is not present in match.path\n // e.g. /files/images/avatar.jpg -> files/finances.xls\n currentPath && currentPath.endsWith(\"*\") && currentMatch.params[\"*\"] !== match.params[\"*\"]\n );\n}\n\nfunction shouldRevalidateLoader(currentLocation, currentMatch, submission, location, match, isRevalidationRequired, actionResult) {\n let currentUrl = createClientSideURL(currentLocation);\n let currentParams = currentMatch.params;\n let nextUrl = createClientSideURL(location);\n let nextParams = match.params; // This is the default implementation as to when we revalidate. If the route\n // provides it's own implementation, then we give them full control but\n // provide this value so they can leverage it if needed after they check\n // their own specific use cases\n // Note that fetchers always provide the same current/next locations so the\n // URL-based checks here don't apply to fetcher shouldRevalidate calls\n\n let defaultShouldRevalidate = isNewRouteInstance(currentMatch, match) || // Clicked the same link, resubmitted a GET form\n currentUrl.toString() === nextUrl.toString() || // Search params affect all loaders\n currentUrl.search !== nextUrl.search || // Forced revalidation due to submission, useRevalidate, or X-Remix-Revalidate\n isRevalidationRequired;\n\n if (match.route.shouldRevalidate) {\n let routeChoice = match.route.shouldRevalidate(_extends({\n currentUrl,\n currentParams,\n nextUrl,\n nextParams\n }, submission, {\n actionResult,\n defaultShouldRevalidate\n }));\n\n if (typeof routeChoice === \"boolean\") {\n return routeChoice;\n }\n }\n\n return defaultShouldRevalidate;\n}\n\nasync function callLoaderOrAction(type, request, match, matches, basename, isStaticRequest, isRouteRequest, requestContext) {\n if (basename === void 0) {\n basename = \"/\";\n }\n\n if (isStaticRequest === void 0) {\n isStaticRequest = false;\n }\n\n if (isRouteRequest === void 0) {\n isRouteRequest = false;\n }\n\n let resultType;\n let result; // Setup a promise we can race against so that abort signals short circuit\n\n let reject;\n let abortPromise = new Promise((_, r) => reject = r);\n\n let onReject = () => reject();\n\n request.signal.addEventListener(\"abort\", onReject);\n\n try {\n let handler = match.route[type];\n invariant(handler, \"Could not find the \" + type + \" to run on the \\\"\" + match.route.id + \"\\\" route\");\n result = await Promise.race([handler({\n request,\n params: match.params,\n context: requestContext\n }), abortPromise]);\n invariant(result !== undefined, \"You defined \" + (type === \"action\" ? \"an action\" : \"a loader\") + \" for route \" + (\"\\\"\" + match.route.id + \"\\\" but didn't return anything from your `\" + type + \"` \") + \"function. Please return a value or `null`.\");\n } catch (e) {\n resultType = ResultType.error;\n result = e;\n } finally {\n request.signal.removeEventListener(\"abort\", onReject);\n }\n\n if (isResponse(result)) {\n let status = result.status; // Process redirects\n\n if (redirectStatusCodes.has(status)) {\n let location = result.headers.get(\"Location\");\n invariant(location, \"Redirects returned/thrown from loaders/actions must have a Location header\");\n let isAbsolute = /^[a-z+]+:\\/\\//i.test(location) || location.startsWith(\"//\"); // Support relative routing in internal redirects\n\n if (!isAbsolute) {\n let activeMatches = matches.slice(0, matches.indexOf(match) + 1);\n let routePathnames = getPathContributingMatches(activeMatches).map(match => match.pathnameBase);\n let resolvedLocation = resolveTo(location, routePathnames, new URL(request.url).pathname);\n invariant(createPath(resolvedLocation), \"Unable to resolve redirect location: \" + location); // Prepend the basename to the redirect location if we have one\n\n if (basename) {\n let path = resolvedLocation.pathname;\n resolvedLocation.pathname = path === \"/\" ? basename : joinPaths([basename, path]);\n }\n\n location = createPath(resolvedLocation);\n } // Don't process redirects in the router during static requests requests.\n // Instead, throw the Response and let the server handle it with an HTTP\n // redirect. We also update the Location header in place in this flow so\n // basename and relative routing is taken into account\n\n\n if (isStaticRequest) {\n result.headers.set(\"Location\", location);\n throw result;\n }\n\n return {\n type: ResultType.redirect,\n status,\n location,\n revalidate: result.headers.get(\"X-Remix-Revalidate\") !== null\n };\n } // For SSR single-route requests, we want to hand Responses back directly\n // without unwrapping. We do this with the QueryRouteResponse wrapper\n // interface so we can know whether it was returned or thrown\n\n\n if (isRouteRequest) {\n // eslint-disable-next-line no-throw-literal\n throw {\n type: resultType || ResultType.data,\n response: result\n };\n }\n\n let data;\n let contentType = result.headers.get(\"Content-Type\"); // Check between word boundaries instead of startsWith() due to the last\n // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type\n\n if (contentType && /\\bapplication\\/json\\b/.test(contentType)) {\n data = await result.json();\n } else {\n data = await result.text();\n }\n\n if (resultType === ResultType.error) {\n return {\n type: resultType,\n error: new ErrorResponse(status, result.statusText, data),\n headers: result.headers\n };\n }\n\n return {\n type: ResultType.data,\n data,\n statusCode: result.status,\n headers: result.headers\n };\n }\n\n if (resultType === ResultType.error) {\n return {\n type: resultType,\n error: result\n };\n }\n\n if (result instanceof DeferredData) {\n return {\n type: ResultType.deferred,\n deferredData: result\n };\n }\n\n return {\n type: ResultType.data,\n data: result\n };\n} // Utility method for creating the Request instances for loaders/actions during\n// client-side navigations and fetches. During SSR we will always have a\n// Request instance from the static handler (query/queryRoute)\n\n\nfunction createClientSideRequest(location, signal, submission) {\n let url = createClientSideURL(stripHashFromPath(location)).toString();\n let init = {\n signal\n };\n\n if (submission && isMutationMethod(submission.formMethod)) {\n let {\n formMethod,\n formEncType,\n formData\n } = submission;\n init.method = formMethod.toUpperCase();\n init.body = formEncType === \"application/x-www-form-urlencoded\" ? convertFormDataToSearchParams(formData) : formData;\n } // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)\n\n\n return new Request(url, init);\n}\n\nfunction convertFormDataToSearchParams(formData) {\n let searchParams = new URLSearchParams();\n\n for (let [key, value] of formData.entries()) {\n invariant(typeof value === \"string\", 'File inputs are not supported with encType \"application/x-www-form-urlencoded\", ' + 'please use \"multipart/form-data\" instead.');\n searchParams.append(key, value);\n }\n\n return searchParams;\n}\n\nfunction processRouteLoaderData(matches, matchesToLoad, results, pendingError, activeDeferreds) {\n // Fill in loaderData/errors from our loaders\n let loaderData = {};\n let errors = null;\n let statusCode;\n let foundError = false;\n let loaderHeaders = {}; // Process loader results into state.loaderData/state.errors\n\n results.forEach((result, index) => {\n let id = matchesToLoad[index].route.id;\n invariant(!isRedirectResult(result), \"Cannot handle redirect results in processLoaderData\");\n\n if (isErrorResult(result)) {\n // Look upwards from the matched route for the closest ancestor\n // error boundary, defaulting to the root match\n let boundaryMatch = findNearestBoundary(matches, id);\n let error = result.error; // If we have a pending action error, we report it at the highest-route\n // that throws a loader error, and then clear it out to indicate that\n // it was consumed\n\n if (pendingError) {\n error = Object.values(pendingError)[0];\n pendingError = undefined;\n }\n\n errors = errors || {}; // Prefer higher error values if lower errors bubble to the same boundary\n\n if (errors[boundaryMatch.route.id] == null) {\n errors[boundaryMatch.route.id] = error;\n } // Clear our any prior loaderData for the throwing route\n\n\n loaderData[id] = undefined; // Once we find our first (highest) error, we set the status code and\n // prevent deeper status codes from overriding\n\n if (!foundError) {\n foundError = true;\n statusCode = isRouteErrorResponse(result.error) ? result.error.status : 500;\n }\n\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n } else if (isDeferredResult(result)) {\n activeDeferreds && activeDeferreds.set(id, result.deferredData);\n loaderData[id] = result.deferredData.data; // TODO: Add statusCode/headers once we wire up streaming in Remix\n } else {\n loaderData[id] = result.data; // Error status codes always override success status codes, but if all\n // loaders are successful we take the deepest status code.\n\n if (result.statusCode != null && result.statusCode !== 200 && !foundError) {\n statusCode = result.statusCode;\n }\n\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n }\n }); // If we didn't consume the pending action error (i.e., all loaders\n // resolved), then consume it here. Also clear out any loaderData for the\n // throwing route\n\n if (pendingError) {\n errors = pendingError;\n loaderData[Object.keys(pendingError)[0]] = undefined;\n }\n\n return {\n loaderData,\n errors,\n statusCode: statusCode || 200,\n loaderHeaders\n };\n}\n\nfunction processLoaderData(state, matches, matchesToLoad, results, pendingError, revalidatingFetchers, fetcherResults, activeDeferreds) {\n let {\n loaderData,\n errors\n } = processRouteLoaderData(matches, matchesToLoad, results, pendingError, activeDeferreds); // Process results from our revalidating fetchers\n\n for (let index = 0; index < revalidatingFetchers.length; index++) {\n let [key,, match] = revalidatingFetchers[index];\n invariant(fetcherResults !== undefined && fetcherResults[index] !== undefined, \"Did not find corresponding fetcher result\");\n let result = fetcherResults[index]; // Process fetcher non-redirect errors\n\n if (isErrorResult(result)) {\n let boundaryMatch = findNearestBoundary(state.matches, match.route.id);\n\n if (!(errors && errors[boundaryMatch.route.id])) {\n errors = _extends({}, errors, {\n [boundaryMatch.route.id]: result.error\n });\n }\n\n state.fetchers.delete(key);\n } else if (isRedirectResult(result)) {\n // Should never get here, redirects should get processed above, but we\n // keep this to type narrow to a success result in the else\n throw new Error(\"Unhandled fetcher revalidation redirect\");\n } else if (isDeferredResult(result)) {\n // Should never get here, deferred data should be awaited for fetchers\n // in resolveDeferredResults\n throw new Error(\"Unhandled fetcher deferred data\");\n } else {\n let doneFetcher = {\n state: \"idle\",\n data: result.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true\n };\n state.fetchers.set(key, doneFetcher);\n }\n }\n\n return {\n loaderData,\n errors\n };\n}\n\nfunction mergeLoaderData(loaderData, newLoaderData, matches, errors) {\n let mergedLoaderData = _extends({}, newLoaderData);\n\n for (let match of matches) {\n let id = match.route.id;\n\n if (newLoaderData.hasOwnProperty(id)) {\n if (newLoaderData[id] !== undefined) {\n mergedLoaderData[id] = newLoaderData[id];\n }\n } else if (loaderData[id] !== undefined) {\n mergedLoaderData[id] = loaderData[id];\n }\n\n if (errors && errors.hasOwnProperty(id)) {\n // Don't keep any loader data below the boundary\n break;\n }\n }\n\n return mergedLoaderData;\n} // Find the nearest error boundary, looking upwards from the leaf route (or the\n// route specified by routeId) for the closest ancestor error boundary,\n// defaulting to the root match\n\n\nfunction findNearestBoundary(matches, routeId) {\n let eligibleMatches = routeId ? matches.slice(0, matches.findIndex(m => m.route.id === routeId) + 1) : [...matches];\n return eligibleMatches.reverse().find(m => m.route.hasErrorBoundary === true) || matches[0];\n}\n\nfunction getShortCircuitMatches(routes) {\n // Prefer a root layout route if present, otherwise shim in a route object\n let route = routes.find(r => r.index || !r.path || r.path === \"/\") || {\n id: \"__shim-error-route__\"\n };\n return {\n matches: [{\n params: {},\n pathname: \"\",\n pathnameBase: \"\",\n route\n }],\n route\n };\n}\n\nfunction getInternalRouterError(status, _temp3) {\n let {\n pathname,\n routeId,\n method\n } = _temp3 === void 0 ? {} : _temp3;\n let statusText = \"Unknown Server Error\";\n let errorMessage = \"Unknown @remix-run/router error\";\n\n if (status === 400) {\n statusText = \"Bad Request\";\n\n if (method && pathname && routeId) {\n errorMessage = \"You made a \" + method + \" request to \\\"\" + pathname + \"\\\" but \" + (\"did not provide a `loader` for route \\\"\" + routeId + \"\\\", \") + \"so there is no way to handle the request.\";\n } else {\n errorMessage = \"Cannot submit binary form data using GET\";\n }\n } else if (status === 403) {\n statusText = \"Forbidden\";\n errorMessage = \"Route \\\"\" + routeId + \"\\\" does not match URL \\\"\" + pathname + \"\\\"\";\n } else if (status === 404) {\n statusText = \"Not Found\";\n errorMessage = \"No route matches URL \\\"\" + pathname + \"\\\"\";\n } else if (status === 405) {\n statusText = \"Method Not Allowed\";\n\n if (method && pathname && routeId) {\n errorMessage = \"You made a \" + method.toUpperCase() + \" request to \\\"\" + pathname + \"\\\" but \" + (\"did not provide an `action` for route \\\"\" + routeId + \"\\\", \") + \"so there is no way to handle the request.\";\n } else if (method) {\n errorMessage = \"Invalid request method \\\"\" + method.toUpperCase() + \"\\\"\";\n }\n }\n\n return new ErrorResponse(status || 500, statusText, new Error(errorMessage), true);\n} // Find any returned redirect errors, starting from the lowest match\n\n\nfunction findRedirect(results) {\n for (let i = results.length - 1; i >= 0; i--) {\n let result = results[i];\n\n if (isRedirectResult(result)) {\n return result;\n }\n }\n}\n\nfunction stripHashFromPath(path) {\n let parsedPath = typeof path === \"string\" ? parsePath(path) : path;\n return createPath(_extends({}, parsedPath, {\n hash: \"\"\n }));\n}\n\nfunction isHashChangeOnly(a, b) {\n return a.pathname === b.pathname && a.search === b.search && a.hash !== b.hash;\n}\n\nfunction isDeferredResult(result) {\n return result.type === ResultType.deferred;\n}\n\nfunction isErrorResult(result) {\n return result.type === ResultType.error;\n}\n\nfunction isRedirectResult(result) {\n return (result && result.type) === ResultType.redirect;\n}\n\nfunction isResponse(value) {\n return value != null && typeof value.status === \"number\" && typeof value.statusText === \"string\" && typeof value.headers === \"object\" && typeof value.body !== \"undefined\";\n}\n\nfunction isRedirectResponse(result) {\n if (!isResponse(result)) {\n return false;\n }\n\n let status = result.status;\n let location = result.headers.get(\"Location\");\n return status >= 300 && status <= 399 && location != null;\n}\n\nfunction isQueryRouteResponse(obj) {\n return obj && isResponse(obj.response) && (obj.type === ResultType.data || ResultType.error);\n}\n\nfunction isValidMethod(method) {\n return validRequestMethods.has(method);\n}\n\nfunction isMutationMethod(method) {\n return validMutationMethods.has(method);\n}\n\nasync function resolveDeferredResults(currentMatches, matchesToLoad, results, signal, isFetcher, currentLoaderData) {\n for (let index = 0; index < results.length; index++) {\n let result = results[index];\n let match = matchesToLoad[index];\n let currentMatch = currentMatches.find(m => m.route.id === match.route.id);\n let isRevalidatingLoader = currentMatch != null && !isNewRouteInstance(currentMatch, match) && (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;\n\n if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) {\n // Note: we do not have to touch activeDeferreds here since we race them\n // against the signal in resolveDeferredData and they'll get aborted\n // there if needed\n await resolveDeferredData(result, signal, isFetcher).then(result => {\n if (result) {\n results[index] = result || results[index];\n }\n });\n }\n }\n}\n\nasync function resolveDeferredData(result, signal, unwrap) {\n if (unwrap === void 0) {\n unwrap = false;\n }\n\n let aborted = await result.deferredData.resolveData(signal);\n\n if (aborted) {\n return;\n }\n\n if (unwrap) {\n try {\n return {\n type: ResultType.data,\n data: result.deferredData.unwrappedData\n };\n } catch (e) {\n // Handle any TrackedPromise._error values encountered while unwrapping\n return {\n type: ResultType.error,\n error: e\n };\n }\n }\n\n return {\n type: ResultType.data,\n data: result.deferredData.data\n };\n}\n\nfunction hasNakedIndexQuery(search) {\n return new URLSearchParams(search).getAll(\"index\").some(v => v === \"\");\n} // Note: This should match the format exported by useMatches, so if you change\n// this please also change that :) Eventually we'll DRY this up\n\n\nfunction createUseMatchesMatch(match, loaderData) {\n let {\n route,\n pathname,\n params\n } = match;\n return {\n id: route.id,\n pathname,\n params,\n data: loaderData[route.id],\n handle: route.handle\n };\n}\n\nfunction getTargetMatch(matches, location) {\n let search = typeof location === \"string\" ? parsePath(location).search : location.search;\n\n if (matches[matches.length - 1].route.index && hasNakedIndexQuery(search || \"\")) {\n // Return the leaf index route when index is present\n return matches[matches.length - 1];\n } // Otherwise grab the deepest \"path contributing\" match (ignoring index and\n // pathless layout routes)\n\n\n let pathMatches = getPathContributingMatches(matches);\n return pathMatches[pathMatches.length - 1];\n} //#endregion\n\nexport { AbortedDeferredError, Action, ErrorResponse, IDLE_FETCHER, IDLE_NAVIGATION, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, getPathContributingMatches as UNSAFE_getPathContributingMatches, createBrowserHistory, createHashHistory, createMemoryHistory, createPath, createRouter, createStaticHandler, defer, generatePath, getStaticContextFromError, getToPathname, invariant, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, parsePath, redirect, resolvePath, resolveTo, stripBasename, warning };\n//# sourceMappingURL=router.js.map\n","function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\n// Older browsers don't support event options, feature detect it.\n\n// Adopted and modified solution from Bohdan Didukh (2017)\n// https://stackoverflow.com/questions/41594997/ios-10-safari-prevent-scrolling-behind-a-fixed-overlay-and-maintain-scroll-posi\n\nvar hasPassiveEvents = false;\nif (typeof window !== 'undefined') {\n var passiveTestOptions = {\n get passive() {\n hasPassiveEvents = true;\n return undefined;\n }\n };\n window.addEventListener('testPassive', null, passiveTestOptions);\n window.removeEventListener('testPassive', null, passiveTestOptions);\n}\n\nvar isIosDevice = typeof window !== 'undefined' && window.navigator && window.navigator.platform && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === 'MacIntel' && window.navigator.maxTouchPoints > 1);\n\n\nvar locks = [];\nvar documentListenerAdded = false;\nvar initialClientY = -1;\nvar previousBodyOverflowSetting = void 0;\nvar previousBodyPosition = void 0;\nvar previousBodyPaddingRight = void 0;\n\n// returns true if `el` should be allowed to receive touchmove events.\nvar allowTouchMove = function allowTouchMove(el) {\n return locks.some(function (lock) {\n if (lock.options.allowTouchMove && lock.options.allowTouchMove(el)) {\n return true;\n }\n\n return false;\n });\n};\n\nvar preventDefault = function preventDefault(rawEvent) {\n var e = rawEvent || window.event;\n\n // For the case whereby consumers adds a touchmove event listener to document.\n // Recall that we do document.addEventListener('touchmove', preventDefault, { passive: false })\n // in disableBodyScroll - so if we provide this opportunity to allowTouchMove, then\n // the touchmove event on document will break.\n if (allowTouchMove(e.target)) {\n return true;\n }\n\n // Do not prevent if the event has more than one touch (usually meaning this is a multi touch gesture like pinch to zoom).\n if (e.touches.length > 1) return true;\n\n if (e.preventDefault) e.preventDefault();\n\n return false;\n};\n\nvar setOverflowHidden = function setOverflowHidden(options) {\n // If previousBodyPaddingRight is already set, don't set it again.\n if (previousBodyPaddingRight === undefined) {\n var _reserveScrollBarGap = !!options && options.reserveScrollBarGap === true;\n var scrollBarGap = window.innerWidth - document.documentElement.clientWidth;\n\n if (_reserveScrollBarGap && scrollBarGap > 0) {\n var computedBodyPaddingRight = parseInt(window.getComputedStyle(document.body).getPropertyValue('padding-right'), 10);\n previousBodyPaddingRight = document.body.style.paddingRight;\n document.body.style.paddingRight = computedBodyPaddingRight + scrollBarGap + 'px';\n }\n }\n\n // If previousBodyOverflowSetting is already set, don't set it again.\n if (previousBodyOverflowSetting === undefined) {\n previousBodyOverflowSetting = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n};\n\nvar restoreOverflowSetting = function restoreOverflowSetting() {\n if (previousBodyPaddingRight !== undefined) {\n document.body.style.paddingRight = previousBodyPaddingRight;\n\n // Restore previousBodyPaddingRight to undefined so setOverflowHidden knows it\n // can be set again.\n previousBodyPaddingRight = undefined;\n }\n\n if (previousBodyOverflowSetting !== undefined) {\n document.body.style.overflow = previousBodyOverflowSetting;\n\n // Restore previousBodyOverflowSetting to undefined\n // so setOverflowHidden knows it can be set again.\n previousBodyOverflowSetting = undefined;\n }\n};\n\nvar setPositionFixed = function setPositionFixed() {\n return window.requestAnimationFrame(function () {\n // If previousBodyPosition is already set, don't set it again.\n if (previousBodyPosition === undefined) {\n previousBodyPosition = {\n position: document.body.style.position,\n top: document.body.style.top,\n left: document.body.style.left\n };\n\n // Update the dom inside an animation frame \n var _window = window,\n scrollY = _window.scrollY,\n scrollX = _window.scrollX,\n innerHeight = _window.innerHeight;\n\n document.body.style.position = 'fixed';\n document.body.style.top = -scrollY;\n document.body.style.left = -scrollX;\n\n setTimeout(function () {\n return window.requestAnimationFrame(function () {\n // Attempt to check if the bottom bar appeared due to the position change\n var bottomBarHeight = innerHeight - window.innerHeight;\n if (bottomBarHeight && scrollY >= innerHeight) {\n // Move the content further up so that the bottom bar doesn't hide it\n document.body.style.top = -(scrollY + bottomBarHeight);\n }\n });\n }, 300);\n }\n });\n};\n\nvar restorePositionSetting = function restorePositionSetting() {\n if (previousBodyPosition !== undefined) {\n // Convert the position from \"px\" to Int\n var y = -parseInt(document.body.style.top, 10);\n var x = -parseInt(document.body.style.left, 10);\n\n // Restore styles\n document.body.style.position = previousBodyPosition.position;\n document.body.style.top = previousBodyPosition.top;\n document.body.style.left = previousBodyPosition.left;\n\n // Restore scroll\n window.scrollTo(x, y);\n\n previousBodyPosition = undefined;\n }\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions\nvar isTargetElementTotallyScrolled = function isTargetElementTotallyScrolled(targetElement) {\n return targetElement ? targetElement.scrollHeight - targetElement.scrollTop <= targetElement.clientHeight : false;\n};\n\nvar handleScroll = function handleScroll(event, targetElement) {\n var clientY = event.targetTouches[0].clientY - initialClientY;\n\n if (allowTouchMove(event.target)) {\n return false;\n }\n\n if (targetElement && targetElement.scrollTop === 0 && clientY > 0) {\n // element is at the top of its scroll.\n return preventDefault(event);\n }\n\n if (isTargetElementTotallyScrolled(targetElement) && clientY < 0) {\n // element is at the bottom of its scroll.\n return preventDefault(event);\n }\n\n event.stopPropagation();\n return true;\n};\n\nexport var disableBodyScroll = function disableBodyScroll(targetElement, options) {\n // targetElement must be provided\n if (!targetElement) {\n // eslint-disable-next-line no-console\n console.error('disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.');\n return;\n }\n\n // disableBodyScroll must not have been called on this targetElement before\n if (locks.some(function (lock) {\n return lock.targetElement === targetElement;\n })) {\n return;\n }\n\n var lock = {\n targetElement: targetElement,\n options: options || {}\n };\n\n locks = [].concat(_toConsumableArray(locks), [lock]);\n\n if (isIosDevice) {\n setPositionFixed();\n } else {\n setOverflowHidden(options);\n }\n\n if (isIosDevice) {\n targetElement.ontouchstart = function (event) {\n if (event.targetTouches.length === 1) {\n // detect single touch.\n initialClientY = event.targetTouches[0].clientY;\n }\n };\n targetElement.ontouchmove = function (event) {\n if (event.targetTouches.length === 1) {\n // detect single touch.\n handleScroll(event, targetElement);\n }\n };\n\n if (!documentListenerAdded) {\n document.addEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n documentListenerAdded = true;\n }\n }\n};\n\nexport var clearAllBodyScrollLocks = function clearAllBodyScrollLocks() {\n if (isIosDevice) {\n // Clear all locks ontouchstart/ontouchmove handlers, and the references.\n locks.forEach(function (lock) {\n lock.targetElement.ontouchstart = null;\n lock.targetElement.ontouchmove = null;\n });\n\n if (documentListenerAdded) {\n document.removeEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n documentListenerAdded = false;\n }\n\n // Reset initial clientY.\n initialClientY = -1;\n }\n\n if (isIosDevice) {\n restorePositionSetting();\n } else {\n restoreOverflowSetting();\n }\n\n locks = [];\n};\n\nexport var enableBodyScroll = function enableBodyScroll(targetElement) {\n if (!targetElement) {\n // eslint-disable-next-line no-console\n console.error('enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.');\n return;\n }\n\n locks = locks.filter(function (lock) {\n return lock.targetElement !== targetElement;\n });\n\n if (isIosDevice) {\n targetElement.ontouchstart = null;\n targetElement.ontouchmove = null;\n\n if (documentListenerAdded && locks.length === 0) {\n document.removeEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n documentListenerAdded = false;\n }\n }\n\n if (isIosDevice) {\n restorePositionSetting();\n } else {\n restoreOverflowSetting();\n }\n};\n\n","\"use strict\";\n\nvar deselectCurrent = require(\"toggle-selection\");\n\nvar clipboardToIE11Formatting = {\n \"text/plain\": \"Text\",\n \"text/html\": \"Url\",\n \"default\": \"Text\"\n}\n\nvar defaultMessage = \"Copy to clipboard: #{key}, Enter\";\n\nfunction format(message) {\n var copyKey = (/mac os x/i.test(navigator.userAgent) ? \"⌘\" : \"Ctrl\") + \"+C\";\n return message.replace(/#{\\s*key\\s*}/g, copyKey);\n}\n\nfunction copy(text, options) {\n var debug,\n message,\n reselectPrevious,\n range,\n selection,\n mark,\n success = false;\n if (!options) {\n options = {};\n }\n debug = options.debug || false;\n try {\n reselectPrevious = deselectCurrent();\n\n range = document.createRange();\n selection = document.getSelection();\n\n mark = document.createElement(\"span\");\n mark.textContent = text;\n // avoid screen readers from reading out loud the text\n mark.ariaHidden = \"true\"\n // reset user styles for span element\n mark.style.all = \"unset\";\n // prevents scrolling to the end of the page\n mark.style.position = \"fixed\";\n mark.style.top = 0;\n mark.style.clip = \"rect(0, 0, 0, 0)\";\n // used to preserve spaces and line breaks\n mark.style.whiteSpace = \"pre\";\n // do not inherit user-select (it may be `none`)\n mark.style.webkitUserSelect = \"text\";\n mark.style.MozUserSelect = \"text\";\n mark.style.msUserSelect = \"text\";\n mark.style.userSelect = \"text\";\n mark.addEventListener(\"copy\", function(e) {\n e.stopPropagation();\n if (options.format) {\n e.preventDefault();\n if (typeof e.clipboardData === \"undefined\") { // IE 11\n debug && console.warn(\"unable to use e.clipboardData\");\n debug && console.warn(\"trying IE specific stuff\");\n window.clipboardData.clearData();\n var format = clipboardToIE11Formatting[options.format] || clipboardToIE11Formatting[\"default\"]\n window.clipboardData.setData(format, text);\n } else { // all other browsers\n e.clipboardData.clearData();\n e.clipboardData.setData(options.format, text);\n }\n }\n if (options.onCopy) {\n e.preventDefault();\n options.onCopy(e.clipboardData);\n }\n });\n\n document.body.appendChild(mark);\n\n range.selectNodeContents(mark);\n selection.addRange(range);\n\n var successful = document.execCommand(\"copy\");\n if (!successful) {\n throw new Error(\"copy command was unsuccessful\");\n }\n success = true;\n } catch (err) {\n debug && console.error(\"unable to copy using execCommand: \", err);\n debug && console.warn(\"trying IE specific stuff\");\n try {\n window.clipboardData.setData(options.format || \"text\", text);\n options.onCopy && options.onCopy(window.clipboardData);\n success = true;\n } catch (err) {\n debug && console.error(\"unable to copy using clipboardData: \", err);\n debug && console.error(\"falling back to prompt\");\n message = format(\"message\" in options ? options.message : defaultMessage);\n window.prompt(message, text);\n }\n } finally {\n if (selection) {\n if (typeof selection.removeRange == \"function\") {\n selection.removeRange(range);\n } else {\n selection.removeAllRanges();\n }\n }\n\n if (mark) {\n document.body.removeChild(mark);\n }\n reselectPrevious();\n }\n\n return success;\n}\n\nmodule.exports = copy;\n","/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n/**\n * Use invariant() to assert state which your program assumes to be true.\n *\n * Provide sprintf-style format (only %s is supported) and arguments\n * to provide information about what broke and what you were\n * expecting.\n *\n * The invariant message will be stripped in production, but the invariant\n * will remain to ensure logic does not differ in production.\n */\n\nvar invariant = function(condition, format, a, b, c, d, e, f) {\n if (process.env.NODE_ENV !== 'production') {\n if (format === undefined) {\n throw new Error('invariant requires an error message argument');\n }\n }\n\n if (!condition) {\n var error;\n if (format === undefined) {\n error = new Error(\n 'Minified exception occurred; use the non-minified dev environment ' +\n 'for the full error message and additional helpful warnings.'\n );\n } else {\n var args = [a, b, c, d, e, f];\n var argIndex = 0;\n error = new Error(\n format.replace(/%s/g, function() { return args[argIndex++]; })\n );\n error.name = 'Invariant Violation';\n }\n\n error.framesToPop = 1; // we don't care about invariant's own frame\n throw error;\n }\n};\n\nmodule.exports = invariant;\n","\"use strict\";\n\n/* eslint-env browser */\n/*\n eslint-disable\n no-console,\n func-names\n*/\n\n/** @typedef {any} TODO */\n\nvar normalizeUrl = require(\"./normalize-url\");\nvar srcByModuleId = Object.create(null);\nvar noDocument = typeof document === \"undefined\";\nvar forEach = Array.prototype.forEach;\n\n/**\n * @param {function} fn\n * @param {number} time\n * @returns {(function(): void)|*}\n */\nfunction debounce(fn, time) {\n var timeout = 0;\n return function () {\n // @ts-ignore\n var self = this;\n // eslint-disable-next-line prefer-rest-params\n var args = arguments;\n var functionCall = function functionCall() {\n return fn.apply(self, args);\n };\n clearTimeout(timeout);\n\n // @ts-ignore\n timeout = setTimeout(functionCall, time);\n };\n}\nfunction noop() {}\n\n/**\n * @param {TODO} moduleId\n * @returns {TODO}\n */\nfunction getCurrentScriptUrl(moduleId) {\n var src = srcByModuleId[moduleId];\n if (!src) {\n if (document.currentScript) {\n src = /** @type {HTMLScriptElement} */document.currentScript.src;\n } else {\n var scripts = document.getElementsByTagName(\"script\");\n var lastScriptTag = scripts[scripts.length - 1];\n if (lastScriptTag) {\n src = lastScriptTag.src;\n }\n }\n srcByModuleId[moduleId] = src;\n }\n\n /**\n * @param {string} fileMap\n * @returns {null | string[]}\n */\n return function (fileMap) {\n if (!src) {\n return null;\n }\n var splitResult = src.split(/([^\\\\/]+)\\.js$/);\n var filename = splitResult && splitResult[1];\n if (!filename) {\n return [src.replace(\".js\", \".css\")];\n }\n if (!fileMap) {\n return [src.replace(\".js\", \".css\")];\n }\n return fileMap.split(\",\").map(function (mapRule) {\n var reg = new RegExp(\"\".concat(filename, \"\\\\.js$\"), \"g\");\n return normalizeUrl(src.replace(reg, \"\".concat(mapRule.replace(/{fileName}/g, filename), \".css\")));\n });\n };\n}\n\n/**\n * @param {TODO} el\n * @param {string} [url]\n */\nfunction updateCss(el, url) {\n if (!url) {\n if (!el.href) {\n return;\n }\n\n // eslint-disable-next-line\n url = el.href.split(\"?\")[0];\n }\n if (!isUrlRequest( /** @type {string} */url)) {\n return;\n }\n if (el.isLoaded === false) {\n // We seem to be about to replace a css link that hasn't loaded yet.\n // We're probably changing the same file more than once.\n return;\n }\n if (!url || !(url.indexOf(\".css\") > -1)) {\n return;\n }\n\n // eslint-disable-next-line no-param-reassign\n el.visited = true;\n var newEl = el.cloneNode();\n newEl.isLoaded = false;\n newEl.addEventListener(\"load\", function () {\n if (newEl.isLoaded) {\n return;\n }\n newEl.isLoaded = true;\n el.parentNode.removeChild(el);\n });\n newEl.addEventListener(\"error\", function () {\n if (newEl.isLoaded) {\n return;\n }\n newEl.isLoaded = true;\n el.parentNode.removeChild(el);\n });\n newEl.href = \"\".concat(url, \"?\").concat(Date.now());\n if (el.nextSibling) {\n el.parentNode.insertBefore(newEl, el.nextSibling);\n } else {\n el.parentNode.appendChild(newEl);\n }\n}\n\n/**\n * @param {string} href\n * @param {TODO} src\n * @returns {TODO}\n */\nfunction getReloadUrl(href, src) {\n var ret;\n\n // eslint-disable-next-line no-param-reassign\n href = normalizeUrl(href);\n src.some(\n /**\n * @param {string} url\n */\n // eslint-disable-next-line array-callback-return\n function (url) {\n if (href.indexOf(src) > -1) {\n ret = url;\n }\n });\n return ret;\n}\n\n/**\n * @param {string} [src]\n * @returns {boolean}\n */\nfunction reloadStyle(src) {\n if (!src) {\n return false;\n }\n var elements = document.querySelectorAll(\"link\");\n var loaded = false;\n forEach.call(elements, function (el) {\n if (!el.href) {\n return;\n }\n var url = getReloadUrl(el.href, src);\n if (!isUrlRequest(url)) {\n return;\n }\n if (el.visited === true) {\n return;\n }\n if (url) {\n updateCss(el, url);\n loaded = true;\n }\n });\n return loaded;\n}\nfunction reloadAll() {\n var elements = document.querySelectorAll(\"link\");\n forEach.call(elements, function (el) {\n if (el.visited === true) {\n return;\n }\n updateCss(el);\n });\n}\n\n/**\n * @param {string} url\n * @returns {boolean}\n */\nfunction isUrlRequest(url) {\n // An URL is not an request if\n\n // It is not http or https\n if (!/^[a-zA-Z][a-zA-Z\\d+\\-.]*:/.test(url)) {\n return false;\n }\n return true;\n}\n\n/**\n * @param {TODO} moduleId\n * @param {TODO} options\n * @returns {TODO}\n */\nmodule.exports = function (moduleId, options) {\n if (noDocument) {\n console.log(\"no window.document found, will not HMR CSS\");\n return noop;\n }\n var getScriptSrc = getCurrentScriptUrl(moduleId);\n function update() {\n var src = getScriptSrc(options.filename);\n var reloaded = reloadStyle(src);\n if (options.locals) {\n console.log(\"[HMR] Detected local css modules. Reload all css\");\n reloadAll();\n return;\n }\n if (reloaded) {\n console.log(\"[HMR] css reload %s\", src.join(\" \"));\n } else {\n console.log(\"[HMR] Reload all css\");\n reloadAll();\n }\n }\n return debounce(update, 50);\n};","\"use strict\";\n\n/* eslint-disable */\n\n/**\n * @param {string[]} pathComponents\n * @returns {string}\n */\nfunction normalizeUrl(pathComponents) {\n return pathComponents.reduce(function (accumulator, item) {\n switch (item) {\n case \"..\":\n accumulator.pop();\n break;\n case \".\":\n break;\n default:\n accumulator.push(item);\n }\n return accumulator;\n }, /** @type {string[]} */[]).join(\"/\");\n}\n\n/**\n * @param {string} urlString\n * @returns {string}\n */\nmodule.exports = function (urlString) {\n urlString = urlString.trim();\n if (/^data:/i.test(urlString)) {\n return urlString;\n }\n var protocol = urlString.indexOf(\"//\") !== -1 ? urlString.split(\"//\")[0] + \"//\" : \"\";\n var components = urlString.replace(new RegExp(protocol, \"i\"), \"\").split(\"/\");\n var host = components[0].toLowerCase().replace(/\\.$/, \"\");\n components[0] = \"\";\n var path = normalizeUrl(components);\n return protocol + host + path;\n};","// extracted by mini-css-extract-plugin\nexport {};\n if(module.hot) {\n // 1672913089237\n var cssReload = require(\"../../../mini-css-extract-plugin@2.7.0_webpack@5.75.0/node_modules/mini-css-extract-plugin/dist/hmr/hotModuleReplacement.js\")(module.id, {\"locals\":false});\n module.hot.dispose(cssReload);\n module.hot.accept(undefined, cssReload);\n }\n ","/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress\n * @license MIT */\n\n;(function(root, factory) {\n\n if (typeof define === 'function' && define.amd) {\n define(factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.NProgress = factory();\n }\n\n})(this, function() {\n var NProgress = {};\n\n NProgress.version = '0.2.0';\n\n var Settings = NProgress.settings = {\n minimum: 0.08,\n easing: 'ease',\n positionUsing: '',\n speed: 200,\n trickle: true,\n trickleRate: 0.02,\n trickleSpeed: 800,\n showSpinner: true,\n barSelector: '[role=\"bar\"]',\n spinnerSelector: '[role=\"spinner\"]',\n parent: 'body',\n template: '<div class=\"bar\" role=\"bar\"><div class=\"peg\"></div></div><div class=\"spinner\" role=\"spinner\"><div class=\"spinner-icon\"></div></div>'\n };\n\n /**\n * Updates configuration.\n *\n * NProgress.configure({\n * minimum: 0.1\n * });\n */\n NProgress.configure = function(options) {\n var key, value;\n for (key in options) {\n value = options[key];\n if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value;\n }\n\n return this;\n };\n\n /**\n * Last number.\n */\n\n NProgress.status = null;\n\n /**\n * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.\n *\n * NProgress.set(0.4);\n * NProgress.set(1.0);\n */\n\n NProgress.set = function(n) {\n var started = NProgress.isStarted();\n\n n = clamp(n, Settings.minimum, 1);\n NProgress.status = (n === 1 ? null : n);\n\n var progress = NProgress.render(!started),\n bar = progress.querySelector(Settings.barSelector),\n speed = Settings.speed,\n ease = Settings.easing;\n\n progress.offsetWidth; /* Repaint */\n\n queue(function(next) {\n // Set positionUsing if it hasn't already been set\n if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS();\n\n // Add transition\n css(bar, barPositionCSS(n, speed, ease));\n\n if (n === 1) {\n // Fade out\n css(progress, { \n transition: 'none', \n opacity: 1 \n });\n progress.offsetWidth; /* Repaint */\n\n setTimeout(function() {\n css(progress, { \n transition: 'all ' + speed + 'ms linear', \n opacity: 0 \n });\n setTimeout(function() {\n NProgress.remove();\n next();\n }, speed);\n }, speed);\n } else {\n setTimeout(next, speed);\n }\n });\n\n return this;\n };\n\n NProgress.isStarted = function() {\n return typeof NProgress.status === 'number';\n };\n\n /**\n * Shows the progress bar.\n * This is the same as setting the status to 0%, except that it doesn't go backwards.\n *\n * NProgress.start();\n *\n */\n NProgress.start = function() {\n if (!NProgress.status) NProgress.set(0);\n\n var work = function() {\n setTimeout(function() {\n if (!NProgress.status) return;\n NProgress.trickle();\n work();\n }, Settings.trickleSpeed);\n };\n\n if (Settings.trickle) work();\n\n return this;\n };\n\n /**\n * Hides the progress bar.\n * This is the *sort of* the same as setting the status to 100%, with the\n * difference being `done()` makes some placebo effect of some realistic motion.\n *\n * NProgress.done();\n *\n * If `true` is passed, it will show the progress bar even if its hidden.\n *\n * NProgress.done(true);\n */\n\n NProgress.done = function(force) {\n if (!force && !NProgress.status) return this;\n\n return NProgress.inc(0.3 + 0.5 * Math.random()).set(1);\n };\n\n /**\n * Increments by a random amount.\n */\n\n NProgress.inc = function(amount) {\n var n = NProgress.status;\n\n if (!n) {\n return NProgress.start();\n } else {\n if (typeof amount !== 'number') {\n amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95);\n }\n\n n = clamp(n + amount, 0, 0.994);\n return NProgress.set(n);\n }\n };\n\n NProgress.trickle = function() {\n return NProgress.inc(Math.random() * Settings.trickleRate);\n };\n\n /**\n * Waits for all supplied jQuery promises and\n * increases the progress as the promises resolve.\n *\n * @param $promise jQUery Promise\n */\n (function() {\n var initial = 0, current = 0;\n\n NProgress.promise = function($promise) {\n if (!$promise || $promise.state() === \"resolved\") {\n return this;\n }\n\n if (current === 0) {\n NProgress.start();\n }\n\n initial++;\n current++;\n\n $promise.always(function() {\n current--;\n if (current === 0) {\n initial = 0;\n NProgress.done();\n } else {\n NProgress.set((initial - current) / initial);\n }\n });\n\n return this;\n };\n\n })();\n\n /**\n * (Internal) renders the progress bar markup based on the `template`\n * setting.\n */\n\n NProgress.render = function(fromStart) {\n if (NProgress.isRendered()) return document.getElementById('nprogress');\n\n addClass(document.documentElement, 'nprogress-busy');\n \n var progress = document.createElement('div');\n progress.id = 'nprogress';\n progress.innerHTML = Settings.template;\n\n var bar = progress.querySelector(Settings.barSelector),\n perc = fromStart ? '-100' : toBarPerc(NProgress.status || 0),\n parent = document.querySelector(Settings.parent),\n spinner;\n \n css(bar, {\n transition: 'all 0 linear',\n transform: 'translate3d(' + perc + '%,0,0)'\n });\n\n if (!Settings.showSpinner) {\n spinner = progress.querySelector(Settings.spinnerSelector);\n spinner && removeElement(spinner);\n }\n\n if (parent != document.body) {\n addClass(parent, 'nprogress-custom-parent');\n }\n\n parent.appendChild(progress);\n return progress;\n };\n\n /**\n * Removes the element. Opposite of render().\n */\n\n NProgress.remove = function() {\n removeClass(document.documentElement, 'nprogress-busy');\n removeClass(document.querySelector(Settings.parent), 'nprogress-custom-parent');\n var progress = document.getElementById('nprogress');\n progress && removeElement(progress);\n };\n\n /**\n * Checks if the progress bar is rendered.\n */\n\n NProgress.isRendered = function() {\n return !!document.getElementById('nprogress');\n };\n\n /**\n * Determine which positioning CSS rule to use.\n */\n\n NProgress.getPositioningCSS = function() {\n // Sniff on document.body.style\n var bodyStyle = document.body.style;\n\n // Sniff prefixes\n var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' :\n ('MozTransform' in bodyStyle) ? 'Moz' :\n ('msTransform' in bodyStyle) ? 'ms' :\n ('OTransform' in bodyStyle) ? 'O' : '';\n\n if (vendorPrefix + 'Perspective' in bodyStyle) {\n // Modern browsers with 3D support, e.g. Webkit, IE10\n return 'translate3d';\n } else if (vendorPrefix + 'Transform' in bodyStyle) {\n // Browsers without 3D support, e.g. IE9\n return 'translate';\n } else {\n // Browsers without translate() support, e.g. IE7-8\n return 'margin';\n }\n };\n\n /**\n * Helpers\n */\n\n function clamp(n, min, max) {\n if (n < min) return min;\n if (n > max) return max;\n return n;\n }\n\n /**\n * (Internal) converts a percentage (`0..1`) to a bar translateX\n * percentage (`-100%..0%`).\n */\n\n function toBarPerc(n) {\n return (-1 + n) * 100;\n }\n\n\n /**\n * (Internal) returns the correct CSS for changing the bar's\n * position given an n percentage, and speed and ease from Settings\n */\n\n function barPositionCSS(n, speed, ease) {\n var barCSS;\n\n if (Settings.positionUsing === 'translate3d') {\n barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' };\n } else if (Settings.positionUsing === 'translate') {\n barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' };\n } else {\n barCSS = { 'margin-left': toBarPerc(n)+'%' };\n }\n\n barCSS.transition = 'all '+speed+'ms '+ease;\n\n return barCSS;\n }\n\n /**\n * (Internal) Queues a function to be executed.\n */\n\n var queue = (function() {\n var pending = [];\n \n function next() {\n var fn = pending.shift();\n if (fn) {\n fn(next);\n }\n }\n\n return function(fn) {\n pending.push(fn);\n if (pending.length == 1) next();\n };\n })();\n\n /**\n * (Internal) Applies css properties to an element, similar to the jQuery \n * css method.\n *\n * While this helper does assist with vendor prefixed property names, it \n * does not perform any manipulation of values prior to setting styles.\n */\n\n var css = (function() {\n var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ],\n cssProps = {};\n\n function camelCase(string) {\n return string.replace(/^-ms-/, 'ms-').replace(/-([\\da-z])/gi, function(match, letter) {\n return letter.toUpperCase();\n });\n }\n\n function getVendorProp(name) {\n var style = document.body.style;\n if (name in style) return name;\n\n var i = cssPrefixes.length,\n capName = name.charAt(0).toUpperCase() + name.slice(1),\n vendorName;\n while (i--) {\n vendorName = cssPrefixes[i] + capName;\n if (vendorName in style) return vendorName;\n }\n\n return name;\n }\n\n function getStyleProp(name) {\n name = camelCase(name);\n return cssProps[name] || (cssProps[name] = getVendorProp(name));\n }\n\n function applyCss(element, prop, value) {\n prop = getStyleProp(prop);\n element.style[prop] = value;\n }\n\n return function(element, properties) {\n var args = arguments,\n prop, \n value;\n\n if (args.length == 2) {\n for (prop in properties) {\n value = properties[prop];\n if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value);\n }\n } else {\n applyCss(element, args[1], args[2]);\n }\n }\n })();\n\n /**\n * (Internal) Determines if an element or space separated list of class names contains a class name.\n */\n\n function hasClass(element, name) {\n var list = typeof element == 'string' ? element : classList(element);\n return list.indexOf(' ' + name + ' ') >= 0;\n }\n\n /**\n * (Internal) Adds a class to an element.\n */\n\n function addClass(element, name) {\n var oldList = classList(element),\n newList = oldList + name;\n\n if (hasClass(oldList, name)) return; \n\n // Trim the opening space.\n element.className = newList.substring(1);\n }\n\n /**\n * (Internal) Removes a class from an element.\n */\n\n function removeClass(element, name) {\n var oldList = classList(element),\n newList;\n\n if (!hasClass(element, name)) return;\n\n // Replace the class name.\n newList = oldList.replace(' ' + name + ' ', ' ');\n\n // Trim the opening and closing spaces.\n element.className = newList.substring(1, newList.length - 1);\n }\n\n /**\n * (Internal) Gets a space separated list of the class names on the element. \n * The list is wrapped with a single space on each end to facilitate finding \n * matches within the list.\n */\n\n function classList(element) {\n return (' ' + (element.className || '') + ' ').replace(/\\s+/gi, ' ');\n }\n\n /**\n * (Internal) Removes an element from the DOM.\n */\n\n function removeElement(element) {\n element && element.parentNode && element.parentNode.removeChild(element);\n }\n\n return NProgress;\n});\n\n","/*\nobject-assign\n(c) Sindre Sorhus\n@license MIT\n*/\n\n'use strict';\n/* eslint-disable no-unused-vars */\nvar getOwnPropertySymbols = Object.getOwnPropertySymbols;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar propIsEnumerable = Object.prototype.propertyIsEnumerable;\n\nfunction toObject(val) {\n\tif (val === null || val === undefined) {\n\t\tthrow new TypeError('Object.assign cannot be called with null or undefined');\n\t}\n\n\treturn Object(val);\n}\n\nfunction shouldUseNative() {\n\ttry {\n\t\tif (!Object.assign) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Detect buggy property enumeration order in older V8 versions.\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=4118\n\t\tvar test1 = new String('abc'); // eslint-disable-line no-new-wrappers\n\t\ttest1[5] = 'de';\n\t\tif (Object.getOwnPropertyNames(test1)[0] === '5') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test2 = {};\n\t\tfor (var i = 0; i < 10; i++) {\n\t\t\ttest2['_' + String.fromCharCode(i)] = i;\n\t\t}\n\t\tvar order2 = Object.getOwnPropertyNames(test2).map(function (n) {\n\t\t\treturn test2[n];\n\t\t});\n\t\tif (order2.join('') !== '0123456789') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test3 = {};\n\t\t'abcdefghijklmnopqrst'.split('').forEach(function (letter) {\n\t\t\ttest3[letter] = letter;\n\t\t});\n\t\tif (Object.keys(Object.assign({}, test3)).join('') !==\n\t\t\t\t'abcdefghijklmnopqrst') {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t} catch (err) {\n\t\t// We don't expect any of the above to throw, but better to be safe.\n\t\treturn false;\n\t}\n}\n\nmodule.exports = shouldUseNative() ? Object.assign : function (target, source) {\n\tvar from;\n\tvar to = toObject(target);\n\tvar symbols;\n\n\tfor (var s = 1; s < arguments.length; s++) {\n\t\tfrom = Object(arguments[s]);\n\n\t\tfor (var key in from) {\n\t\t\tif (hasOwnProperty.call(from, key)) {\n\t\t\t\tto[key] = from[key];\n\t\t\t}\n\t\t}\n\n\t\tif (getOwnPropertySymbols) {\n\t\t\tsymbols = getOwnPropertySymbols(from);\n\t\t\tfor (var i = 0; i < symbols.length; i++) {\n\t\t\t\tif (propIsEnumerable.call(from, symbols[i])) {\n\t\t\t\t\tto[symbols[i]] = from[symbols[i]];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn to;\n};\n","/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nvar printWarning = function() {};\n\nif (process.env.NODE_ENV !== 'production') {\n var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret');\n var loggedTypeFailures = {};\n var has = require('./lib/has');\n\n printWarning = function(text) {\n var message = 'Warning: ' + text;\n if (typeof console !== 'undefined') {\n console.error(message);\n }\n try {\n // --- Welcome to debugging React ---\n // This error was thrown as a convenience so that you can use this stack\n // to find the callsite that caused this warning to fire.\n throw new Error(message);\n } catch (x) { /**/ }\n };\n}\n\n/**\n * Assert that the values match with the type specs.\n * Error messages are memorized and will only be shown once.\n *\n * @param {object} typeSpecs Map of name to a ReactPropType\n * @param {object} values Runtime values that need to be type-checked\n * @param {string} location e.g. \"prop\", \"context\", \"child context\"\n * @param {string} componentName Name of the component for error messages.\n * @param {?Function} getStack Returns the component stack.\n * @private\n */\nfunction checkPropTypes(typeSpecs, values, location, componentName, getStack) {\n if (process.env.NODE_ENV !== 'production') {\n for (var typeSpecName in typeSpecs) {\n if (has(typeSpecs, typeSpecName)) {\n var error;\n // Prop type validation may throw. In case they do, we don't want to\n // fail the render phase where it didn't fail before. So we log it.\n // After these have been cleaned up, we'll let them throw.\n try {\n // This is intentionally an invariant that gets caught. It's the same\n // behavior as without this statement except with a better message.\n if (typeof typeSpecs[typeSpecName] !== 'function') {\n var err = Error(\n (componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' +\n 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' +\n 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.'\n );\n err.name = 'Invariant Violation';\n throw err;\n }\n error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);\n } catch (ex) {\n error = ex;\n }\n if (error && !(error instanceof Error)) {\n printWarning(\n (componentName || 'React class') + ': type specification of ' +\n location + ' `' + typeSpecName + '` is invalid; the type checker ' +\n 'function must return `null` or an `Error` but returned a ' + typeof error + '. ' +\n 'You may have forgotten to pass an argument to the type checker ' +\n 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' +\n 'shape all require an argument).'\n );\n }\n if (error instanceof Error && !(error.message in loggedTypeFailures)) {\n // Only monitor this failure once because there tends to be a lot of the\n // same error.\n loggedTypeFailures[error.message] = true;\n\n var stack = getStack ? getStack() : '';\n\n printWarning(\n 'Failed ' + location + ' type: ' + error.message + (stack != null ? stack : '')\n );\n }\n }\n }\n }\n}\n\n/**\n * Resets warning cache when testing.\n *\n * @private\n */\ncheckPropTypes.resetWarningCache = function() {\n if (process.env.NODE_ENV !== 'production') {\n loggedTypeFailures = {};\n }\n}\n\nmodule.exports = checkPropTypes;\n","/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nvar ReactIs = require('react-is');\nvar assign = require('object-assign');\n\nvar ReactPropTypesSecret = require('./lib/ReactPropTypesSecret');\nvar has = require('./lib/has');\nvar checkPropTypes = require('./checkPropTypes');\n\nvar printWarning = function() {};\n\nif (process.env.NODE_ENV !== 'production') {\n printWarning = function(text) {\n var message = 'Warning: ' + text;\n if (typeof console !== 'undefined') {\n console.error(message);\n }\n try {\n // --- Welcome to debugging React ---\n // This error was thrown as a convenience so that you can use this stack\n // to find the callsite that caused this warning to fire.\n throw new Error(message);\n } catch (x) {}\n };\n}\n\nfunction emptyFunctionThatReturnsNull() {\n return null;\n}\n\nmodule.exports = function(isValidElement, throwOnDirectAccess) {\n /* global Symbol */\n var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;\n var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.\n\n /**\n * Returns the iterator method function contained on the iterable object.\n *\n * Be sure to invoke the function with the iterable as context:\n *\n * var iteratorFn = getIteratorFn(myIterable);\n * if (iteratorFn) {\n * var iterator = iteratorFn.call(myIterable);\n * ...\n * }\n *\n * @param {?object} maybeIterable\n * @return {?function}\n */\n function getIteratorFn(maybeIterable) {\n var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);\n if (typeof iteratorFn === 'function') {\n return iteratorFn;\n }\n }\n\n /**\n * Collection of methods that allow declaration and validation of props that are\n * supplied to React components. Example usage:\n *\n * var Props = require('ReactPropTypes');\n * var MyArticle = React.createClass({\n * propTypes: {\n * // An optional string prop named \"description\".\n * description: Props.string,\n *\n * // A required enum prop named \"category\".\n * category: Props.oneOf(['News','Photos']).isRequired,\n *\n * // A prop named \"dialog\" that requires an instance of Dialog.\n * dialog: Props.instanceOf(Dialog).isRequired\n * },\n * render: function() { ... }\n * });\n *\n * A more formal specification of how these methods are used:\n *\n * type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)\n * decl := ReactPropTypes.{type}(.isRequired)?\n *\n * Each and every declaration produces a function with the same signature. This\n * allows the creation of custom validation functions. For example:\n *\n * var MyLink = React.createClass({\n * propTypes: {\n * // An optional string or URI prop named \"href\".\n * href: function(props, propName, componentName) {\n * var propValue = props[propName];\n * if (propValue != null && typeof propValue !== 'string' &&\n * !(propValue instanceof URI)) {\n * return new Error(\n * 'Expected a string or an URI for ' + propName + ' in ' +\n * componentName\n * );\n * }\n * }\n * },\n * render: function() {...}\n * });\n *\n * @internal\n */\n\n var ANONYMOUS = '<<anonymous>>';\n\n // Important!\n // Keep this list in sync with production version in `./factoryWithThrowingShims.js`.\n var ReactPropTypes = {\n array: createPrimitiveTypeChecker('array'),\n bigint: createPrimitiveTypeChecker('bigint'),\n bool: createPrimitiveTypeChecker('boolean'),\n func: createPrimitiveTypeChecker('function'),\n number: createPrimitiveTypeChecker('number'),\n object: createPrimitiveTypeChecker('object'),\n string: createPrimitiveTypeChecker('string'),\n symbol: createPrimitiveTypeChecker('symbol'),\n\n any: createAnyTypeChecker(),\n arrayOf: createArrayOfTypeChecker,\n element: createElementTypeChecker(),\n elementType: createElementTypeTypeChecker(),\n instanceOf: createInstanceTypeChecker,\n node: createNodeChecker(),\n objectOf: createObjectOfTypeChecker,\n oneOf: createEnumTypeChecker,\n oneOfType: createUnionTypeChecker,\n shape: createShapeTypeChecker,\n exact: createStrictShapeTypeChecker,\n };\n\n /**\n * inlined Object.is polyfill to avoid requiring consumers ship their own\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n */\n /*eslint-disable no-self-compare*/\n function is(x, y) {\n // SameValue algorithm\n if (x === y) {\n // Steps 1-5, 7-10\n // Steps 6.b-6.e: +0 != -0\n return x !== 0 || 1 / x === 1 / y;\n } else {\n // Step 6.a: NaN == NaN\n return x !== x && y !== y;\n }\n }\n /*eslint-enable no-self-compare*/\n\n /**\n * We use an Error-like object for backward compatibility as people may call\n * PropTypes directly and inspect their output. However, we don't use real\n * Errors anymore. We don't inspect their stack anyway, and creating them\n * is prohibitively expensive if they are created too often, such as what\n * happens in oneOfType() for any type before the one that matched.\n */\n function PropTypeError(message, data) {\n this.message = message;\n this.data = data && typeof data === 'object' ? data: {};\n this.stack = '';\n }\n // Make `instanceof Error` still work for returned errors.\n PropTypeError.prototype = Error.prototype;\n\n function createChainableTypeChecker(validate) {\n if (process.env.NODE_ENV !== 'production') {\n var manualPropTypeCallCache = {};\n var manualPropTypeWarningCount = 0;\n }\n function checkType(isRequired, props, propName, componentName, location, propFullName, secret) {\n componentName = componentName || ANONYMOUS;\n propFullName = propFullName || propName;\n\n if (secret !== ReactPropTypesSecret) {\n if (throwOnDirectAccess) {\n // New behavior only for users of `prop-types` package\n var err = new Error(\n 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +\n 'Use `PropTypes.checkPropTypes()` to call them. ' +\n 'Read more at http://fb.me/use-check-prop-types'\n );\n err.name = 'Invariant Violation';\n throw err;\n } else if (process.env.NODE_ENV !== 'production' && typeof console !== 'undefined') {\n // Old behavior for people using React.PropTypes\n var cacheKey = componentName + ':' + propName;\n if (\n !manualPropTypeCallCache[cacheKey] &&\n // Avoid spamming the console because they are often not actionable except for lib authors\n manualPropTypeWarningCount < 3\n ) {\n printWarning(\n 'You are manually calling a React.PropTypes validation ' +\n 'function for the `' + propFullName + '` prop on `' + componentName + '`. This is deprecated ' +\n 'and will throw in the standalone `prop-types` package. ' +\n 'You may be seeing this warning due to a third-party PropTypes ' +\n 'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.'\n );\n manualPropTypeCallCache[cacheKey] = true;\n manualPropTypeWarningCount++;\n }\n }\n }\n if (props[propName] == null) {\n if (isRequired) {\n if (props[propName] === null) {\n return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.'));\n }\n return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.'));\n }\n return null;\n } else {\n return validate(props, propName, componentName, location, propFullName);\n }\n }\n\n var chainedCheckType = checkType.bind(null, false);\n chainedCheckType.isRequired = checkType.bind(null, true);\n\n return chainedCheckType;\n }\n\n function createPrimitiveTypeChecker(expectedType) {\n function validate(props, propName, componentName, location, propFullName, secret) {\n var propValue = props[propName];\n var propType = getPropType(propValue);\n if (propType !== expectedType) {\n // `propValue` being instance of, say, date/regexp, pass the 'object'\n // check, but we can offer a more precise error message here rather than\n // 'of type `object`'.\n var preciseType = getPreciseType(propValue);\n\n return new PropTypeError(\n 'Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'),\n {expectedType: expectedType}\n );\n }\n return null;\n }\n return createChainableTypeChecker(validate);\n }\n\n function createAnyTypeChecker() {\n return createChainableTypeChecker(emptyFunctionThatReturnsNull);\n }\n\n function createArrayOfTypeChecker(typeChecker) {\n function validate(props, propName, componentName, location, propFullName) {\n if (typeof typeChecker !== 'function') {\n return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.');\n }\n var propValue = props[propName];\n if (!Array.isArray(propValue)) {\n var propType = getPropType(propValue);\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.'));\n }\n for (var i = 0; i < propValue.length; i++) {\n var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']', ReactPropTypesSecret);\n if (error instanceof Error) {\n return error;\n }\n }\n return null;\n }\n return createChainableTypeChecker(validate);\n }\n\n function createElementTypeChecker() {\n function validate(props, propName, componentName, location, propFullName) {\n var propValue = props[propName];\n if (!isValidElement(propValue)) {\n var propType = getPropType(propValue);\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement.'));\n }\n return null;\n }\n return createChainableTypeChecker(validate);\n }\n\n function createElementTypeTypeChecker() {\n function validate(props, propName, componentName, location, propFullName) {\n var propValue = props[propName];\n if (!ReactIs.isValidElementType(propValue)) {\n var propType = getPropType(propValue);\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement type.'));\n }\n return null;\n }\n return createChainableTypeChecker(validate);\n }\n\n function createInstanceTypeChecker(expectedClass) {\n function validate(props, propName, componentName, location, propFullName) {\n if (!(props[propName] instanceof expectedClass)) {\n var expectedClassName = expectedClass.name || ANONYMOUS;\n var actualClassName = getClassName(props[propName]);\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.'));\n }\n return null;\n }\n return createChainableTypeChecker(validate);\n }\n\n function createEnumTypeChecker(expectedValues) {\n if (!Array.isArray(expectedValues)) {\n if (process.env.NODE_ENV !== 'production') {\n if (arguments.length > 1) {\n printWarning(\n 'Invalid arguments supplied to oneOf, expected an array, got ' + arguments.length + ' arguments. ' +\n 'A common mistake is to write oneOf(x, y, z) instead of oneOf([x, y, z]).'\n );\n } else {\n printWarning('Invalid argument supplied to oneOf, expected an array.');\n }\n }\n return emptyFunctionThatReturnsNull;\n }\n\n function validate(props, propName, componentName, location, propFullName) {\n var propValue = props[propName];\n for (var i = 0; i < expectedValues.length; i++) {\n if (is(propValue, expectedValues[i])) {\n return null;\n }\n }\n\n var valuesString = JSON.stringify(expectedValues, function replacer(key, value) {\n var type = getPreciseType(value);\n if (type === 'symbol') {\n return String(value);\n }\n return value;\n });\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of value `' + String(propValue) + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.'));\n }\n return createChainableTypeChecker(validate);\n }\n\n function createObjectOfTypeChecker(typeChecker) {\n function validate(props, propName, componentName, location, propFullName) {\n if (typeof typeChecker !== 'function') {\n return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.');\n }\n var propValue = props[propName];\n var propType = getPropType(propValue);\n if (propType !== 'object') {\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.'));\n }\n for (var key in propValue) {\n if (has(propValue, key)) {\n var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);\n if (error instanceof Error) {\n return error;\n }\n }\n }\n return null;\n }\n return createChainableTypeChecker(validate);\n }\n\n function createUnionTypeChecker(arrayOfTypeCheckers) {\n if (!Array.isArray(arrayOfTypeCheckers)) {\n process.env.NODE_ENV !== 'production' ? printWarning('Invalid argument supplied to oneOfType, expected an instance of array.') : void 0;\n return emptyFunctionThatReturnsNull;\n }\n\n for (var i = 0; i < arrayOfTypeCheckers.length; i++) {\n var checker = arrayOfTypeCheckers[i];\n if (typeof checker !== 'function') {\n printWarning(\n 'Invalid argument supplied to oneOfType. Expected an array of check functions, but ' +\n 'received ' + getPostfixForTypeWarning(checker) + ' at index ' + i + '.'\n );\n return emptyFunctionThatReturnsNull;\n }\n }\n\n function validate(props, propName, componentName, location, propFullName) {\n var expectedTypes = [];\n for (var i = 0; i < arrayOfTypeCheckers.length; i++) {\n var checker = arrayOfTypeCheckers[i];\n var checkerResult = checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret);\n if (checkerResult == null) {\n return null;\n }\n if (checkerResult.data && has(checkerResult.data, 'expectedType')) {\n expectedTypes.push(checkerResult.data.expectedType);\n }\n }\n var expectedTypesMessage = (expectedTypes.length > 0) ? ', expected one of type [' + expectedTypes.join(', ') + ']': '';\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`' + expectedTypesMessage + '.'));\n }\n return createChainableTypeChecker(validate);\n }\n\n function createNodeChecker() {\n function validate(props, propName, componentName, location, propFullName) {\n if (!isNode(props[propName])) {\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.'));\n }\n return null;\n }\n return createChainableTypeChecker(validate);\n }\n\n function invalidValidatorError(componentName, location, propFullName, key, type) {\n return new PropTypeError(\n (componentName || 'React class') + ': ' + location + ' type `' + propFullName + '.' + key + '` is invalid; ' +\n 'it must be a function, usually from the `prop-types` package, but received `' + type + '`.'\n );\n }\n\n function createShapeTypeChecker(shapeTypes) {\n function validate(props, propName, componentName, location, propFullName) {\n var propValue = props[propName];\n var propType = getPropType(propValue);\n if (propType !== 'object') {\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));\n }\n for (var key in shapeTypes) {\n var checker = shapeTypes[key];\n if (typeof checker !== 'function') {\n return invalidValidatorError(componentName, location, propFullName, key, getPreciseType(checker));\n }\n var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);\n if (error) {\n return error;\n }\n }\n return null;\n }\n return createChainableTypeChecker(validate);\n }\n\n function createStrictShapeTypeChecker(shapeTypes) {\n function validate(props, propName, componentName, location, propFullName) {\n var propValue = props[propName];\n var propType = getPropType(propValue);\n if (propType !== 'object') {\n return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));\n }\n // We need to check all keys in case some are required but missing from props.\n var allKeys = assign({}, props[propName], shapeTypes);\n for (var key in allKeys) {\n var checker = shapeTypes[key];\n if (has(shapeTypes, key) && typeof checker !== 'function') {\n return invalidValidatorError(componentName, location, propFullName, key, getPreciseType(checker));\n }\n if (!checker) {\n return new PropTypeError(\n 'Invalid ' + location + ' `' + propFullName + '` key `' + key + '` supplied to `' + componentName + '`.' +\n '\\nBad object: ' + JSON.stringify(props[propName], null, ' ') +\n '\\nValid keys: ' + JSON.stringify(Object.keys(shapeTypes), null, ' ')\n );\n }\n var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);\n if (error) {\n return error;\n }\n }\n return null;\n }\n\n return createChainableTypeChecker(validate);\n }\n\n function isNode(propValue) {\n switch (typeof propValue) {\n case 'number':\n case 'string':\n case 'undefined':\n return true;\n case 'boolean':\n return !propValue;\n case 'object':\n if (Array.isArray(propValue)) {\n return propValue.every(isNode);\n }\n if (propValue === null || isValidElement(propValue)) {\n return true;\n }\n\n var iteratorFn = getIteratorFn(propValue);\n if (iteratorFn) {\n var iterator = iteratorFn.call(propValue);\n var step;\n if (iteratorFn !== propValue.entries) {\n while (!(step = iterator.next()).done) {\n if (!isNode(step.value)) {\n return false;\n }\n }\n } else {\n // Iterator will provide entry [k,v] tuples rather than values.\n while (!(step = iterator.next()).done) {\n var entry = step.value;\n if (entry) {\n if (!isNode(entry[1])) {\n return false;\n }\n }\n }\n }\n } else {\n return false;\n }\n\n return true;\n default:\n return false;\n }\n }\n\n function isSymbol(propType, propValue) {\n // Native Symbol.\n if (propType === 'symbol') {\n return true;\n }\n\n // falsy value can't be a Symbol\n if (!propValue) {\n return false;\n }\n\n // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'\n if (propValue['@@toStringTag'] === 'Symbol') {\n return true;\n }\n\n // Fallback for non-spec compliant Symbols which are polyfilled.\n if (typeof Symbol === 'function' && propValue instanceof Symbol) {\n return true;\n }\n\n return false;\n }\n\n // Equivalent of `typeof` but with special handling for array and regexp.\n function getPropType(propValue) {\n var propType = typeof propValue;\n if (Array.isArray(propValue)) {\n return 'array';\n }\n if (propValue instanceof RegExp) {\n // Old webkits (at least until Android 4.0) return 'function' rather than\n // 'object' for typeof a RegExp. We'll normalize this here so that /bla/\n // passes PropTypes.object.\n return 'object';\n }\n if (isSymbol(propType, propValue)) {\n return 'symbol';\n }\n return propType;\n }\n\n // This handles more types than `getPropType`. Only used for error messages.\n // See `createPrimitiveTypeChecker`.\n function getPreciseType(propValue) {\n if (typeof propValue === 'undefined' || propValue === null) {\n return '' + propValue;\n }\n var propType = getPropType(propValue);\n if (propType === 'object') {\n if (propValue instanceof Date) {\n return 'date';\n } else if (propValue instanceof RegExp) {\n return 'regexp';\n }\n }\n return propType;\n }\n\n // Returns a string that is postfixed to a warning about an invalid type.\n // For example, \"undefined\" or \"of type array\"\n function getPostfixForTypeWarning(value) {\n var type = getPreciseType(value);\n switch (type) {\n case 'array':\n case 'object':\n return 'an ' + type;\n case 'boolean':\n case 'date':\n case 'regexp':\n return 'a ' + type;\n default:\n return type;\n }\n }\n\n // Returns class name of the object, if any.\n function getClassName(propValue) {\n if (!propValue.constructor || !propValue.constructor.name) {\n return ANONYMOUS;\n }\n return propValue.constructor.name;\n }\n\n ReactPropTypes.checkPropTypes = checkPropTypes;\n ReactPropTypes.resetWarningCache = checkPropTypes.resetWarningCache;\n ReactPropTypes.PropTypes = ReactPropTypes;\n\n return ReactPropTypes;\n};\n","/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nif (process.env.NODE_ENV !== 'production') {\n var ReactIs = require('react-is');\n\n // By explicitly using `prop-types` you are opting into new development behavior.\n // http://fb.me/prop-types-in-prod\n var throwOnDirectAccess = true;\n module.exports = require('./factoryWithTypeCheckers')(ReactIs.isElement, throwOnDirectAccess);\n} else {\n // By explicitly using `prop-types` you are opting into new production behavior.\n // http://fb.me/prop-types-in-prod\n module.exports = require('./factoryWithThrowingShims')();\n}\n","/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nvar ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';\n\nmodule.exports = ReactPropTypesSecret;\n","module.exports = Function.call.bind(Object.prototype.hasOwnProperty);\n","/**\n * @license React\n * scheduler.development.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nif (process.env.NODE_ENV !== \"production\") {\n (function() {\n\n 'use strict';\n\n/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\nif (\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart ===\n 'function'\n) {\n __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());\n}\n var enableSchedulerDebugging = false;\nvar enableProfiling = false;\nvar frameYieldMs = 5;\n\nfunction push(heap, node) {\n var index = heap.length;\n heap.push(node);\n siftUp(heap, node, index);\n}\nfunction peek(heap) {\n return heap.length === 0 ? null : heap[0];\n}\nfunction pop(heap) {\n if (heap.length === 0) {\n return null;\n }\n\n var first = heap[0];\n var last = heap.pop();\n\n if (last !== first) {\n heap[0] = last;\n siftDown(heap, last, 0);\n }\n\n return first;\n}\n\nfunction siftUp(heap, node, i) {\n var index = i;\n\n while (index > 0) {\n var parentIndex = index - 1 >>> 1;\n var parent = heap[parentIndex];\n\n if (compare(parent, node) > 0) {\n // The parent is larger. Swap positions.\n heap[parentIndex] = node;\n heap[index] = parent;\n index = parentIndex;\n } else {\n // The parent is smaller. Exit.\n return;\n }\n }\n}\n\nfunction siftDown(heap, node, i) {\n var index = i;\n var length = heap.length;\n var halfLength = length >>> 1;\n\n while (index < halfLength) {\n var leftIndex = (index + 1) * 2 - 1;\n var left = heap[leftIndex];\n var rightIndex = leftIndex + 1;\n var right = heap[rightIndex]; // If the left or right node is smaller, swap with the smaller of those.\n\n if (compare(left, node) < 0) {\n if (rightIndex < length && compare(right, left) < 0) {\n heap[index] = right;\n heap[rightIndex] = node;\n index = rightIndex;\n } else {\n heap[index] = left;\n heap[leftIndex] = node;\n index = leftIndex;\n }\n } else if (rightIndex < length && compare(right, node) < 0) {\n heap[index] = right;\n heap[rightIndex] = node;\n index = rightIndex;\n } else {\n // Neither child is smaller. Exit.\n return;\n }\n }\n}\n\nfunction compare(a, b) {\n // Compare sort index first, then task id.\n var diff = a.sortIndex - b.sortIndex;\n return diff !== 0 ? diff : a.id - b.id;\n}\n\n// TODO: Use symbols?\nvar ImmediatePriority = 1;\nvar UserBlockingPriority = 2;\nvar NormalPriority = 3;\nvar LowPriority = 4;\nvar IdlePriority = 5;\n\nfunction markTaskErrored(task, ms) {\n}\n\n/* eslint-disable no-var */\n\nvar hasPerformanceNow = typeof performance === 'object' && typeof performance.now === 'function';\n\nif (hasPerformanceNow) {\n var localPerformance = performance;\n\n exports.unstable_now = function () {\n return localPerformance.now();\n };\n} else {\n var localDate = Date;\n var initialTime = localDate.now();\n\n exports.unstable_now = function () {\n return localDate.now() - initialTime;\n };\n} // Max 31 bit integer. The max integer size in V8 for 32-bit systems.\n// Math.pow(2, 30) - 1\n// 0b111111111111111111111111111111\n\n\nvar maxSigned31BitInt = 1073741823; // Times out immediately\n\nvar IMMEDIATE_PRIORITY_TIMEOUT = -1; // Eventually times out\n\nvar USER_BLOCKING_PRIORITY_TIMEOUT = 250;\nvar NORMAL_PRIORITY_TIMEOUT = 5000;\nvar LOW_PRIORITY_TIMEOUT = 10000; // Never times out\n\nvar IDLE_PRIORITY_TIMEOUT = maxSigned31BitInt; // Tasks are stored on a min heap\n\nvar taskQueue = [];\nvar timerQueue = []; // Incrementing id counter. Used to maintain insertion order.\n\nvar taskIdCounter = 1; // Pausing the scheduler is useful for debugging.\nvar currentTask = null;\nvar currentPriorityLevel = NormalPriority; // This is set while performing work, to prevent re-entrance.\n\nvar isPerformingWork = false;\nvar isHostCallbackScheduled = false;\nvar isHostTimeoutScheduled = false; // Capture local references to native APIs, in case a polyfill overrides them.\n\nvar localSetTimeout = typeof setTimeout === 'function' ? setTimeout : null;\nvar localClearTimeout = typeof clearTimeout === 'function' ? clearTimeout : null;\nvar localSetImmediate = typeof setImmediate !== 'undefined' ? setImmediate : null; // IE and Node.js + jsdom\n\nvar isInputPending = typeof navigator !== 'undefined' && navigator.scheduling !== undefined && navigator.scheduling.isInputPending !== undefined ? navigator.scheduling.isInputPending.bind(navigator.scheduling) : null;\n\nfunction advanceTimers(currentTime) {\n // Check for tasks that are no longer delayed and add them to the queue.\n var timer = peek(timerQueue);\n\n while (timer !== null) {\n if (timer.callback === null) {\n // Timer was cancelled.\n pop(timerQueue);\n } else if (timer.startTime <= currentTime) {\n // Timer fired. Transfer to the task queue.\n pop(timerQueue);\n timer.sortIndex = timer.expirationTime;\n push(taskQueue, timer);\n } else {\n // Remaining timers are pending.\n return;\n }\n\n timer = peek(timerQueue);\n }\n}\n\nfunction handleTimeout(currentTime) {\n isHostTimeoutScheduled = false;\n advanceTimers(currentTime);\n\n if (!isHostCallbackScheduled) {\n if (peek(taskQueue) !== null) {\n isHostCallbackScheduled = true;\n requestHostCallback(flushWork);\n } else {\n var firstTimer = peek(timerQueue);\n\n if (firstTimer !== null) {\n requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);\n }\n }\n }\n}\n\nfunction flushWork(hasTimeRemaining, initialTime) {\n\n\n isHostCallbackScheduled = false;\n\n if (isHostTimeoutScheduled) {\n // We scheduled a timeout but it's no longer needed. Cancel it.\n isHostTimeoutScheduled = false;\n cancelHostTimeout();\n }\n\n isPerformingWork = true;\n var previousPriorityLevel = currentPriorityLevel;\n\n try {\n if (enableProfiling) {\n try {\n return workLoop(hasTimeRemaining, initialTime);\n } catch (error) {\n if (currentTask !== null) {\n var currentTime = exports.unstable_now();\n markTaskErrored(currentTask, currentTime);\n currentTask.isQueued = false;\n }\n\n throw error;\n }\n } else {\n // No catch in prod code path.\n return workLoop(hasTimeRemaining, initialTime);\n }\n } finally {\n currentTask = null;\n currentPriorityLevel = previousPriorityLevel;\n isPerformingWork = false;\n }\n}\n\nfunction workLoop(hasTimeRemaining, initialTime) {\n var currentTime = initialTime;\n advanceTimers(currentTime);\n currentTask = peek(taskQueue);\n\n while (currentTask !== null && !(enableSchedulerDebugging )) {\n if (currentTask.expirationTime > currentTime && (!hasTimeRemaining || shouldYieldToHost())) {\n // This currentTask hasn't expired, and we've reached the deadline.\n break;\n }\n\n var callback = currentTask.callback;\n\n if (typeof callback === 'function') {\n currentTask.callback = null;\n currentPriorityLevel = currentTask.priorityLevel;\n var didUserCallbackTimeout = currentTask.expirationTime <= currentTime;\n\n var continuationCallback = callback(didUserCallbackTimeout);\n currentTime = exports.unstable_now();\n\n if (typeof continuationCallback === 'function') {\n currentTask.callback = continuationCallback;\n } else {\n\n if (currentTask === peek(taskQueue)) {\n pop(taskQueue);\n }\n }\n\n advanceTimers(currentTime);\n } else {\n pop(taskQueue);\n }\n\n currentTask = peek(taskQueue);\n } // Return whether there's additional work\n\n\n if (currentTask !== null) {\n return true;\n } else {\n var firstTimer = peek(timerQueue);\n\n if (firstTimer !== null) {\n requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);\n }\n\n return false;\n }\n}\n\nfunction unstable_runWithPriority(priorityLevel, eventHandler) {\n switch (priorityLevel) {\n case ImmediatePriority:\n case UserBlockingPriority:\n case NormalPriority:\n case LowPriority:\n case IdlePriority:\n break;\n\n default:\n priorityLevel = NormalPriority;\n }\n\n var previousPriorityLevel = currentPriorityLevel;\n currentPriorityLevel = priorityLevel;\n\n try {\n return eventHandler();\n } finally {\n currentPriorityLevel = previousPriorityLevel;\n }\n}\n\nfunction unstable_next(eventHandler) {\n var priorityLevel;\n\n switch (currentPriorityLevel) {\n case ImmediatePriority:\n case UserBlockingPriority:\n case NormalPriority:\n // Shift down to normal priority\n priorityLevel = NormalPriority;\n break;\n\n default:\n // Anything lower than normal priority should remain at the current level.\n priorityLevel = currentPriorityLevel;\n break;\n }\n\n var previousPriorityLevel = currentPriorityLevel;\n currentPriorityLevel = priorityLevel;\n\n try {\n return eventHandler();\n } finally {\n currentPriorityLevel = previousPriorityLevel;\n }\n}\n\nfunction unstable_wrapCallback(callback) {\n var parentPriorityLevel = currentPriorityLevel;\n return function () {\n // This is a fork of runWithPriority, inlined for performance.\n var previousPriorityLevel = currentPriorityLevel;\n currentPriorityLevel = parentPriorityLevel;\n\n try {\n return callback.apply(this, arguments);\n } finally {\n currentPriorityLevel = previousPriorityLevel;\n }\n };\n}\n\nfunction unstable_scheduleCallback(priorityLevel, callback, options) {\n var currentTime = exports.unstable_now();\n var startTime;\n\n if (typeof options === 'object' && options !== null) {\n var delay = options.delay;\n\n if (typeof delay === 'number' && delay > 0) {\n startTime = currentTime + delay;\n } else {\n startTime = currentTime;\n }\n } else {\n startTime = currentTime;\n }\n\n var timeout;\n\n switch (priorityLevel) {\n case ImmediatePriority:\n timeout = IMMEDIATE_PRIORITY_TIMEOUT;\n break;\n\n case UserBlockingPriority:\n timeout = USER_BLOCKING_PRIORITY_TIMEOUT;\n break;\n\n case IdlePriority:\n timeout = IDLE_PRIORITY_TIMEOUT;\n break;\n\n case LowPriority:\n timeout = LOW_PRIORITY_TIMEOUT;\n break;\n\n case NormalPriority:\n default:\n timeout = NORMAL_PRIORITY_TIMEOUT;\n break;\n }\n\n var expirationTime = startTime + timeout;\n var newTask = {\n id: taskIdCounter++,\n callback: callback,\n priorityLevel: priorityLevel,\n startTime: startTime,\n expirationTime: expirationTime,\n sortIndex: -1\n };\n\n if (startTime > currentTime) {\n // This is a delayed task.\n newTask.sortIndex = startTime;\n push(timerQueue, newTask);\n\n if (peek(taskQueue) === null && newTask === peek(timerQueue)) {\n // All tasks are delayed, and this is the task with the earliest delay.\n if (isHostTimeoutScheduled) {\n // Cancel an existing timeout.\n cancelHostTimeout();\n } else {\n isHostTimeoutScheduled = true;\n } // Schedule a timeout.\n\n\n requestHostTimeout(handleTimeout, startTime - currentTime);\n }\n } else {\n newTask.sortIndex = expirationTime;\n push(taskQueue, newTask);\n // wait until the next time we yield.\n\n\n if (!isHostCallbackScheduled && !isPerformingWork) {\n isHostCallbackScheduled = true;\n requestHostCallback(flushWork);\n }\n }\n\n return newTask;\n}\n\nfunction unstable_pauseExecution() {\n}\n\nfunction unstable_continueExecution() {\n\n if (!isHostCallbackScheduled && !isPerformingWork) {\n isHostCallbackScheduled = true;\n requestHostCallback(flushWork);\n }\n}\n\nfunction unstable_getFirstCallbackNode() {\n return peek(taskQueue);\n}\n\nfunction unstable_cancelCallback(task) {\n // remove from the queue because you can't remove arbitrary nodes from an\n // array based heap, only the first one.)\n\n\n task.callback = null;\n}\n\nfunction unstable_getCurrentPriorityLevel() {\n return currentPriorityLevel;\n}\n\nvar isMessageLoopRunning = false;\nvar scheduledHostCallback = null;\nvar taskTimeoutID = -1; // Scheduler periodically yields in case there is other work on the main\n// thread, like user events. By default, it yields multiple times per frame.\n// It does not attempt to align with frame boundaries, since most tasks don't\n// need to be frame aligned; for those that do, use requestAnimationFrame.\n\nvar frameInterval = frameYieldMs;\nvar startTime = -1;\n\nfunction shouldYieldToHost() {\n var timeElapsed = exports.unstable_now() - startTime;\n\n if (timeElapsed < frameInterval) {\n // The main thread has only been blocked for a really short amount of time;\n // smaller than a single frame. Don't yield yet.\n return false;\n } // The main thread has been blocked for a non-negligible amount of time. We\n\n\n return true;\n}\n\nfunction requestPaint() {\n\n}\n\nfunction forceFrameRate(fps) {\n if (fps < 0 || fps > 125) {\n // Using console['error'] to evade Babel and ESLint\n console['error']('forceFrameRate takes a positive int between 0 and 125, ' + 'forcing frame rates higher than 125 fps is not supported');\n return;\n }\n\n if (fps > 0) {\n frameInterval = Math.floor(1000 / fps);\n } else {\n // reset the framerate\n frameInterval = frameYieldMs;\n }\n}\n\nvar performWorkUntilDeadline = function () {\n if (scheduledHostCallback !== null) {\n var currentTime = exports.unstable_now(); // Keep track of the start time so we can measure how long the main thread\n // has been blocked.\n\n startTime = currentTime;\n var hasTimeRemaining = true; // If a scheduler task throws, exit the current browser task so the\n // error can be observed.\n //\n // Intentionally not using a try-catch, since that makes some debugging\n // techniques harder. Instead, if `scheduledHostCallback` errors, then\n // `hasMoreWork` will remain true, and we'll continue the work loop.\n\n var hasMoreWork = true;\n\n try {\n hasMoreWork = scheduledHostCallback(hasTimeRemaining, currentTime);\n } finally {\n if (hasMoreWork) {\n // If there's more work, schedule the next message event at the end\n // of the preceding one.\n schedulePerformWorkUntilDeadline();\n } else {\n isMessageLoopRunning = false;\n scheduledHostCallback = null;\n }\n }\n } else {\n isMessageLoopRunning = false;\n } // Yielding to the browser will give it a chance to paint, so we can\n};\n\nvar schedulePerformWorkUntilDeadline;\n\nif (typeof localSetImmediate === 'function') {\n // Node.js and old IE.\n // There's a few reasons for why we prefer setImmediate.\n //\n // Unlike MessageChannel, it doesn't prevent a Node.js process from exiting.\n // (Even though this is a DOM fork of the Scheduler, you could get here\n // with a mix of Node.js 15+, which has a MessageChannel, and jsdom.)\n // https://github.com/facebook/react/issues/20756\n //\n // But also, it runs earlier which is the semantic we want.\n // If other browsers ever implement it, it's better to use it.\n // Although both of these would be inferior to native scheduling.\n schedulePerformWorkUntilDeadline = function () {\n localSetImmediate(performWorkUntilDeadline);\n };\n} else if (typeof MessageChannel !== 'undefined') {\n // DOM and Worker environments.\n // We prefer MessageChannel because of the 4ms setTimeout clamping.\n var channel = new MessageChannel();\n var port = channel.port2;\n channel.port1.onmessage = performWorkUntilDeadline;\n\n schedulePerformWorkUntilDeadline = function () {\n port.postMessage(null);\n };\n} else {\n // We should only fallback here in non-browser environments.\n schedulePerformWorkUntilDeadline = function () {\n localSetTimeout(performWorkUntilDeadline, 0);\n };\n}\n\nfunction requestHostCallback(callback) {\n scheduledHostCallback = callback;\n\n if (!isMessageLoopRunning) {\n isMessageLoopRunning = true;\n schedulePerformWorkUntilDeadline();\n }\n}\n\nfunction requestHostTimeout(callback, ms) {\n taskTimeoutID = localSetTimeout(function () {\n callback(exports.unstable_now());\n }, ms);\n}\n\nfunction cancelHostTimeout() {\n localClearTimeout(taskTimeoutID);\n taskTimeoutID = -1;\n}\n\nvar unstable_requestPaint = requestPaint;\nvar unstable_Profiling = null;\n\nexports.unstable_IdlePriority = IdlePriority;\nexports.unstable_ImmediatePriority = ImmediatePriority;\nexports.unstable_LowPriority = LowPriority;\nexports.unstable_NormalPriority = NormalPriority;\nexports.unstable_Profiling = unstable_Profiling;\nexports.unstable_UserBlockingPriority = UserBlockingPriority;\nexports.unstable_cancelCallback = unstable_cancelCallback;\nexports.unstable_continueExecution = unstable_continueExecution;\nexports.unstable_forceFrameRate = forceFrameRate;\nexports.unstable_getCurrentPriorityLevel = unstable_getCurrentPriorityLevel;\nexports.unstable_getFirstCallbackNode = unstable_getFirstCallbackNode;\nexports.unstable_next = unstable_next;\nexports.unstable_pauseExecution = unstable_pauseExecution;\nexports.unstable_requestPaint = unstable_requestPaint;\nexports.unstable_runWithPriority = unstable_runWithPriority;\nexports.unstable_scheduleCallback = unstable_scheduleCallback;\nexports.unstable_shouldYield = shouldYieldToHost;\nexports.unstable_wrapCallback = unstable_wrapCallback;\n /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\nif (\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop ===\n 'function'\n) {\n __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error());\n}\n \n })();\n}\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/scheduler.production.min.js');\n} else {\n module.exports = require('./cjs/scheduler.development.js');\n}\n","//\n\nmodule.exports = function shallowEqual(objA, objB, compare, compareContext) {\n var ret = compare ? compare.call(compareContext, objA, objB) : void 0;\n\n if (ret !== void 0) {\n return !!ret;\n }\n\n if (objA === objB) {\n return true;\n }\n\n if (typeof objA !== \"object\" || !objA || typeof objB !== \"object\" || !objB) {\n return false;\n }\n\n var keysA = Object.keys(objA);\n var keysB = Object.keys(objB);\n\n if (keysA.length !== keysB.length) {\n return false;\n }\n\n var bHasOwnProperty = Object.prototype.hasOwnProperty.bind(objB);\n\n // Test for A's keys different from B.\n for (var idx = 0; idx < keysA.length; idx++) {\n var key = keysA[idx];\n\n if (!bHasOwnProperty(key)) {\n return false;\n }\n\n var valueA = objA[key];\n var valueB = objB[key];\n\n ret = compare ? compare.call(compareContext, valueA, valueB, key) : void 0;\n\n if (ret === false || (ret === void 0 && valueA !== valueB)) {\n return false;\n }\n }\n\n return true;\n};\n","\nmodule.exports = function () {\n var selection = document.getSelection();\n if (!selection.rangeCount) {\n return function () {};\n }\n var active = document.activeElement;\n\n var ranges = [];\n for (var i = 0; i < selection.rangeCount; i++) {\n ranges.push(selection.getRangeAt(i));\n }\n\n switch (active.tagName.toUpperCase()) { // .toUpperCase handles XHTML\n case 'INPUT':\n case 'TEXTAREA':\n active.blur();\n break;\n\n default:\n active = null;\n break;\n }\n\n selection.removeAllRanges();\n return function () {\n selection.type === 'Caret' &&\n selection.removeAllRanges();\n\n if (!selection.rangeCount) {\n ranges.forEach(function(range) {\n selection.addRange(range);\n });\n }\n\n active &&\n active.focus();\n };\n};\n","export default {\"title\":\"Module tools\",\"description\":\"\",\"icon\":\"\",\"themeConfig\":{\"footer\":{\"message\":\"Copyright © 2022 ByteDance.\"},\"socialLinks\":[{\"icon\":\"github\",\"mode\":\"link\",\"content\":\"https://github.com/modern-js-dev/modern.js/tree/main/packages/solutions/module-tools\"}],\"locales\":[{\"lang\":\"zh\",\"label\":\"简体中文\",\"nav\":[{\"text\":\"指南\",\"link\":\"/guide/intro/welcome\",\"activeMatch\":\"^/guide/\"},{\"text\":\"API\",\"link\":\"/api/\",\"activeMatch\":\"^/api/\"},{\"text\":\"插件\",\"link\":\"/plugins/guide/getting-started\",\"activeMatch\":\"^/plugins/\"},{\"text\":\"v2.0.2\",\"items\":[{\"text\":\"更新日志\",\"link\":\"https://github.com/modern-js-dev/modern.js/tree/main/packages/solutions/module-tools/CHANGELOG.md\"},{\"text\":\"贡献指南\",\"link\":\"https://github.com/modern-js-dev/modern.js/tree/main/packages/solutions/module-tools/CHANGELOG.md\"}]}],\"title\":\"Module tools\",\"outlineTitle\":\"目录\",\"prevPageText\":\"上一页\",\"nextPageText\":\"下一页\",\"description\":\"模块工程解决方案\",\"sidebar\":{\"/api/\":[{\"text\":\"概览\",\"link\":\"/api/\"},{\"text\":\"配置项\",\"collapsed\":false,\"collapsible\":true,\"items\":[{\"text\":\"BuildConfig\",\"link\":\"/api/config/build-config\"},{\"text\":\"BuildPreset\",\"link\":\"/api/config/build-preset\"},{\"text\":\"DesignSystem\",\"link\":\"/api/config/design-system\"},{\"text\":\"Plugins\",\"link\":\"/api/config/plugins\"},{\"text\":\"Testing\",\"link\":\"/api/config/testing\"}]},{\"text\":\"Plugin API\",\"collapsed\":false,\"collapsible\":true,\"items\":[{\"text\":\"Plugin Hooks\",\"link\":\"/api/plugin-api/plugin-hooks\"}]}],\"/guide/\":[{\"text\":\"介绍\",\"collapsed\":false,\"collapsible\":true,\"items\":[{\"text\":\"欢迎使用\",\"link\":\"/guide/intro/welcome\"},{\"text\":\"为什么需要模块工程解决方案\",\"link\":\"/guide/intro/why-module-engineering-solution\"},{\"text\":\"快速开始\",\"link\":\"/guide/intro/getting-started\"}]},{\"text\":\"基础使用\",\"collapsed\":false,\"collapsible\":true,\"items\":[{\"text\":\"开始之前\",\"link\":\"/guide/basic/before-getting-started\"},{\"text\":\"命令预览\",\"link\":\"/guide/basic/command-preview\"},{\"text\":\"修改输出产物\",\"link\":\"/guide/basic/modify-output-product\"},{\"text\":\"使用微生成器\",\"link\":\"/guide/basic/use-micro-generator\"},{\"text\":\"使用 Storybook\",\"link\":\"/guide/basic/using-storybook\"},{\"text\":\"测试项目\",\"link\":\"/guide/basic/test-your-project\"},{\"text\":\"版本管理与发布\",\"link\":\"/guide/basic/publish-your-project\"}]},{\"text\":\"进阶指南\",\"collapsed\":false,\"collapsible\":true,\"items\":[{\"text\":\"深入理解构建\",\"link\":\"/guide/advance/in-depth-about-build\"},{\"text\":\"深入理解 dev 命令\",\"link\":\"/guide/advance/in-depth-about-dev-command\"},{\"text\":\"使用 Copy 工具\",\"link\":\"/guide/advance/copy\"},{\"text\":\"如何处理第三方依赖\",\"link\":\"/guide/advance/external-dependency\"},{\"text\":\"构建 umd 产物\",\"link\":\"/guide/advance/build-umd\"},{\"text\":\"主题配置\",\"link\":\"/guide/advance/theme-config\"},{\"text\":\"处理静态资源文件\",\"link\":\"/guide/advance/asset\"}]},{\"text\":\"最佳实践\",\"collapsed\":false,\"collapsible\":true,\"items\":[{\"text\":\"开发组件\",\"link\":\"/guide/best-practices/components\"}]}],\"/plugins/\":[{\"text\":\"指南\",\"collapsed\":false,\"collapsible\":true,\"items\":[{\"text\":\"快速开始\",\"link\":\"/plugins/guide/getting-started\"},{\"text\":\"插件对象\",\"link\":\"/plugins/guide/plugin-object\"},{\"text\":\"Setup 函数\",\"link\":\"/plugins/guide/setup-function\"}]},{\"text\":\"插件列表\",\"collapsed\":false,\"collapsible\":true,\"items\":[{\"text\":\"总览\",\"link\":\"/plugins/official-list/overview\"}]}]}},{\"lang\":\"en\",\"label\":\"English\",\"nav\":[{\"text\":\"Guide\",\"link\":\"/en/guide/intro/welcome\",\"activeMatch\":\"^/guide/\"},{\"text\":\"API\",\"link\":\"/en/api/\",\"activeMatch\":\"^/api/\"},{\"text\":\"Plugins\",\"link\":\"/en/plugins/guide/getting-started\",\"activeMatch\":\"^/plugins/\"},{\"text\":\"v2.0.2\",\"items\":[{\"text\":\"Changelog\",\"link\":\"https://github.com/modern-js-dev/modern.js/tree/main/packages/solutions/module-tools/CHANGELOG.md\"},{\"text\":\"Contributing\",\"link\":\"https://github.com/modern-js-dev/modern.js/tree/main/packages/solutions/module-tools/CHANGELOG.md\"}]}],\"title\":\"Module tools\",\"description\":\"Module Engineering Solutions\",\"sidebar\":{\"/en/api/\":[{\"text\":\"Config\",\"collapsed\":false,\"collapsible\":true,\"items\":[{\"text\":\"BuildConfig\",\"link\":\"/en/api/config/build-config\"},{\"text\":\"BuildPreset\",\"link\":\"/en/api/config/build-preset\"},{\"text\":\"DesignSystem\",\"link\":\"/en/api/config/design-system\"},{\"text\":\"Plugins\",\"link\":\"/en/api/config/plugins\"},{\"text\":\"Testing\",\"link\":\"/en/api/config/testing\"}]},{\"text\":\"Plugin API\",\"collapsed\":false,\"collapsible\":true,\"items\":[{\"text\":\"Plugin Hooks\",\"link\":\"/en/api/plugin-api/plugin-hooks\"}]},{\"text\":\"Overview\",\"link\":\"/en/api/\"}],\"/en/guide/\":[{\"text\":\"Introduction\",\"collapsed\":false,\"collapsible\":true,\"items\":[{\"text\":\"Welcome to Module Tools\",\"link\":\"/en/guide/intro/welcome\"},{\"text\":\"Why module project solution\",\"link\":\"/en/guide/intro/why-module-engineering-solution\"},{\"text\":\"Quick start\",\"link\":\"/en/guide/intro/getting-started\"}]},{\"text\":\"Basic Guide\",\"collapsed\":false,\"collapsible\":true,\"items\":[{\"text\":\"Before you start\",\"link\":\"/en/guide/basic/before-getting-started\"},{\"text\":\"Command Preview\",\"link\":\"/en/guide/basic/command-preview\"},{\"text\":\"modify-output-product\",\"link\":\"/en/guide/basic/modify-output-product\"},{\"text\":\"Using the Microgenerator\",\"link\":\"/en/guide/basic/use-micro-generator\"},{\"text\":\"Using Storybook\",\"link\":\"/en/guide/basic/using-storybook\"},{\"text\":\"Testing Projects\",\"link\":\"/en/guide/basic/test-your-project\"},{\"text\":\"Versioning and Publishing\",\"link\":\"/en/guide/basic/publish-your-project\"}]},{\"text\":\"Advanced Guide\",\"collapsed\":false,\"collapsible\":true,\"items\":[{\"text\":\"In-depth understanding of build\",\"link\":\"/en/guide/advance/in-depth-about-build\"},{\"text\":\"深入理解 dev 命令\",\"link\":\"/en/guide/advance/in-depth-about-dev-command\"},{\"text\":\"Use the Copy Tools\",\"link\":\"/en/guide/advance/copy\"},{\"text\":\"How to handle third-party dependencies\",\"link\":\"/en/guide/advance/external-dependency\"},{\"text\":\"Build umd products\",\"link\":\"/en/guide/advance/build-umd\"},{\"text\":\"Handle static resource files\",\"link\":\"/en/guide/advance/asset\"},{\"text\":\"Theme Configuration\",\"link\":\"/en/guide/advance/theme-config\"}]},{\"text\":\"Best practices\",\"collapsed\":false,\"collapsible\":true,\"items\":[{\"text\":\"Developing Components\",\"link\":\"/en/guide/best-practices/components\"}]}],\"/en/plugins/\":[{\"text\":\"Guide\",\"collapsed\":false,\"collapsible\":true,\"items\":[{\"text\":\"Quick Start\",\"link\":\"/en/plugins/guide/getting-started\"},{\"text\":\"Plugin Object\",\"link\":\"/en/plugins/guide/plugin-object\"},{\"text\":\"Setup function\",\"link\":\"/en/plugins/guide/setup-function\"}]},{\"text\":\"Plugins List\",\"collapsed\":false,\"collapsible\":true,\"items\":[{\"text\":\"Overview\",\"link\":\"/en/plugins/official-list/overview\"}]}]}}]},\"base\":\"/\",\"root\":\"/Users/bytedance/modern.js/website/module-tools/docs\",\"lang\":\"zh\",\"logo\":\"\",\"pages\":[{\"title\":\"BuildConfig\",\"routePath\":\"/en/api/config/build-config\",\"toc\":[{\"id\":\"alias\",\"text\":\"alias\",\"depth\":2},{\"id\":\"asset\",\"text\":\"asset\",\"depth\":2},{\"id\":\"path\",\"text\":\"path\",\"depth\":3},{\"id\":\"limit\",\"text\":\"limit\",\"depth\":3},{\"id\":\"publicpath\",\"text\":\"publicPath\",\"depth\":3},{\"id\":\"svgr\",\"text\":\"svgr\",\"depth\":3},{\"id\":\"include\",\"text\":\"include\",\"depth\":4},{\"id\":\"exclude\",\"text\":\"exclude\",\"depth\":4},{\"id\":\"autoexternal\",\"text\":\"autoExternal\",\"depth\":2},{\"id\":\"dependencies\",\"text\":\"dependencies\",\"depth\":3},{\"id\":\"peerdependencies\",\"text\":\"peerDependencies\",\"depth\":3},{\"id\":\"buildtype\",\"text\":\"buildType\",\"depth\":2},{\"id\":\"copy\",\"text\":\"copy\",\"depth\":2},{\"id\":\"define\",\"text\":\"define\",\"depth\":2},{\"id\":\"dts\",\"text\":\"dts\",\"depth\":2},{\"id\":\"tsconfigpath\",\"text\":\"tsconfigPath\",\"depth\":3},{\"id\":\"distpath\",\"text\":\"distPath\",\"depth\":3},{\"id\":\"only\",\"text\":\"only\",\"depth\":3},{\"id\":\"externals\",\"text\":\"externals\",\"depth\":2},{\"id\":\"format\",\"text\":\"format\",\"depth\":2},{\"id\":\"input\",\"text\":\"input\",\"depth\":2},{\"id\":\"jsx\",\"text\":\"jsx\",\"depth\":2},{\"id\":\"minify\",\"text\":\"minify\",\"depth\":2},{\"id\":\"outdir\",\"text\":\"outDir\",\"depth\":2},{\"id\":\"platform\",\"text\":\"platform\",\"depth\":2},{\"id\":\"sourcedir\",\"text\":\"sourceDir\",\"depth\":2},{\"id\":\"sourcemap\",\"text\":\"sourceMap\",\"depth\":2},{\"id\":\"splitting\",\"text\":\"splitting\",\"depth\":2},{\"id\":\"style\",\"text\":\"style\",\"depth\":2},{\"id\":\"less\",\"text\":\"less\",\"depth\":3},{\"id\":\"lessoptions\",\"text\":\"lessOptions\",\"depth\":4},{\"id\":\"additionaldata\",\"text\":\"additionalData\",\"depth\":4},{\"id\":\"implementation\",\"text\":\"implementation\",\"depth\":4},{\"id\":\"sass\",\"text\":\"sass\",\"depth\":3},{\"id\":\"sassoptions\",\"text\":\"sassOptions\",\"depth\":4},{\"id\":\"additionaldata-1\",\"text\":\"additionalData\",\"depth\":4},{\"id\":\"implementation-1\",\"text\":\"implementation\",\"depth\":4},{\"id\":\"postcss\",\"text\":\"postcss\",\"depth\":3},{\"id\":\"inject\",\"text\":\"inject\",\"depth\":3},{\"id\":\"automodules\",\"text\":\"autoModules\",\"depth\":3},{\"id\":\"modules\",\"text\":\"modules\",\"depth\":3},{\"id\":\"tailwindcss\",\"text\":\"tailwindcss\",\"depth\":3},{\"id\":\"target\",\"text\":\"target\",\"depth\":2},{\"id\":\"umdglobals\",\"text\":\"umdGlobals\",\"depth\":2},{\"id\":\"umdmodulename\",\"text\":\"umdModuleName\",\"depth\":2}],\"content\":\"BUILDCONFIG\\n\\nThis section describes all the configuration of Module tools for building\\n\\n\\nALIAS\\n\\n * type: Record<string, string | string[]> | Function\\n * default: {'@': 'src',}\\n\\nFor TypeScript projects, you only need to configure compilerOptions.paths in\\ntsconfig.json, Module tools will automatically recognize the alias in\\ntsconfig.json, so there is no need to configure the alias field additionally.\\n\\nexport default {\\n buildConfig: {\\n alias: {\\n '@common': '. /src/common',\\n },\\n },\\n};\\n\\n\\nAfter the above configuration is done, if @common/Foo.tsx is referenced in the\\ncode, it will map to the <root>/src/common/Foo.tsx path.\\n\\nWhen the value of alias is defined as a function, you can accept the pre-defined\\nalias object and modify it.\\n\\nexport default {\\n buildConfig: {\\n alias: alias => {\\n alias['@common'] = '. /src/common';\\n },\\n },\\n};\\n\\n\\nIt is also possible to return a new object as the final result in the function,\\nwhich will override the pre-defined alias object.\\n\\nexport default {\\n buildConfig: {\\n alias: alias => {\\n return {\\n '@common': '. /src/common',\\n };\\n },\\n },\\n};\\n\\n\\n\\nASSET\\n\\n\\nPATH\\n\\nStatic resource output path, will be based on outDir\\n\\n * type: string\\n * default: assets\\n\\n\\nLIMIT\\n\\nThreshold for automatically inlining static resources when building, resources\\nless than 10 KB will be automatically inlined into the bundle product\\n\\n * type: number\\n * default: 10 * 1024\\n\\n\\nPUBLICPATH\\n\\nThe CDN prefix given to unlinked resources when packaging\\n\\n * type: string\\n * default: undefined\\n\\nexport default {\\n buildConfig: {\\n asset: {\\n publicPath: 'https://xxx/',\\n },\\n },\\n};\\n\\n\\nAt this point, all static resources will be prefixed with https://xxx/\\n\\n\\nSVGR\\n\\nPackaged to handle svg as a React component, options reference svgr, plus\\nsupport for two configuration items include and exclude to match the svg file to\\nbe handled\\n\\n * type: boolean | Object\\n * default: false\\n\\nINCLUDE\\n\\nSet the matching svg file\\n\\n * type: string | RegExp | (string | RegExp)[]\\n * default: /\\\\.svg$/\\n\\nEXCLUDE\\n\\nSet unmatched svg files\\n\\n * type: string | RegExp | (string | RegExp)[]\\n * default: undefined\\n\\n\\nAUTOEXTERNAL\\n\\nAutomatically externalize project dependencies and peerDependencies and not\\npackage them into the final bundle\\n\\n * type: boolean | Object\\n * default: true\\n\\n\\nDEPENDENCIES\\n\\nWhether or not the dep dependencies of the external project are needed\\n\\n * type: boolean\\n * default: true\\n\\n\\nPEERDEPENDENCIES\\n\\nWhether to require peerDep dependencies for external projects\\n\\n * type: boolean\\n * default: true\\n\\n\\nBUILDTYPE\\n\\nThe build type, bundle will package your code, bundleless will only do the code\\nconversion\\n\\n * type: 'bundle' | 'bundleless'\\n * default: bundle\\n\\n\\nCOPY\\n\\nCopies the specified file or directory into the build output directory\\n\\n * type: Array\\n * default: []\\n\\nexport default {\\n buildConfig: {\\n copy: [{ from: '. /src/assets', to: '' }],\\n },\\n};\\n\\n\\nReference for array settings: copy-webpack-plugin patterns\\n\\n\\nDEFINE\\n\\nDefine global variables that will be injected into the code\\n\\n * type: Record<string, string>\\n * default: {}\\n\\nSince the define function is implemented by global text replacement, you need to\\nensure that the global variable values are strings. A safer approach is to\\nconvert the value of each global variable to a string, using JSON.stringify, as\\nfollows.\\n\\nexport default {\\n buildConfig: {\\n define: {\\n VERSION: JSON.stringify('1.0'),\\n },\\n },\\n};\\n\\n\\nTo prevent excessive global replacement substitution, it is recommended that the\\nfollowing two principles be followed when using\\n\\n * Use upper case for global constants\\n * Customize the prefix and suffix of global constants to ensure uniqueness\\n\\n\\nDTS\\n\\nThe dts file generates the relevant configuration, by default it generates\\n\\n * type: false | Object\\n * default: {}\\n\\n\\nTSCONFIGPATH\\n\\nPath to the tsconfig file\\n\\n * type: string\\n * default: . /tsconfig.json\\n\\n\\nDISTPATH\\n\\nThe output path of the dts file, based on outDir\\n\\n * type: string\\n * default: . /types\\n\\n\\nONLY\\n\\nGenerate only dts files, not js files\\n\\n * type: boolean\\n * default: false\\n\\n\\nEXTERNALS\\n\\nConfigure external dependencies that will not be packaged into the final bundle\\n\\n * type: (string | RegExp)[]\\n * default: []\\n\\n\\nFORMAT\\n\\nThe format of the js product output, where iife and umd can only take effect\\nwhen buildType is bundle\\n\\n * type: 'esm' | 'cjs' | 'iife' | 'umd'\\n * default: cjs\\n\\n\\nINPUT\\n\\nSpecify the entry file for the build, in the form of an array that can specify\\nthe directory\\n\\n * type: string[] | Record<string, string>\\n * default: ['src/index.ts'] in bundle mode, ['src'] in bundleless mode\\n\\nexport default {\\n buildConfig: {\\n input: ['src/index.ts', 'src/index2.ts'],\\n },\\n};\\n\\n\\n\\nJSX\\n\\nSpecify the compilation method of jsx, default support React17, automatically\\ninject jsx runtime code\\n\\n * type: automatic | classic\\n * default: automatic\\n\\n\\nMINIFY\\n\\nUse esbuild or terser to compress code, also pass terserOptions\\n\\n * type: 'terser' | 'esbuild' | false | Object\\n * default: false\\n\\nexport default {\\n buildConfig: {\\n minify: {\\n compress: {\\n drop_console: true,\\n },\\n },\\n },\\n};\\n\\n\\n\\nOUTDIR\\n\\nSpecifies the output directory of the build\\n\\n * type: string\\n * default: dist\\n\\n\\nPLATFORM\\n\\nGenerates code for the node environment by default, you can also specify browser\\nwhich will generate code for the browser environment\\n\\n * type: 'browser' | 'node'\\n * default: node\\n\\n\\nSOURCEDIR\\n\\nSpecify the source directory of the build, default is src, which is used to\\ngenerate the corresponding product directory based on the source directory\\nstructure when building bundleless.\\n\\n * type: string\\n * default: src\\n\\n\\nSOURCEMAP\\n\\nWhether to generate sourceMap or not\\n\\n * type: boolean | 'inline' | 'external'\\n * default: false\\n\\n\\nSPLITTING\\n\\nWhether to enable code splitting\\n\\n * type: boolean\\n * default: false\\n\\n\\nSTYLE\\n\\nConfigure style-related configuration\\n\\n\\nLESS\\n\\nless-related configuration\\n\\nLESSOPTIONS\\n\\nRefer to less for detailed configuration\\n\\n * type: Object\\n * default: { javascriptEnabled: true }\\n\\nADDITIONALDATA\\n\\nAdd Less code to the beginning of the entry file.\\n\\n * type: string\\n * default: undefined\\n\\nexport default {\\n buildConfig: {\\n style: {\\n less: {\\n additionalData: `@base-color: #c6538c;`,\\n },\\n },\\n },\\n};\\n\\n\\nIMPLEMENTATION\\n\\nConfigure the implementation library used by Less, if not specified, the\\nbuilt-in version used is 4.1.3\\n\\n * type: string | Object\\n * default: undefined\\n\\nSpecify the implementation library for Less when the Object type is specified\\n\\nexport default {\\n buildConfig: {\\n style: {\\n less: {\\n implementation: require('less'),\\n },\\n },\\n },\\n};\\n\\n\\nFor the string type, specify the path to the implementation library for Less\\n\\nexport default {\\n buildConfig: {\\n style: {\\n less: {\\n implementation: require.resolve('less'),\\n },\\n },\\n },\\n};\\n\\n\\n\\nSASS\\n\\nsass-related configuration\\n\\nSASSOPTIONS\\n\\nRefer to node-sass for detailed configuration\\n\\n * type: Object\\n * default: {}\\n\\nADDITIONALDATA\\n\\nAdd Sass code to the beginning of the entry file.\\n\\n * type: string | Function\\n * default: undefined\\n\\nexport default {\\n buildConfig: {\\n style: {\\n sass: {\\n additionalData: `$base-color: #c6538c;\\n $border-dark: rgba($base-color, 0.88);`,\\n },\\n },\\n },\\n};\\n\\n\\nIMPLEMENTATION\\n\\nConfigure the implementation library used by Sass, the built-in version used is\\n1.5.4 if not specified\\n\\n * type: string | Object\\n * default: undefined\\n\\nSpecify the implementation library for Sass when the Object type is specified\\n\\nexport default {\\n buildConfig: {\\n style: {\\n sass: {\\n implementation: require('sass'),\\n },\\n },\\n },\\n};\\n\\n\\nFor the string type, specify the path to the Sass implementation library\\n\\nexport default {\\n buildConfig: {\\n style: {\\n sass: {\\n implementation: require.resolve('sass'),\\n },\\n },\\n },\\n};\\n\\n\\n\\nPOSTCSS\\n\\n * plugins\\n * processOptions\\n\\nSee postcss for detailed configuration\\n\\n\\nINJECT\\n\\nConfigure whether to insert style into js in packaged mode\\n\\n * type: boolean\\n * default: false\\n\\n\\nAUTOMODULES\\n\\nEnable CSS Modules automatically based on the filename.\\n\\n * type: boolean | RegExp\\n * default: true\\n\\ntrue : Enables CSS Modules for style files ending with .module.css .module.less\\n.module.scss .module.sass filenames\\n\\nfalse : Disable CSS Modules.\\n\\nRegExp : Enables CSS Modules for all files that match the regular condition.\\n\\n\\nMODULES\\n\\nCSS Modules configuration\\n\\n * type: Object\\n * default: {}\\n\\nA common configuration is localsConvention, which changes the class name\\ngeneration rules for css modules\\n\\nexport default {\\n buildConfig: {\\n style: {\\n modules: {\\n localsConvention: 'camelCaseOnly',\\n },\\n },\\n },\\n};\\n\\n\\nFor the following styles\\n\\n.box-title {\\n color: red;\\n}\\n\\n\\nYou can use styles.boxTitle to access\\n\\nFor detailed configuration see postcss-modules\\n\\n\\nTAILWINDCSS\\n\\ntailwindcss related configuration\\n\\n * type: Object | Function\\n * default: see configuration details below\\n\\nconst tailwind = {\\n content: [\\n './config/html/**/*.html',\\n './config/html/**/*.ejs',\\n './config/html/**/*.hbs',\\n './src/**/*.js',\\n './src/**/*.jsx',\\n './src/**/*.ts',\\n './src/**/*.tsx',\\n './storybook/**/*',\\n ],\\n};\\n\\n\\nWhen the value is of type Object, it is merged with the default configuration\\nvia Object.assign.\\n\\nWhen the value is of type Function, the object returned by the function is\\nmerged with the default configuration via Object.assign.\\n\\nThe theme property is not allowed, otherwise the build will fail, using\\ndesignSystem as the Tailwind CSS Theme configuration.\\n\\nThe rest of the usage is the same as Tailwind CSS: Quick Portal.\\n\\n\\nTARGET\\n\\nSpecify the target environment for the build\\n\\n * type: 'es5' | 'es6' | 'es2015' | 'es2016' | 'es2017' | 'es2018' | 'es2019' |\\n 'es2020' | 'es2021' | 'es2022' | 'esnext'\\n * default: 'es2015'\\n\\n\\nUMDGLOBALS\\n\\nSpecify global variables for external import of umd products\\n\\n * type: Record<string, string>\\n * default: {}\\n\\nexport default {\\n buildConfig: {\\n umdGlobals: {\\n react: 'React',\\n 'react-dom': 'ReactDOM',\\n },\\n },\\n};\\n\\n\\nAt this point, react and react-dom will be seen as global variables imported\\nexternally and will not be packed into the umd product, but will be accessible\\nby way of global.React and global.ReactDOM\\n\\n\\nUMDMODULENAME\\n\\nSpecifies the module name of the umd product\\n\\n * type: string | Function\\n * default: name => name\\n\\nexport default {\\n buildConfig: {\\n format: 'umd',\\n umdModuleName: 'myLib',\\n },\\n};\\n\\n\\nAt this point the umd product will go to mount on global.myLib\\n\\n * The module name of the umd product must not conflict with the global variable\\n name.\\n * Module names should not contain special characters like -, @, /, etc.\\n\\nAlso the function form can take one parameter, which is the output path of the\\ncurrent package file\\n\\nexport default {\\n buildConfig: {\\n format: 'umd',\\n umdModuleName: path => {\\n if (path.includes('index')) {\\n return 'myLib';\\n } else {\\n return 'myLib2';\\n }\\n },\\n },\\n};\\n\",\"frontmatter\":{\"sidebar_position\":1}},{\"title\":\"BuildPreset\",\"routePath\":\"/en/api/config/build-preset\",\"toc\":[{\"id\":\"string\",\"text\":\"string\",\"depth\":2},{\"id\":\"npm-library\",\"text\":\"``npm-library'`\",\"depth\":3},{\"id\":\"npm-library-with-umd\",\"text\":\"npm-library-with-umd'\",\"depth\":3},{\"id\":\"npm-component\",\"text\":\"'npm-component'\",\"depth\":3},{\"id\":\"npm-component-with-umd\",\"text\":\"'npm-component-with-umd'\",\"depth\":3},{\"id\":\"about-the-ecmascript-versions-supported-by-the-presets-and-es5-esnext\",\"text\":\"About the ECMAScript versions supported by the presets and {es5.... .esnext}\",\"depth\":3},{\"id\":\"function\",\"text\":\"Function\",\"depth\":2}],\"content\":\"BUILDPRESET\\n\\nA build preset string or preset function. Provides out-of-the-box build\\nconfiguration\\n\\n * type: string | Function\\n * default: undefined\\n\\n\\nSTRING\\n\\nThe string form allows you to use the built-in presets directly\\n\\n\\n\\nexport default defineConfig({\\n buildPreset: 'npm-library',\\n});\\n\\n\\n\\n``NPM-LIBRARY'`\\n\\nLibrary generic schema used under class NPM package manager, contains esm and\\ncjs Bundle products, and includes a type file.\\n\\nAbout the class NPM Package Manager\\n\\n * npm\\n * yarn\\n * pnpm\\n\\n{\\n \\\"main\\\": \\\". /dist/lib/index.js\\\",\\n \\\"module\\\": \\\". /dist/es/index.js\\\",\\n \\\"types\\\": \\\". /dist/types/index.d.ts\\\"\\n}\\n\\n\\nThe build configuration corresponding to the preset string.\\n\\nexport const buildConfig = [\\n {\\n format: 'cjs',\\n target: 'es6',\\n buildType: 'bundle',\\n outDir: '. /lib',\\n },\\n {\\n format: 'esm',\\n target: 'es6',\\n buildType: 'bundle',\\n outDir: '. /es',\\n },\\n {\\n buildType: 'bundle',\\n outDir: '. /types',\\n dts: {\\n only: true,\\n },\\n },\\n];\\n\\n\\n\\nNPM-LIBRARY-WITH-UMD'\\n\\nUsed under class NPM package manager, and Library supports a similar pattern to\\nunpkg. Additional umd products are provided on top of the pre-defined\\nnpm-library.\\n\\n{\\n \\\"main\\\": \\\". /dist/lib/index.js\\\",\\n \\\"module\\\": \\\". /dist/es/index.js\\\",\\n \\\"types\\\": \\\". /dist/types/index.d.ts\\\",\\n \\\"unpkg\\\": \\\". /dist/umd/index.js\\\",\\n};\\n\\n\\nThe build configuration corresponding to the preset string.\\n\\nexport const buildConfig = [\\n {\\n format: 'cjs',\\n target: 'es6',\\n buildType: 'bundle',\\n outDir: '. /lib',\\n },\\n {\\n format: 'esm',\\n target: 'es6',\\n buildType: 'bundle',\\n outDir: '. /es',\\n },\\n {\\n format: 'umd',\\n target: 'es6',\\n buildType: 'bundle',\\n outDir: '. /umd',\\n },\\n {\\n buildType: 'bundle',\\n outDir: '. /types',\\n dts: {\\n only: true,\\n },\\n },\\n];\\n\\n\\n\\n'NPM-COMPONENT'\\n\\nA generic pattern for components (libraries) used under the class NPM package\\nmanager. Contains both esm and cjs Bundleless products (for easy Tree shaking\\noptimization), as well as including a copy of the type file.\\n\\nFor style files included in the source code, the products provide the compiled\\nproduct of the style and the source file of the style.\\n\\n{\\n \\\"main\\\": \\\". /dist/lib/index.js\\\", // bundleless type\\n \\\"module\\\": \\\". /dist/es/index.js\\\", // bundleless type\\n \\\"types\\\": \\\". /dist/types/index.d.ts\\\",\\n};\\n\\n\\nThe pre-defined strings correspond to the build configuration.\\n\\nexport const buildConfig = [\\n {\\n format: 'cjs',\\n target: 'es6',\\n buildType: 'bundleless',\\n outDir: '. /lib',\\n },\\n {\\n format: 'esm',\\n target: 'es6',\\n buildType: 'bundleless',\\n outDir: '. /es',\\n },\\n {\\n buildType: 'bundleless',\\n outDir: '. /types',\\n dts: {\\n only: true,\\n },\\n },\\n];\\n\\n\\n\\n'NPM-COMPONENT-WITH-UMD'\\n\\nComponent (library) used under class NPM package manager, with support for class\\nunpkg schema. Additional umd products are provided on top of the pre-defined\\nnpm-component.\\n\\n{\\n \\\"main\\\": \\\". /dist/lib/index.js\\\", // bundleless type\\n \\\"module\\\": \\\". /dist/es/index.js\\\", // bundleless type\\n \\\"types\\\": \\\". /dist/types/index.d.ts\\\",\\n \\\"unpkg\\\": \\\". /dist/umd/index.js\\\",\\n};\\n\\n\\nexport const buildConfig = [\\n {\\n format: 'cjs',\\n target: 'es6',\\n buildType: 'bundleless',\\n outDir: '. /lib',\\n },\\n {\\n format: 'esm',\\n target: 'es6',\\n buildType: 'bundleless',\\n outDir: '. /es',\\n },\\n {\\n format: 'umd',\\n target: 'es6',\\n buildType: 'bundle',\\n outDir: '. /umd',\\n },\\n {\\n buildType: 'bundleless',\\n outDir: '. /types',\\n dts: {\\n only: true,\\n },\\n },\\n];\\n\\n\\n\\nABOUT THE ECMASCRIPT VERSIONS SUPPORTED BY THE PRESETS AND {ES5.... .ESNEXT}\\n\\nWhen you want to use a buildPreset preset that supports other ECMAScript\\nversions, you can directly add the supported versions to the 'npm-library',\\n'npm-library-with-umd', 'npm-component', 'npm-component-with-umd' presets.\\n\\nFor example, if you want the npm-library'` preset to support es2017``, you can\\nconfigure it as follows.\\n\\n\\n\\nexport default defineConfig({\\n buildPreset: 'npm-library-es2017',\\n});\\n\\n\\n\\nFUNCTION\\n\\nThe way the function is configured, you can get the preset value from the preset\\nparameter and then modify the build configuration inside to customize your build\\nconfiguration. The following is an example of how a function can be configured\\nto compress a build product.\\n\\n\\n\\nexport default defineConfig({\\n buildPreset({ preset }) {\\n const { NPM_LIBRARY } = preset;\\n return NPM_LIBRARY.map(config => {\\n config.minify = {\\n compress: {\\n drop_console: true,\\n },\\n };\\n return config;\\n });\\n },\\n});\\n\",\"frontmatter\":{\"sidebar_position\":2}},{\"title\":\"DesignSystem\",\"routePath\":\"/en/api/config/design-system\",\"toc\":[{\"id\":\"max-width-breakpoints\",\"text\":\"Max-width breakpoints\",\"depth\":3},{\"id\":\"multiple-range-breakpoints\",\"text\":\"Multiple range breakpoints\",\"depth\":3},{\"id\":\"custom-media-queries\",\"text\":\"Custom media queries\",\"depth\":3},{\"id\":\"print-styles\",\"text\":\"Print styles\",\"depth\":3},{\"id\":\"dark-mode\",\"text\":\"Dark Mode\",\"depth\":3},{\"id\":\"colors\",\"text\":\"Colors\",\"depth\":2},{\"id\":\"spacing\",\"text\":\"Spacing\",\"depth\":2},{\"id\":\"core-plugins\",\"text\":\"Core plugins\",\"depth\":2},{\"id\":\"customizing-the-default-configuration\",\"text\":\"Customizing the default configuration\",\"depth\":2},{\"id\":\"override-the-default-configuration\",\"text\":\"Override the default configuration\",\"depth\":3},{\"id\":\"extending-the-default-configuration\",\"text\":\"Extending the default configuration\",\"depth\":3},{\"id\":\"referencing-other-values\",\"text\":\"Referencing other values\",\"depth\":3},{\"id\":\"disabling-the-entire-core-plugin\",\"text\":\"Disabling the entire core plugin\",\"depth\":3},{\"id\":\"adding-your-own-key\",\"text\":\"Adding your own key\",\"depth\":3},{\"id\":\"configuration-references\",\"text\":\"Configuration references\",\"depth\":2}],\"content\":\"DESIGNSYSTEM\\n\\nThis chapter describes the configuration related to designSystem\\n\\nThe Tailwind CSS feature needs to be enabled first via pnpm run new.\\n\\n * type: Object\\n * default: see configuration details below.\\n\\n black: '#000',\\n white: '#fff',\\n\\n gray: {\\n 100: '#f7fafc',\\n 200: '#edf2f7',\\n 300: '#e2e8f0',\\n 400: '#cbd5e0',\\n 500: '#a0aec0',\\n 600: '#718096',\\n 700: '#4a5568',\\n 800: '#2d3748',\\n 900: '#1a202c',\\n },\\n red: {\\n 100: '#fff5f5',\\n 200: '#fed7d7',\\n 300: '#feb2b2',\\n 400: '#fc8181',\\n 500: '#f56565',\\n 600: '#e53e3e',\\n 700: '#c53030',\\n 800: '#9b2c2c',\\n 900: '#742a2a',\\n },\\n orange: {\\n 100: '#fffaf0',\\n 200: '#feebc8',\\n 300: '#fbd38d',\\n 400: '#f6ad55',\\n 500: '#ed8936',\\n 600: '#dd6b20',\\n 700: '#c05621',\\n 800: '#9c4221',\\n 900: '#7b341e',\\n },\\n yellow: {\\n 100: '#fffff0',\\n 200: '#fefcbf',\\n 300: '#faf089',\\n 400: '#f6e05e',\\n 500: '#ecc94b',\\n 600: '#d69e2e',\\n 700: '#b7791f',\\n 800: '#975a16',\\n 900: '#744210',\\n },\\n green: {\\n 100: '#f0fff4',\\n 200: '#c6f6d5',\\n 300: '#9ae6b4',\\n 400: '#68d391',\\n 500: '#48bb78',\\n 600: '#38a169',\\n 700: '#2f855a',\\n 800: '#276749',\\n 900: '#22543d',\\n },\\n teal: {\\n 100: '#e6fffa',\\n 200: '#b2f5ea',\\n 300: '#81e6d9',\\n 400: '#4fd1c5',\\n 500: '#38b2ac',\\n 600: '#319795',\\n 700: '#2c7a7b',\\n 800: '#285e61',\\n 900: '#234e52',\\n },\\n blue: {\\n 100: '#ebf8ff',\\n 200: '#bee3f8',\\n 300: '#90cdf4',\\n 400: '#63b3ed',\\n 500: '#4299e1',\\n 600: '#3182ce',\\n 700: '#2b6cb0',\\n 800: '#2c5282',\\n 900: '#2a4365',\\n },\\n indigo: {\\n 100: '#ebf4ff',\\n 200: '#c3dafe',\\n 300: '#a3bffa',\\n 400: '#7f9cf5',\\n 500: '#667eea',\\n 600: '#5a67d8',\\n 700: '#4c51bf',\\n 800: '#434190',\\n 900: '#3c366b',\\n },\\n purple: {\\n 100: '#faf5ff',\\n 200: '#e9d8fd',\\n 300: '#d6bcfa',\\n 400: '#b794f4',\\n 500: '#9f7aea',\\n 600: '#805ad5',\\n 700: '#6b46c1',\\n 800: '#553c9a',\\n 900: '#44337a',\\n },\\n pink: {\\n 100: '#fff5f7',\\n 200: '#fed7e2',\\n 300: '#fbb6ce',\\n 400: '#f687b3',\\n 500: '#ed64a6',\\n 600: '#d53f8c',\\n 700: '#b83280',\\n 800: '#97266d',\\n 900: '#702459',\\n },\\n},\\nspacing: {\\n px: '1px',\\n '0': '0',\\n '1': '0.25rem',\\n '2': '0.5rem',\\n '3': '0.75rem',\\n '4': '1rem',\\n '5': '1.25rem',\\n '6': '1.5rem',\\n '8': '2rem',\\n '10': '2.5rem',\\n '12': '3rem',\\n '16': '4rem',\\n '20': '5rem',\\n '24': '6rem',\\n '32': '8rem',\\n '40': '10rem',\\n '48': '12rem',\\n '56': '14rem',\\n '64': '16rem',\\n},\\nbackgroundColor: theme => theme('colors'),\\nbackgroundOpacity: theme => theme('opacity'),\\nbackgroundPosition: {\\n bottom: 'bottom',\\n center: 'center',\\n left: 'left',\\n 'left-bottom': 'left bottom',\\n 'left-top': 'left top',\\n right: 'right',\\n 'right-bottom': 'right bottom',\\n 'right-top': 'right top',\\n top: 'top',\\n},\\nbackgroundSize: {\\n auto: 'auto',\\n cover: 'cover',\\n contain: 'contain',\\n},\\nborderColor: theme => ({\\n ...theme('colors'),\\n default: theme('colors.gray.300', 'currentColor'),\\n}),\\nborderOpacity: theme => theme('opacity'),\\nborderRadius: {\\n none: '0',\\n sm: '0.125rem',\\n default: '0.25rem',\\n md: '0.375rem',\\n lg: '0.5rem',\\n full: '9999px',\\n},\\nborderWidth: {\\n default: '1px',\\n '0': '0',\\n '2': '2px',\\n '4': '4px',\\n '8': '8px',\\n},\\nboxShadow: {\\n xs: '0 0 0 1px rgba(0, 0, 0, 0.05)',\\n sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',\\n default: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',\\n md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',\\n lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',\\n xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',\\n '2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',\\n inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',\\n outline: '0 0 0 3px rgba(66, 153, 225, 0.5)',\\n none: 'none',\\n},\\ncontainer: {},\\ncursor: {\\n auto: 'auto',\\n default: 'default',\\n pointer: 'pointer',\\n wait: 'wait',\\n text: 'text',\\n move: 'move',\\n 'not-allowed': 'not-allowed',\\n},\\ndivideColor: theme => theme('borderColor'),\\ndivideOpacity: theme => theme('borderOpacity'),\\ndivideWidth: theme => theme('borderWidth'),\\nfill: {\\n current: 'currentColor',\\n},\\nflex: {\\n '1': '1 1 0%',\\n auto: '1 1 auto',\\n initial: '0 1 auto',\\n none: 'none',\\n},\\nflexGrow: {\\n '0': '0',\\n default: '1',\\n},\\nflexShrink: {\\n '0': '0',\\n default: '1',\\n},\\nfontFamily: {\\n sans: [\\n 'system-ui',\\n '-apple-system',\\n 'BlinkMacSystemFont',\\n '\\\"Segoe UI\\\"',\\n 'Roboto',\\n '\\\"Helvetica Neue\\\"',\\n 'Arial',\\n '\\\"Noto Sans\\\"',\\n 'sans-serif',\\n '\\\"Apple Color Emoji\\\"',\\n '\\\"Segoe UI Emoji\\\"',\\n '\\\"Segoe UI Symbol\\\"',\\n '\\\"Noto Color Emoji\\\"',\\n ],\\n serif: ['Georgia', 'Cambria', '\\\"Times New Roman\\\"', 'Times', 'serif'],\\n mono: ['Menlo', 'Monaco', 'Consolas', '\\\"Liberation Mono\\\"', '\\\"Courier New\\\"', 'monospace'],\\n},\\nfontSize: {\\n xs: '0.75rem',\\n sm: '0.875rem',\\n base: '1rem',\\n lg: '1.125rem',\\n xl: '1.25rem',\\n '2xl': '1.5rem',\\n '3xl': '1.875rem',\\n '4xl': '2.25rem',\\n '5xl': '3rem',\\n '6xl': '4rem',\\n},\\nfontWeight: {\\n hairline: '100',\\n thin: '200',\\n light: '300',\\n normal: '400',\\n medium: '500',\\n semibold: '600',\\n bold: '700',\\n extrabold: '800',\\n black: '900',\\n},\\nheight: theme => ({\\n auto: 'auto',\\n ...theme('spacing'),\\n full: '100%',\\n screen: '100vh',\\n}),\\ninset: {\\n '0': '0',\\n auto: 'auto',\\n},\\nletterSpacing: {\\n tighter: '-0.05em',\\n tight: '-0.025em',\\n normal: '0',\\n wide: '0.025em',\\n wider: '0.05em',\\n widest: '0.1em',\\n},\\nlineHeight: {\\n none: '1',\\n tight: '1.25',\\n snug: '1.375',\\n normal: '1.5',\\n relaxed: '1.625',\\n loose: '2',\\n '3': '.75rem',\\n '4': '1rem',\\n '5': '1.25rem',\\n '6': '1.5rem',\\n '7': '1.75rem',\\n '8': '2rem',\\n '9': '2.25rem',\\n '10': '2.5rem',\\n},\\nlistStyleType: {\\n none: 'none',\\n disc: 'disc',\\n decimal: 'decimal',\\n},\\nmargin: (theme, { negative }) => ({\\n auto: 'auto',\\n ...theme('spacing'),\\n ...negative(theme('spacing')),\\n}),\\nmaxHeight: {\\n full: '100%',\\n screen: '100vh',\\n},\\nmaxWidth: (theme, { breakpoints }) => ({\\n none: 'none',\\n xs: '20rem',\\n sm: '24rem',\\n md: '28rem',\\n lg: '32rem',\\n xl: '36rem',\\n '2xl': '42rem',\\n '3xl': '48rem',\\n '4xl': '56rem',\\n '5xl': '64rem',\\n '6xl': '72rem',\\n full: '100%',\\n ...breakpoints(theme('screens')),\\n}),\\nminHeight: {\\n '0': '0',\\n full: '100%',\\n screen: '100vh',\\n},\\nminWidth: {\\n '0': '0',\\n full: '100%',\\n},\\nobjectPosition: {\\n bottom: 'bottom',\\n center: 'center',\\n left: 'left',\\n 'left-bottom': 'left bottom',\\n 'left-top': 'left top',\\n right: 'right',\\n 'right-bottom': 'right bottom',\\n 'right-top': 'right top',\\n top: 'top',\\n},\\nopacity: {\\n '0': '0',\\n '25': '0.25',\\n '50': '0.5',\\n '75': '0.75',\\n '100': '1',\\n},\\norder: {\\n first: '-9999',\\n last: '9999',\\n none: '0',\\n '1': '1',\\n '2': '2',\\n '3': '3',\\n '4': '4',\\n '5': '5',\\n '6': '6',\\n '7': '7',\\n '8': '8',\\n '9': '9',\\n '10': '10',\\n '11': '11',\\n '12': '12',\\n},\\npadding: theme => theme('spacing'),\\nplaceholderColor: theme => theme('colors'),\\nplaceholderOpacity: theme => theme('opacity'),\\nspace: (theme, { negative }) => ({\\n ...theme('spacing'),\\n ...negative(theme('spacing')),\\n}),\\nstroke: {\\n current: 'currentColor',\\n},\\nstrokeWidth: {\\n '0': '0',\\n '1': '1',\\n '2': '2',\\n},\\ntextColor: theme => theme('colors'),\\ntextOpacity: theme => theme('opacity'),\\nwidth: theme => ({\\n auto: 'auto',\\n ...theme('spacing'),\\n '1/2': '50%',\\n '1/3': '33.333333%',\\n '2/3': '66.666667%',\\n '1/4': '25%',\\n '2/4': '50%',\\n '3/4': '75%',\\n '1/5': '20%',\\n '2/5': '40%',\\n '3/5': '60%',\\n '4/5': '80%',\\n '1/6': '16.666667%',\\n '2/6': '33.333333%',\\n '3/6': '50%',\\n '4/6': '66.666667%',\\n '5/6': '83.333333%',\\n '1/12': '8.333333%',\\n '2/12': '16.666667%',\\n '3/12': '25%',\\n '4/12': '33.333333%',\\n '5/12': '41.666667%',\\n '6/12': '50%',\\n '7/12': '58.333333%',\\n '8/12': '66.666667%',\\n '9/12': '75%',\\n '10/12': '83.333333%',\\n '11/12': '91.666667%',\\n full: '100%',\\n screen: '100vw',\\n}),\\nzIndex: {\\n auto: 'auto',\\n '0': '0',\\n '10': '10',\\n '20': '20',\\n '30': '30',\\n '40': '40',\\n '50': '50',\\n},\\ngap: theme => theme('spacing'),\\ngridTemplateColumns: {\\n none: 'none',\\n '1': 'repeat(1, minmax(0, 1fr))',\\n '2': 'repeat(2, minmax(0, 1fr))',\\n '3': 'repeat(3, minmax(0, 1fr))',\\n '4': 'repeat(4, minmax(0, 1fr))',\\n '5': 'repeat(5, minmax(0, 1fr))',\\n '6': 'repeat(6, minmax(0, 1fr))',\\n '7': 'repeat(7, minmax(0, 1fr))',\\n '8': 'repeat(8, minmax(0, 1fr))',\\n '9': 'repeat(9, minmax(0, 1fr))',\\n '10': 'repeat(10, minmax(0, 1fr))',\\n '11': 'repeat(11, minmax(0, 1fr))',\\n '12': 'repeat(12, minmax(0, 1fr))',\\n},\\ngridColumn: {\\n auto: 'auto',\\n 'span-1': 'span 1 / span 1',\\n 'span-2': 'span 2 / span 2',\\n 'span-3': 'span 3 / span 3',\\n 'span-4': 'span 4 / span 4',\\n 'span-5': 'span 5 / span 5',\\n 'span-6': 'span 6 / span 6',\\n 'span-7': 'span 7 / span 7',\\n 'span-8': 'span 8 / span 8',\\n 'span-9': 'span 9 / span 9',\\n 'span-10': 'span 10 / span 10',\\n 'span-11': 'span 11 / span 11',\\n 'span-12': 'span 12 / span 12',\\n},\\ngridColumnStart: {\\n auto: 'auto',\\n '1': '1',\\n '2': '2',\\n '3': '3',\\n '4': '4',\\n '5': '5',\\n '6': '6',\\n '7': '7',\\n '8': '8',\\n '9': '9',\\n '10': '10',\\n '11': '11',\\n '12': '12',\\n '13': '13',\\n},\\ngridColumnEnd: {\\n auto: 'auto',\\n '1': '1',\\n '2': '2',\\n '3': '3',\\n '4': '4',\\n '5': '5',\\n '6': '6',\\n '7': '7',\\n '8': '8',\\n '9': '9',\\n '10': '10',\\n '11': '11',\\n '12': '12',\\n '13': '13',\\n},\\ngridTemplateRows: {\\n none: 'none',\\n '1': 'repeat(1, minmax(0, 1fr))',\\n '2': 'repeat(2, minmax(0, 1fr))',\\n '3': 'repeat(3, minmax(0, 1fr))',\\n '4': 'repeat(4, minmax(0, 1fr))',\\n '5': 'repeat(5, minmax(0, 1fr))',\\n '6': 'repeat(6, minmax(0, 1fr))',\\n},\\ngridRow: {\\n auto: 'auto',\\n 'span-1': 'span 1 / span 1',\\n 'span-2': 'span 2 / span 2',\\n 'span-3': 'span 3 / span 3',\\n 'span-4': 'span 4 / span 4',\\n 'span-5': 'span 5 / span 5',\\n 'span-6': 'span 6 / span 6',\\n},\\ngridRowStart: {\\n auto: 'auto',\\n '1': '1',\\n '2': '2',\\n '3': '3',\\n '4': '4',\\n '5': '5',\\n '6': '6',\\n '7': '7',\\n},\\ngridRowEnd: {\\n auto: 'auto',\\n '1': '1',\\n '2': '2',\\n '3': '3',\\n '4': '4',\\n '5': '5',\\n '6': '6',\\n '7': '7',\\n},\\ntransformOrigin: {\\n center: 'center',\\n top: 'top',\\n 'top-right': 'top right',\\n right: 'right',\\n 'bottom-right': 'bottom right',\\n bottom: 'bottom',\\n 'bottom-left': 'bottom left',\\n left: 'left',\\n 'top-left': 'top left',\\n},\\nscale: {\\n '0': '0',\\n '50': '.5',\\n '75': '.75',\\n '90': '.9',\\n '95': '.95',\\n '100': '1',\\n '105': '1.05',\\n '110': '1.1',\\n '125': '1.25',\\n '150': '1.5',\\n},\\nrotate: {\\n '-180': '-180deg',\\n '-90': '-90deg',\\n '-45': '-45deg',\\n '0': '0',\\n '45': '45deg',\\n '90': '90deg',\\n '180': '180deg',\\n},\\ntranslate: (theme, { negative }) => ({\\n ...theme('spacing'),\\n ...negative(theme('spacing')),\\n '-full': '-100%',\\n '-1/2': '-50%',\\n '1/2': '50%',\\n full: '100%',\\n}),\\nskew: {\\n '-12': '-12deg',\\n '-6': '-6deg',\\n '-3': '-3deg',\\n '0': '0',\\n '3': '3deg',\\n '6': '6deg',\\n '12': '12deg',\\n},\\ntransitionProperty: {\\n none: 'none',\\n all: 'all',\\n default: 'background-color, border-color, color, fill, stroke, opacity, box-shadow, transform',\\n colors: 'background-color, border-color, color, fill, stroke',\\n opacity: 'opacity',\\n shadow: 'box-shadow',\\n transform: 'transform',\\n},\\ntransitionTimingFunction: {\\n linear: 'linear',\\n in: 'cubic-bezier(0.4, 0, 1, 1)',\\n out: 'cubic-bezier(0, 0, 0.2, 1)',\\n 'in-out': 'cubic-bezier(0.4, 0, 0.2, 1)',\\n},\\ntransitionDuration: {\\n '75': '75ms',\\n '100': '100ms',\\n '150': '150ms',\\n '200': '200ms',\\n '300': '300ms',\\n '500': '500ms',\\n '700': '700ms',\\n '1000': '1000ms',\\n},\\ntransitionDelay: {\\n '75': '75ms',\\n '100': '100ms',\\n '150': '150ms',\\n '200': '200ms',\\n '300': '300ms',\\n '500': '500ms',\\n '700': '700ms',\\n '1000': '1000ms',\\n},\\n\\n\\n};\\n\\n:::tips\\nMore about [TailwindCSS configuration](https://tailwindcss.com/docs/configuration#theme)\\n:::\\n</details>\\n\\n\\nThe `designSystem` is used to define the project's color palette, typographic scales (Typographic Scales or Type Scale), font list, breakpoints, border rounding values, etc. Since Modern.js borrows the design approach from Tailwind Theme and integrates with Tailwind CSS internally, `designSystem` is used in the same way as Tailwind CSS Theme\\n\\nThe `designSystem` object contains the `screens`, `colors` and `spacing` properties, as well as each customizable core plugin.\\n\\n## Screens\\n\\nThe responsive breakpoints in your project can be customized using `screens`: the\\n\\n```js\\nconst designSystem = {\\n screens: {\\n sm: '640px',\\n md: '768px',\\n lg: '1024px',\\n xl: '1280px',\\n },\\n};\\n\\n\\nwhere the property name in the screens object is the screen name (used as a\\nprefix for the adaptive utility variants generated by Tailwind CSS, e.g.\\nmd:text-center) and the value is the min-width at which the breakpoint should\\nstart.\\n\\nDefault breakpoints are inspired by common device resolutions: the\\n\\nconst designSystem = {\\n screens: {\\n sm: '640px',\\n // => @media (min-width: 640px) { ... }\\n\\n md: '768px',\\n // => @media (min-width: 768px) { ... }\\n\\n lg: '1024px',\\n // => @media (min-width: 1024px) { ... }\\n\\n xl: '1280px',\\n // => @media (min-width: 1280px) { ... }\\n },\\n};\\n\\n\\nYou can use any name you like as a breakpoint property in your project: the\\n\\nconst designSystem = {\\n screens: {\\n tablet: '640px',\\n // => @media (min-width: 640px) { ... }\\n\\n laptop: '1024px',\\n // => @media (min-width: 1024px) { ... }\\n\\n desktop: '1280px',\\n // => @media (min-width: 1280px) { ... }\\n },\\n};\\n\\n\\nThese screen names are reflected in utilities, so text-center now looks like\\nthis\\n\\n.text-center {\\n text-align: center;\\n}\\n\\n@media (min-width: 640px) {\\n .tablet\\\\:text-center {\\n text-align: center;\\n }\\n}\\n\\n@media (min-width: 1024px) {\\n .laptop\\\\:text-center {\\n text-align: center;\\n }\\n}\\n\\n@media (min-width: 1280px) {\\n .desktop\\\\:text-center {\\n text-align: center;\\n }\\n}\\n\\n\\n\\nMAX-WIDTH BREAKPOINTS\\n\\nTo use the max-width breakpoint instead of min-width, you can specify the screen\\nas an object with the max attribute.\\n\\nconst designSystem = {\\n screens: {\\n xl: { max: '1279px' }\\n // => @media (max-width: 1279px) { ... }\\n\\n lg: { max: '1023px' },\\n // => @media (max-width: 1023px) { ... }\\n\\n md: { max: '767px' },\\n // => @media (max-width: 767px) { ... }\\n\\n sm: { max: '639px' },\\n // => @media (max-width: 639px) { ... }\\n },\\n};\\n\\n\\nIf necessary, to create breakpoints with min-width and max-width definitions,\\ne.g.\\n\\nconst designSystem = {\\n screens: {\\n sm: { min: '640px', max: '767px' }\\n md: { min: '768px', max: '1023px' }\\n lg: { min: '1024px', max: '1279px' }, lg: { min: '1024px', max: '1279px' },\\n xl: { min: '1280px' }\\n },\\n};\\n\\n\\n\\nMULTIPLE RANGE BREAKPOINTS\\n\\nSometimes it can be useful to apply a single breakpoint definition to multiple\\nscopes.\\n\\nFor example, suppose you have a sidebar and want the breakpoint to be based on\\nthe width of the content area rather than the entire viewport. You can simulate\\nthis situation by using a smaller breakpoint style when the sidebar is visible\\nand the content area is narrowed: the\\n\\nconst designSystem = {\\n screens: {\\n sm: '500px',\\n md: [\\n // Sidebar appears at 768px, so revert to `sm:` styles between 768px\\n // and 868px, after which the main content area is wide enough again to\\n // apply the `md:` styles.\\n { min: '668px', max: '767px' }\\n { min: '868px' }, { min: '868px' },\\n ],\\n lg: '1100px',\\n xl: '1400px',\\n },\\n};\\n\\n\\n\\nCUSTOM MEDIA QUERIES\\n\\nIf a fully customizable media query is required for a breakpoint, an object with\\nthe raw attribute can be used.\\n\\nconst designSystem = {\\n extend: {\\n screens: {\\n portrait: { raw: '(orientation: portrait)' },\\n // => @media (orientation: portrait) { ... }\\n },\\n },\\n};\\n\\n\\n\\nPRINT STYLES\\n\\nThe raw option may be particularly useful if you need to apply different styles\\nto printing.\\n\\nAll that needs to be done is to add a print under designSystem.extend.screens.\\n\\n``js const designSystem = { extend: { screens: { print: { raw: 'print' }, // =>\\n@media print { ... } }, }, };\\n\\n\\nThen, a class such as ``print:text-black`` can be used to specify a style that is applied only when someone tries to print a page: ``\\n\\n```html\\n<div class=\\\"text-gray-700 print:text-black\\\">\\n <! -- ... -->\\n</div>\\n\\n\\n\\nDARK MODE\\n\\nraw 选项可以用于实现 “暗模式” 屏幕:\\n\\nconst designSystem = {\\n extend: {\\n screens: {\\n dark: { raw: '(prefers-color-scheme: dark)' },\\n // => @media (prefers-color-scheme: dark) { ... }\\n },\\n },\\n};\\n\\n\\n然后,您可以使用 dark: 前缀在暗模式下为元素设置不同的样式:\\n\\n<div class=\\\"text-gray-700 dark:text-gray-200\\\">\\n <! -- ... -->\\n</div>\\n\\n\\n请注意,由于这些 screen variants 是在 Tailwind CSS 中实现的,因此无法使用这种方法将断点与暗模式结合使用 ,例如\\nmd:dark:text-gray-300 将不起作用。\\n\\n\\nCOLORS\\n\\ncolors 属性可让您自定义项目的全局调色板。\\n\\nconst designSystem = {\\n colors: {\\n transparent: 'transparent',\\n black: '#000',\\n white: '#fff',\\n gray: {\\n 100: '#f7fafc',\\n // ...\\n 900: '#1a202c',\\n },\\n\\n // ...\\n },\\n};\\n\\n\\nBy default, these colors are inherited by the backgroundColor, textColor and\\nborderColor core plugins.\\n\\nTo learn more, you can check out: Customizing Colors.\\n\\n\\nSPACING\\n\\nThe global spacing and scaling of items can be customized using the space\\nattribute: the\\n\\nconst designSystem = {\\n spacing: {\\n px: '1px',\\n 0: '0',\\n 1: '0.25rem',\\n 2: '0.5rem',\\n 3: '0.75rem',\\n 4: '1rem',\\n 5: '1.25rem',\\n 6: '1.5rem',\\n 8: '2rem',\\n 10: '2.5rem',\\n 12: '3rem',\\n 16: '4rem',\\n 20: '5rem',\\n 24: '6rem',\\n 32: '8rem',\\n 40: '10rem',\\n 48: '12rem',\\n 56: '14rem',\\n 64: '16rem',\\n },\\n};\\n\\n\\nBy default, these values are inherited by the padding, margin, negativeMargin,\\nwidth and height core plugins.\\n\\nTo learn more, see Customizing Spacing.\\n\\n\\nCORE PLUGINS\\n\\nThe rest of the theme section is used to configure the values available for each\\ncore plugin.\\n\\nFor example, the borderRadius property allows you to customize the ``utilities`\\nthat will generate the rounded corners.\\n\\n``js const designSystem = { borderRadius: { none: '0', sm: '.125rem', default:\\n'.25rem', lg: '.5rem', full: '9999px', }, };\\n\\n\\n** The attribute name determines the suffix of the generated class, and the value determines the value of the actual CSS declaration. **\\nThe example ``borderRadius`` configuration above will generate the following CSS classes.\\n\\n```css\\n.rounded-none { border-radius: 0 }\\n.rounded-sm { border-radius: .125rem }\\n.rounded { border-radius: .25rem }\\n.rounded-lg { border-radius: .5rem }\\n.rounded-full { border-radius: 9999px }\\n\\n\\nYou will notice that the rounded class is created without the suffix in the\\ntheme configuration using the default attribute. This is a common convention in\\nTailwind CSS supported by many (though not all) of the core plugins.\\n\\nTo learn more about customizing a specific core plugin, please visit the\\ndocumentation for that plugin.\\n\\n\\nCUSTOMIZING THE DEFAULT CONFIGURATION\\n\\nOut of the box, your project will automatically inherit values from the default\\ntheme configuration. If you want to customize the default theme, there are\\nseveral different options depending on the goal.\\n\\n\\nOVERRIDE THE DEFAULT CONFIGURATION\\n\\nTo override the options in the default configuration, add the properties to be\\noverridden to designSystem at\\n\\n\\n\\nconst designSystem = {\\n // Replaces all of the default `opacity` values\\n opacity: {\\n 0: '0',\\n 20: '0.2',\\n 40: '0.4',\\n 60: '0.6',\\n 80: '0.8',\\n 100: '1',\\n },\\n};\\n\\nexport default defineConfig({\\n designSystem,\\n});\\n\\n\\nThis will completely replace the default property configuration, so in the above\\nexample, the default opacity utilities will not be generated.\\n\\nAny properties you do not provide will be inherited from the default theme, so\\nin the example above, the default theme configuration for color, spacing, border\\nrounding, background position, etc. will be retained.\\n\\n\\nEXTENDING THE DEFAULT CONFIGURATION\\n\\nIf you want to keep the default values of the theme options but add new values,\\nadd the extensions under the designSystem.extend property.\\n\\nFor example, if you want to add an additional breakpoint but keep the existing\\none, you can extend the screens property with.\\n\\n\\n\\nconst designSystem = {\\n extend: {\\n // Adds a new breakpoint in addition to the default breakpoints\\n screens: {\\n '2xl': '1440px',\\n },\\n },\\n};\\n\\nexport default defineConfig({\\n designSystem,\\n});\\n\\n\\nYou can certainly override some parts of the default theme and extend other\\nparts of the default theme in the same configuration: the\\n\\n\\n\\nconst designSystem = {\\n opacity: {\\n 0: '0',\\n 20: '0.2',\\n 40: '0.4',\\n 60: '0.6',\\n 80: '0.8',\\n 100: '1',\\n },\\n extend: {\\n screens: {\\n '2xl': '1440px',\\n },\\n },\\n};\\n\\nexport default defineConfig({\\n designSystem,\\n});\\n\\n\\n\\nREFERENCING OTHER VALUES\\n\\nIf you need to reference another value in the configuration, you can do so by\\nproviding a closure function instead of a static value. The function will\\nreceive the theme() function as an argument, and you can use this function to\\nfind other values in the configuration using a dot representation.\\n\\nFor example, you can generate fill utilities for each color in the palette by\\nreferring to theme('colors') on the fill configuration.\\n\\n\\n\\nconst designSystem = {\\n colors: {\\n // ...\\n },\\n fill: theme => theme('colors'),\\n};\\n\\nexport default defineConfig({\\n designSystem,\\n});\\n\\n\\nThe theme() function tries to find the value you are looking for from an already\\nfully merged configuration object, so it can reference your own custom settings\\nas well as the default theme value. It also works recursively, so as long as\\nthere is a static value at the end of the chain, it can resolve the value you\\nare looking for.\\n\\nReference to the default configuration\\n\\nIf for any reason you want to reference a value in the default configuration,\\nyou can import it from tailwindcss/defaultTheme. A useful example would be to\\nadd one of the fonts provided by the default configuration to.\\n\\n\\n\\nconst defaultTheme = require('tailwindcss/defaultTheme');\\n\\nconst designSystem = {\\n extend: {\\n fontFamily: {\\n sans: ['Lato', ... .defaultTheme.fontFamily.sans],\\n },\\n },\\n};\\n\\nexport default defineConfig({\\n designSystem,\\n});\\n\\n\\n\\nDISABLING THE ENTIRE CORE PLUGIN\\n\\nIf you don't want to generate any classes for a core plugin, it's better to set\\nthe plugin to false in the corePlugins configuration, rather than providing an\\nempty object for the property in the configuration: ``\\n\\n// Don't assign an empty object in your theme configuration\\n\\nconst designSystem = {\\n opacity: {},\\n};\\n\\n// Do disable the plugin in your corePlugins configuration\\nconst designSyttem = {\\n corePlugins: {\\n opacity: { false,\\n },\\n};\\n\\n\\nThe end result is the same, but since many core plugins don't expose any\\nconfiguration, it's best to keep it consistent by only disabling them with\\ncorePlugins anyway.\\n\\n\\nADDING YOUR OWN KEY\\n\\nIn many cases it may be useful to add your own properties to the configuration\\nobject.\\n\\nOne example is to add new properties for multiplexing between multiple core\\nplugins. For example, you can extract a positions object that both the\\nbackgroundPosition and objectPosition plugins can refer to.\\n\\nconst designSystem = {\\n positions: {\\n bottom: 'bottom',\\n center: 'center',\\n left: 'left',\\n 'left-bottom': 'left bottom',\\n 'left-top': 'left top',\\n right: 'right',\\n 'right-bottom': 'right bottom',\\n 'right-top': 'right top',\\n top: 'top',\\n },\\n backgroundPosition: theme => theme('positions'),\\n objectPosition: theme => theme('positions'),\\n};\\n\\n\\nAnother example is to add a new property to a custom plugin for referencing. For\\nexample, if you write a gradient plugin for your project, you can add a gradient\\nproperty to the theme object referenced by that plugin.\\n\\n\\n\\nconst designSystem = {\\n gradients: theme => ({\\n 'blue-green': [theme('colors.blue.500'), theme('colors.green.500')],\\n 'purple-blue': [theme('colors.purple.500'), theme('colors.blue.500')],\\n // ...\\n }),\\n};\\n\\nexport default defineConfig({\\n designSystem,\\n buildConfig: {\\n style: {\\n postcss: {\\n plugins: [require('. /plugins/gradients')],\\n },\\n },\\n },\\n});\\n\\n\\n\\nCONFIGURATION REFERENCES\\n\\nAll properties in the configuration object, except screens, colors and spacing,\\nare mapped to the core plugins of Tailwind CSS. Since many plugins are\\nresponsible for CSS properties that accept only static sets of values (e.g.,\\ne.g., float), please note that not every plugin has a corresponding property in\\nthe theme object.\\n\\nAll of these properties can also be used under the designSystem.extend property\\nto extend the default theme.\\n\\nFor more information about what all the properties do, check out this link.\",\"frontmatter\":{\"sidebar_position\":3}},{\"title\":\"Plugins\",\"routePath\":\"/en/api/config/plugins\",\"toc\":[],\"content\":\"PLUGINS\\n\\nThis chapter describes the configuration of the registered module-tools plugin.\\n\\n * type: Array<ModuleToolsPlugin>\\n\\n\\nexport default defineConfig({\\n plugins: [ExamplePlugin()],\\n});\\n\\n\\nFor more information on how to write plugins, check out the [Plugin Writing\\nGuide].\",\"frontmatter\":{\"sidebar_position\":4}},{\"title\":\"Testing\",\"routePath\":\"/en/api/config/testing\",\"toc\":[{\"id\":\"jest\",\"text\":\"jest\",\"depth\":2},{\"id\":\"transformer\",\"text\":\"transformer\",\"depth\":2}],\"content\":\"TESTING\\n\\nThis chapter describes the test-related configuration\\n\\nYou need to enable the unit testing feature with pnpm run new first.\\n\\n\\nJEST\\n\\n * Type: Object | Function\\n * Default value: {}\\n\\nThe configuration corresponding to Jest, when of type Object, can be configured\\nwith all the underlying configurations supported by Jest .\\n\\n\\n\\nexport default defineConfig({\\n testing: {\\n jest: {\\n testTimeout: 10000,\\n },\\n },\\n});\\n\\n\\nWhen the value is of type Function, the default configuration is passed as the\\nfirst parameter and a new Jest configuration object needs to be returned.\\n\\n\\n\\nexport default defineConfig({\\n testing: {\\n jest: options => {\\n return {\\n ... . options,\\n testTimeout: 10000\\n }\\n }\\n }\\n});\\n\\n\\n\\nTRANSFORMER\\n\\n * type: 'babel-jest' | 'ts-jest'\\n * Default value: 'babel-jest'\\n\\nConfigure the compilation tool for the source code when executing tests:\\nbabel-jest or ts-jest. The default is babel-jest.\\n\\nbabel-jest can also compile TS files without type errors, so use ts-jest if you\\nneed to check the TS type when running tests.\",\"frontmatter\":{\"sidebar_position\":5}},{\"title\":\"Overview\",\"routePath\":\"/en/api/\",\"toc\":[],\"content\":\"OVERVIEW\",\"frontmatter\":{\"overview\":true,\"sidebar_label\":\"Overview\"}},{\"title\":\"Plugin Hooks\",\"routePath\":\"/en/api/plugin-api/plugin-hooks\",\"toc\":[{\"id\":\"build-hooks\",\"text\":\"build hooks\",\"depth\":2},{\"id\":\"beforebuild\",\"text\":\"beforeBuild\",\"depth\":3},{\"id\":\"beforebuildtask\",\"text\":\"beforeBuildTask\",\"depth\":3},{\"id\":\"afterbuildtask\",\"text\":\"afterBuildTask\",\"depth\":3},{\"id\":\"afterbuild\",\"text\":\"afterBuild\",\"depth\":3},{\"id\":\"buildplatform-hooks\",\"text\":\"buildPlatform hooks\",\"depth\":2},{\"id\":\"registerbuildplatform\",\"text\":\"registerBuildPlatform\",\"depth\":3},{\"id\":\"beforebuildplatform\",\"text\":\"beforeBuildPlatform\",\"depth\":3},{\"id\":\"buildplatform\",\"text\":\"buildPlatform\",\"depth\":3},{\"id\":\"afterbuildplatform\",\"text\":\"afterBuildPlatform\",\"depth\":3},{\"id\":\"dev-hooks\",\"text\":\"Dev Hooks\",\"depth\":2},{\"id\":\"registerdev\",\"text\":\"registerDev.\",\"depth\":3},{\"id\":\"beforedev\",\"text\":\"beforeDev\",\"depth\":3},{\"id\":\"beforeafterdevmenu\",\"text\":\"(before|after)DevMenu\",\"depth\":3},{\"id\":\"beforedevtask\",\"text\":\"beforeDevTask\",\"depth\":3},{\"id\":\"afterdev\",\"text\":\"afterDev\",\"depth\":3}],\"content\":\"PLUGIN HOOKS\\n\\nThis chapter describes the lifecycle hooks supported by module-tools.\\n\\nCurrently there are two main types of lifecycle hooks.\\n\\n * Build hooks: triggered only when the build command is executed to build the\\n source code product.\\n * buildPlatform hook: triggered only when the build --platform command is\\n executed to generate other build products.\\n * dev hooks: hooks that are triggered when running the dev command.\\n\\n\\nBUILD HOOKS\\n\\nThe following Hooks are triggered in order when the build command is executed.\\n\\n * beforeBuild\\n * beforeBuildTask\\n * afterBuildTask\\n * afterBuild\\n\\n\\nBEFOREBUILD\\n\\nTriggered before the execution of the overall build process.\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n beforeBuild(options: Options): Return {\\n return options.config;\\n }\\n }\\n },\\n});\\n\\n\\nParameters and return value types.\\n\\ntype Options = { options: { config: BuildConfig; cliOptions: BuildCommandOptions } }\\n\\nexport interface BuildCommandOptions {\\n config: string;\\n clear?: boolean;\\n dts?: boolean;\\n platform?: boolean | string[];\\n tsconfig: string;\\n watch?: boolean;\\n}\\n\\ntype Return = BuildConfig;\\n\\n\\n> BuildConfig type reference API configuration\\n\\n\\nBEFOREBUILDTASK\\n\\nBased on the build configuration, module tools will split the overall build into\\nmultiple sub-build tasks. The Hook will be triggered before each build subtask.\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n beforeBuildTask(config: BaseBuildConfig): BaseBuildConfig {\\n return config;\\n }\\n }\\n },\\n});\\n\\n\\nParameters and return value types.\\n\\nBaseBuildConfig type reference API configuration\\n\\n\\nAFTERBUILDTASK\\n\\nTriggered after the end of each build subtask.\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n afterBuildTask(options: BuildTaskResult): void {\\n // ...\\n }\\n }\\n },\\n});\\n\\n\\nParameters and return value types.\\n\\nexport interface BuildTaskResult {\\n status: 'success' | 'fail';\\n message?: string;\\n config: BaseBuildConfig;\\n}\\n\\n\\n\\nAFTERBUILD\\n\\nTriggered after the end of the overall build process.\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n afterBuild(options: BuildResult): void {\\n // ...\\n }\\n }\\n },\\n});\\n\\n\\nParameters and return value types.\\n\\nexport interface BuildResult {\\n status: 'success' | 'fail';\\n message?: string;\\n config: BuildConfig;\\n commandOptions: BuildCommandOptions;\\n totalDuration: number;\\n}\\n\\n\\n\\nBUILDPLATFORM HOOKS\\n\\nmodule-tools also provides the build --platform command to perform specific\\nbuild tasks.\\n\\nFor example, after installing the Storybook plugin, you can run build --platform\\nor build --platform storybook to perform Storybook build tasks. This is because\\nthe Storybook plugin is based on the buildPlatform Hooks.\\n\\nHooks are triggered in the following order after executing build --platform.\\n\\n * registerBuildPlatform\\n * beforeBuildPlatform\\n * buildPlatform\\n * afterBuildPlatform\\n\\n\\nREGISTERBUILDPLATFORM\\n\\nGets information about the tasks that need to be run when executing the build\\n--platform command.\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n registerBuildPlatform(): RegisterBuildPlatformResult {\\n // ...\\n return {\\n platform: 'stroybook',\\n build() {\\n // run storybook logic\\n },\\n }, };\\n },\\n };\\n },\\n});\\n\\n\\nTypes of parameters entered and returned.\\n\\nexport interface RegisterBuildPlatformResult {\\n platform: string | string[];\\n build: (\\n currentPlatform: string, // the currently running platform build task\\n context: { isTsProject: boolean },\\n ) => void | Promise<void>;\\n}\\n\\n\\n\\nBEFOREBUILDPLATFORM\\n\\nTriggers all registered build tasks when the build --platform command is\\nexecuted. beforeBuildPlatform will be triggered before the execution of the\\noverall build task.\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n beforeBuildPlatform(platforms: RegisterBuildPlatformResult[]): void {\\n console.info(`have ${platforms.length} platform tasks`);\\n },\\n };\\n },\\n});\\n\\n\\nTypes of parameters entered and returned.\\n\\nexport interface RegisterBuildPlatformResult {\\n platform: string | string[];\\n build: (\\n currentPlatform: string, // the currently running platform build task\\n context: { isTsProject: boolean },\\n ) => void | Promise<void>;\\n}\\n\\n\\n\\nBUILDPLATFORM\\n\\nWhen the build --platform command is executed, all registered build tasks will\\nbe triggered. buildPlatform will be triggered before each build task is\\nexecuted.\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n buildPlatform({ platform }: Options): void {\\n console.info(`current task is ${platform}`);\\n },\\n };\\n },\\n});\\n\\n\\nTypes of parameters entered and returned.\\n\\nexport interface Options {\\n platform: string;\\n}\\n\\n\\n\\nAFTERBUILDPLATFORM\\n\\nWhen the build --platform command is executed, all registered build tasks will\\nbe triggered. afterBuildPlatform will be triggered after the overall platform\\nbuild task is finished.\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n afterBuildPlatform(result: BuildPlatformResult): void {\\n if (result.status === 'success') {\\n console.info(`all platform build task success`);\\n } else {\\n console.error(result.message);\\n }\\n },\\n };\\n },\\n});\\n\\n\\nTypes of parameters entered and returned.\\n\\nexport interface BuildPlatformResult {\\n status: 'success' | 'fail';\\n message: string | Error | null;\\n}\\n\\n\\n\\nDEV HOOKS\\n\\nThe following Hooks are triggered in order when the dev command is executed.\\n\\n * registerDev: triggered when getting dev function information.\\n * beforeDev: Triggered before starting the dev process as a whole.\\n * beforeDevMenu: triggered before the dev list/menu appears.\\n * afterDevMenu: triggered after dev list/menu option is selected.\\n * beforeDevTask: Triggered before executing the dev task.\\n * afterDev: Triggered at the end of the overall dev process.\\n\\n\\nREGISTERDEV.\\n\\nRegister dev tool related data. Mainly contains.\\n\\n * the name of the dev tool\\n * The name of the item displayed in the menu list and the corresponding value.\\n * The definition of the dev subcommand.\\n * Whether to execute the source code build before running the dev task\\n * The function to execute the dev task.\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n registerDev() {\\n return {\\n // Dev tool name\\n name: 'storybook',\\n // Menu content\\n menuItem: {\\n name: 'Storybook',\\n value: 'storybook',\\n },\\n // Defined dev subcommands\\n subCommands: ['storybook', 'story'],\\n async action() {\\n // dev logic\\n },\\n };\\n },\\n };\\n },\\n});\\n\\n\\nTypes of parameters entered and returned.\\n\\nexport interface DevToolData {\\n name: string;\\n subCommands?: string[];\\n menuItem?: {\\n name: string;\\n value: string;\\n };\\n // Whether to disable the source build before the dev command is executed\\n disableRunBuild?: boolean;\\n action: (\\n options: { port?: string },\\n context: { isTsProject?: boolean },\\n ) => void | Promise<void>;\\n}\\n\\n\\nWhen dev a project, it may be possible to set disableRunBuild: true to disable\\nbuild tasks for source execution (in listening mode) if you only need to dev\\ncode functionality.\\n\\nThe currently supported Storybook dev supports using source code products as dev\\nobjects, so disableRunBuild: false in the Storybook plugin.\\n\\n\\nBEFOREDEV\\n\\nTriggered before the dev task is executed after all dev tool metadata has been\\ncollected.\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n beforeDev(metas: DevToolData[]) {\\n console.info(`have ${metas.length} dev tools`);\\n },\\n };\\n },\\n});\\n\\n\\nTypes of parameters entered and returned.\\n\\nexport interface DevToolData {\\n name: string;\\n subCommands?: string[];\\n menuItem?: {\\n name: string;\\n value: string;\\n };\\n // Whether to disable the source build before the dev command is executed\\n disableRunBuild?: boolean;\\n action: (\\n options: { port?: string },\\n context: { isTsProject?: boolean },\\n ) => void | Promise<void>;\\n}\\n\\n\\n\\n(BEFORE|AFTER)DEVMENU\\n\\nbeforeDevMenu is triggered before the dev list/menu appears. Receives inquirer\\nquestion as argument. Default value is.\\n\\nconst question = [\\n {\\n name: 'choiceDevTool',\\n message: 'Select dev tool',\\n type: 'list',\\n // Registered dev messages\\n choices,\\n },\\n];\\n\\n\\nafterDevMenu Triggered after selecting dev list/menu options.\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n beforeDevMenu(questions) {\\n questions[0].message += '!' ;\\n return questions; // required\\n },\\n afterDevMenu(options: Options) {\\n console.info(`choise ${options.result.choiceDevTool} dev tools`);\\n }\\n };\\n },\\n});\\n\\n\\nTypes of parameters entered and returned.\\n\\nexport type { QuestionCollection } from 'inquirer';\\n\\nexport interface Options {\\n result: PromptResult;\\n devTools: DevToolData[];\\n}\\n\\nexport type PromptResult = { choiceDevTool: string }\\nexport interface DevToolData {\\n name: string;\\n subCommands?: string[];\\n menuItem?: {\\n name: string;\\n value: string;\\n };\\n // Whether to disable the source build before the dev command is executed\\n disableRunBuild?: boolean;\\n action: (\\n options: { port?: string },\\n context: { isTsProject?: boolean },\\n ) => void | Promise<void>;\\n}\\n\\n\\n\\nBEFOREDEVTASK\\n\\nTriggered before the dev task is executed.\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n beforeDevTask(currentDevData: DevToolData) {\\n console.info(`${currentDevData.name} running`);\\n },\\n };\\n },\\n});\\n\\n\\nTypes of parameters entered and returned.\\n\\nexport interface DevToolData {\\n name: string;\\n subCommands?: string[];\\n menuItem?: {\\n name: string;\\n value: string;\\n };\\n // Whether to disable the source build before the dev command is executed\\n disableRunBuild?: boolean;\\n action: (\\n options: { port?: string },\\n context: { isTsProject?: boolean },\\n ) => void | Promise<void>;\\n}\\n\\n\\n\\nAFTERDEV\\n\\nTriggered when the dev task process is interrupted.\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n afterDev() {\\n console.info(`exit!`);\\n },\\n };\\n },\\n});\\n\",\"frontmatter\":{}},{\"title\":\"Handle static resource files\",\"routePath\":\"/en/guide/advance/asset\",\"toc\":[{\"id\":\"default-behavior\",\"text\":\"Default behavior\",\"depth\":2},{\"id\":\"setting-cdn-prefix\",\"text\":\"Setting CDN Prefix\",\"depth\":2},{\"id\":\"svgr-1\",\"text\":\"SVGR\",\"depth\":2}],\"content\":\"HANDLE STATIC RESOURCE FILES\\n\\nThe module project will handle static resources used in the code. If\\nconfiguration is required, then the buildConfig.asset API can be used.\\n\\n\\nDEFAULT BEHAVIOR\\n\\nBy default, module projects are processed for the following static resources:\\n\\n * '.svg'、'.png'、'.jpg'、'.jpeg'、'.gif'、'.webp'\\n * '.ttf'、'.otf'、'.woff'、'.woff2'、'.eot'\\n * '.mp3'、'.mp4'、'.webm'、'.ogg'、'.wav'、'.flac'、'.aac'、'.mov'\\n\\nFor the handling of static files, the module project currently supports the\\nfollowing functions.\\n\\n * Set the static resource path to . /assets.\\n * For files over 10kb they are inlined into the code.\\n * Use SVGR for files with the .svg suffix.\\n\\nLet us look at the following example:\\n\\n<CH.Spotlight>\\n\\n\\n//...\\n\\n\\n--------------------------------------------------------------------------------\\n\\nProject source code.\\n\\n\\n//...\\n\\n\\n--------------------------------------------------------------------------------\\n\\nIf the size of bg.png is less than 10 kb, then the product directory structure\\nand product content are.\\n\\n<CH.Code>\\n\\n./dist\\n└── asset.js\\n\\n\\n--------------------------------------------------------------------------------\\n\\nvar bg_default = 'data:image/png;base64,';\\nconsole.info(bg_default);\\n\\n\\n</CH.Code>\\n\\nIf the size of bg.png is larger than 10 kb, then the product directory structure\\nand product content are.\\n\\n<CH.Code>\\n\\n./dist\\n├── asset.js\\n└── assets\\n └── bg.13e2aba2.png\\n\\n\\n--------------------------------------------------------------------------------\\n\\nvar bg_default = 'assets/bg.13e2aba2.png';\\nconsole.info(bg_default);\\n\\n\\n</CH.Code>\\n\\n</CH.Spotlight>\\n\\nWhen wanting to modify the default behavior, the following API can be used:\\n\\n * asset.path: modify the output path of the static resource file.\\n * asset.limit: modify the threshold value for inline static resource files.\\n\\n\\nSETTING CDN PREFIX\\n\\nIf the project is running in a browser environment, we may need to host static\\nresources to a CDN and then use them in the production environment.\\n\\nThen we need to add the CDN base path in front of the path to the static\\nresource file in the default generated build product. Again, see an example:\\n\\n<CH.Spotlight>\\n\\n\\n//...\\n\\n\\n--------------------------------------------------------------------------------\\n\\nProject source code.\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\nmodern.config config file。\\n\\nexport default defineConfig({\\n buildConfig: {\\n format: 'umd',\\n asset: {\\n publicPath: 'https://cdn/',\\n },\\n },\\n});\\n\\n\\n--------------------------------------------------------------------------------\\n\\nIf the size of bg.png is larger than 10 kb, then the product content will be.\\n\\n(function (global, factory) {\\n if (typeof module === 'object' && typeof module.exports === 'object')\\n factory();\\n else if (typeof define === 'function' && define.amd) define([], factory);\\n else if (\\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self)\\n )\\n factory();\\n})(this, function () {\\n 'use strict';\\n var bg_default = 'http://cdn/assets/bg.13e2aba2.png';\\n // src/asset.tsx\\n console.info(bg_default);\\n});\\n\\n\\n</CH.Spotlight>\\n\\n\\nSVGR\\n\\nWIP\",\"frontmatter\":{\"sidebar_position\":6}},{\"title\":\"Build umd products\",\"routePath\":\"/en/guide/advance/build-umd\",\"toc\":[{\"id\":\"third-party-dependency-handling-for-umd-products\",\"text\":\"Third-party dependency handling for umd products\",\"depth\":2},{\"id\":\"changing-the-name-of-a-global-variable-in-a-project\",\"text\":\"Changing the name of a global variable in a project\",\"depth\":2}],\"content\":\"BUILD UMD PRODUCTS\\n\\nThe full name of umd is Universal Module Definition, and JS files in this format\\ncan run in multiple runtime environments: the\\n\\n * Browser environment: module loading based on AMD specification\\n * Node.js environment: module loading based on CommonJS\\n * Other cases: mount the module on a global object.\\n\\nWe can therefore specify the build product of the project as an umd product in\\nthe following way:\\n\\nexport default defineConfig({\\n buildConfig: {\\n format: 'umd',\\n },\\n});\\n\\n\\n\\nTHIRD-PARTY DEPENDENCY HANDLING FOR UMD PRODUCTS\\n\\nIn the [How to handle third-party dependencies] chapter, we know that we can\\ncontrol whether or not the project packages third-party dependencies via the\\nautoExternals and externals APIs. So when building umd products, we can also use\\nit like this:\\n\\n<CH.Spotlight>\\n\\n{\\n \\\"dependencies\\\": {\\n \\\"react\\\": \\\"^17\\\"\\n //...other dependencies\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nIf the project depends on react.\\n\\n{\\n \\\"dependencies\\\": {\\n \\\"react\\\": \\\"^17\\\"\\n //...other dependencies\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nmodern.config.ts.\\n\\nexport default defineConfig({\\n buildConfig: {\\n format: 'umd',\\n autoExternal: false,\\n externals: ['react'],\\n },\\n});\\n\\n\\n--------------------------------------------------------------------------------\\n\\nWhen a react dependency is used in the source code.\\n\\n\\nconsole.info(React);\\n\\n\\n--------------------------------------------------------------------------------\\n\\nThe react code is not packaged into the product at this point.\\n\\n(function (global, factory) {\\n if (typeof module === 'object' && typeof module.exports === 'object')\\n factory(exports, require('react'));\\n else if (typeof define === 'function' && define.amd)\\n define(['exports', 'react'], factory);\\n else if (\\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self)\\n )\\n factory((global.index = {}), global.react);\\n})(this, function (exports, _react) {\\n 'use strict';\\n Object.defineProperty(exports, '__esModule', {\\n value: true,\\n });\\n _react = /*#__PURE__*/ _interopRequireDefault(_react);\\n function _interopRequireDefault(obj) {\\n return obj && obj.__esModule\\n ? obj\\n : {\\n default: obj,\\n };\\n }\\n console.info(_react.default);\\n});\\n\\n\\n</CH.Spotlight>\\n\\nWe know from the above example that when using the autoExternal and externals\\nAPIs.\\n\\n * In a Node.js environment, you can get the react dependency with\\n require('react').\\n * In a browser environment, you can get the react dependency via global.react.\\n\\nHowever, in the browser environment, when getting third-party dependencies,\\nglobal variable names are not necessarily identical to the dependency names, so\\nyou have to use the buildConfig.umdGlobals API.\\n\\nAgain using the previous example, when the react dependency exists in the\\nbrowser environment as a windows.React or global.React global variable, then:\\n\\n<CH.Spotlight>\\n\\n{\\n \\\"devDependencies\\\": {\\n \\\"react\\\": \\\"^17\\\"\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nIf the project depends on react.\\n\\n{\\n \\\"devDependencies\\\": {\\n \\\"react\\\": \\\"^17\\\"\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nmodern.config.ts config file。\\n\\nexport default defineConfig({\\n buildConfig: {\\n format: 'umd',\\n umdGlobals: {\\n react: 'React',\\n },\\n },\\n});\\n\\n\\n--------------------------------------------------------------------------------\\n\\nWhen a react dependency is used in the source code.\\n\\n\\nconsole.info(React);\\n\\n\\n--------------------------------------------------------------------------------\\n\\nAt this point we will see the product code like this.\\n\\n(function (global, factory) {\\n if (typeof module === 'object' && typeof module.exports === 'object')\\n factory();\\n else if (typeof define === 'function' && define.amd) define([], factory);\\n else if (\\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self)\\n )\\n factory();\\n})(this, function () {\\n // ...\\n // libuild:globals:react\\n var require_react = __commonJS({\\n 'libuild:globals:react'(exports, module1) {\\n module1.exports = Function('return this')()['React'];\\n },\\n });\\n // src/index.ts\\n var import_react = __toESM(require_react());\\n console.info(import_react.default);\\n});\\n\\n\\n</CH.Spotlight>\\n\\nThe project can then run in the browser and use the React variables that exist\\non the global object.\\n\\n\\nCHANGING THE NAME OF A GLOBAL VARIABLE IN A PROJECT\\n\\nWhen we package the following code into an umd product and run it in the\\nbrowser, we can use the module via window.index.\\n\\nexport default () => {\\n console.info('hello world');\\n};\\n\\n\\n** By default, the name of the source file is used as the name of the module's\\nglobal variable in the browser. **For the above example, the product would read\\nas follows:\\n\\n(function (global, factory) {\\n if (typeof module === 'object' && typeof module.exports === 'object')\\n factory(exports);\\n else if (typeof define === 'function' && define.amd)\\n define(['exports'], factory);\\n else if (\\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self)\\n )\\n factory((global.index = {}));\\n})(this, function (exports) {\\n //...\\n});\\n\\n\\nIf you need to modify it, you need to use the buildConfig.umdModuleName API.\\n\\nWhen this API is used:\\n\\nexport default defineConfig({\\n buildConfig: {\\n format: 'umd',\\n umdModuleName: 'myLib',\\n },\\n});\\n\\n\\nThe construction products at this point are:\\n\\n(function (global, factory) {\\n if (typeof module === 'object' && typeof module.exports === 'object')\\n factory(exports);\\n else if (typeof define === 'function' && define.amd)\\n define(['exports'], factory);\\n else if (\\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self)\\n )\\n factory((global.myLib = {}));\\n})(this, function (exports) {\\n //...\\n});\\n\",\"frontmatter\":{\"sidebar_position\":5}},{\"title\":\"Use the Copy Tools\",\"routePath\":\"/en/guide/advance/copy\",\"toc\":[{\"id\":\"understanding-the-copy-api\",\"text\":\"Understanding the Copy API\",\"depth\":2},{\"id\":\"api-description\",\"text\":\"API Description\",\"depth\":2},{\"id\":\"不同场景使用示例\",\"text\":\"不同场景使用示例\",\"depth\":2},{\"id\":\"将文件复制文件\",\"text\":\"将文件复制文件\",\"depth\":3},{\"id\":\"将文件复制到目录\",\"text\":\"将文件复制到目录\",\"depth\":3},{\"id\":\"从目录复制到目录\",\"text\":\"从目录复制到目录\",\"depth\":3},{\"id\":\"从目录到文件\",\"text\":\"从目录到文件\",\"depth\":3},{\"id\":\"使用-glob\",\"text\":\"使用 Glob\",\"depth\":3}],\"content\":\"USE THE COPY TOOLS\\n\\nThe Module Project provides the Copy utility for copying already existing\\nindividual files or entire directories into the product directory. Next we learn\\nhow to use it.\\n\\n\\nUNDERSTANDING THE COPY API\\n\\nWe can use the Copy tool via the buildConfig.copy API, which contains the\\nfollowing two main configurations.\\n\\n * patterns\\n * options\\n\\nIt is recommended to spend some time getting to know them before you start\\nlearning.\\n\\n\\nAPI DESCRIPTION\\n\\ncopy.patterns 用于寻找复制的文件以及配置输出的路径。\\n\\n其中 patterns.from 用于指定要复制的文件或者目录。它接收 Glob 形式字符串或具体路径。Glob 形式字符串是指 fast-glob\\npattern-syntax。因此我们可以按照如下两种方式使用它:\\n\\nexport default defineConfig({\\n buildConfig: {\\n copy: {\\n patterns: [\\n { from: './index.html', to: '' },\\n { from: './*.html', to: '' },\\n ],\\n },\\n },\\n});\\n\\n\\npatterns.context 一般和 patterns.from 配合使用,默认情况下它的值与 buildConfig.sourceDir\\n相同,因此我们可以按照如下方式指定 src/data.json 文件为要复制的文件:\\n\\n> 默认情况下,buildConfig.sourceDir 为 src\\n\\nexport default defineConfig({\\n buildConfig: {\\n copy: {\\n patterns: [\\n { from: './data.json' to: ''},\\n ],\\n },\\n },\\n});\\n\\n\\n当指定的文件不在源码目录的时候,可以修改 context 配置。例如指定项目目录下的 temp/index.html 为要复制的文件:\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n copy: {\\n patterns: [\\n {\\n from: './index.html',\\n context: path.join(__dirname, './temp')\\n to: '',\\n }\\n ],\\n },\\n },\\n});\\n\\n\\npatterns.to 用于指定复制文件的输出路径,默认情况下它的值为 buildConfig.outDir对应的值。因此我们按照如下方式将\\nsrc/index.html 复制到 dist 目录下:\\n\\nexport default defineConfig({\\n buildConfig: {\\n copy: {\\n patterns: [{ from: './index.html' }],\\n },\\n },\\n});\\n\\n\\n当我们配置了 patterns.to 的时候:\\n\\n * 如果是相对路径,则该路径会相对于 buildConfig.outDir 计算出复制文件输出的绝对路径。\\n * 如果是绝对路径,则会直接使用该值。\\n\\n最后 patterns.globOptions 用于配置寻找复制文件 globby 对象,其配置可参考:\\n\\n * globby.options\\n\\n\\n不同场景使用示例\\n\\n\\n将文件复制文件\\n\\nexport default defineConfig({\\n buildConfig: [\\n {\\n outDir: 'dist',\\n copy: {\\n patterns: [\\n /**\\n * copy file to file\\n */\\n {\\n from: './temp-1/a.png',\\n context: __dirname,\\n to: './temp-1/b.png',\\n },\\n ],\\n },\\n },\\n ],\\n});\\n\\n\\n\\n将文件复制到目录\\n\\nexport default defineConfig({\\n buildConfig: [\\n {\\n outDir: 'dist',\\n copy: {\\n patterns: [\\n /**\\n * copy file to dir\\n */\\n {\\n from: './temp-2/a.png',\\n context: __dirname,\\n to: './temp-2',\\n },\\n ],\\n },\\n },\\n ],\\n});\\n\\n\\n\\n从目录复制到目录\\n\\nexport default defineConfig({\\n buildConfig: [\\n {\\n outDir: 'dist',\\n copy: {\\n patterns: [\\n /**\\n * copy dir to dir\\n */\\n {\\n from: './temp-3/',\\n to: './temp-3',\\n context: __dirname,\\n },\\n ],\\n options: {\\n enableCopySync: true,\\n },\\n },\\n },\\n ],\\n});\\n\\n\\n\\n从目录到文件\\n\\nexport default defineConfig({\\n buildConfig: [\\n {\\n outDir: 'dist',\\n copy: {\\n patterns: [\\n /**\\n * copy dir to file\\n */\\n {\\n from: './temp-4/',\\n context: __dirname,\\n to: './temp-4/_index.html',\\n },\\n ],\\n options: {\\n enableCopySync: true,\\n },\\n },\\n },\\n ],\\n});\\n\\n\\n\\n使用 GLOB\\n\\nexport default defineConfig({\\n buildConfig: [\\n {\\n outDir: 'dist',\\n copy: {\\n patterns: [\\n /**\\n * copy glob to dir\\n */\\n {\\n from: './*.html',\\n to: './temp-5',\\n },\\n ],\\n options: {\\n enableCopySync: true,\\n },\\n },\\n },\\n {\\n copy: {\\n patterns: [\\n /**\\n * copy glob to file\\n */\\n {\\n from: './*.html',\\n to: './temp-6/index.html',\\n },\\n ],\\n options: {\\n enableCopySync: true,\\n },\\n },\\n },\\n ],\\n});\\n\",\"frontmatter\":{\"sidebar_position\":3}},{\"title\":\"How to handle third-party dependencies\",\"routePath\":\"/en/guide/advance/external-dependency\",\"toc\":[{\"id\":\"default-handling-of-third-party-dependencies\",\"text\":\"Default handling of third-party dependencies\",\"depth\":2},{\"id\":\"packaging-third-party-dependencies\",\"text\":\"Packaging third-party dependencies\",\"depth\":2},{\"id\":\"turn-off-default-behavior\",\"text\":\"Turn off default behavior\",\"depth\":3},{\"id\":\"exclude-specified-third-party-dependencies\",\"text\":\"Exclude specified third-party dependencies\",\"depth\":3}],\"content\":\"HOW TO HANDLE THIRD-PARTY DEPENDENCIES\\n\\nGenerally, third-party dependencies required by a project can be installed via\\nthe install command in the package manager. After the third-party dependencies\\nare successfully installed, they will generally appear under dependencies and\\ndevDependencies in the project package.json.\\n\\n{\\n \\\"dependencies\\\": {},\\n \\\"devDependencies\\\": {}\\n}\\n\\n\\nDependencies under \\\"dependencies\\\" are generally related to project code and\\nbuilds, and if these third-party dependencies are declared under\\n\\\"devDependencies\\\", then there will be missing dependencies in production\\nenvironments.\\n\\nIn addition to \\\"dependencies\\\", \\\"peerDependencies\\\" can also declare dependencies\\nthat are needed in the production environment, but it puts more emphasis on the\\nexistence of these dependencies declared by \\\"peerDependencies\\\" in the project's\\nruntime environment, similar to the plugin mechanism.\\n\\n\\nDEFAULT HANDLING OF THIRD-PARTY DEPENDENCIES\\n\\nBy default, third-party dependencies under \\\"dependencies\\\" and \\\"peerDependencies\\\"\\nare not packaged in the module project**, so:\\n\\n<CH.Spotlight>\\n\\n{\\n \\\"dependencies\\\": {\\n \\\"react\\\": \\\"^17\\\"\\n },\\n // or\\n \\\"peerDependencies\\\": {\\n \\\"react\\\": \\\"^17\\\"\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nIf the project has a dependency on react.\\n\\n{\\n \\\"dependencies\\\": {\\n \\\"react\\\": \\\"^17\\\"\\n },\\n // or\\n \\\"peerDependencies\\\": {\\n \\\"react\\\": \\\"^17\\\"\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nWhen a react dependency is used in the source code.\\n\\n\\nconsole.info(React);\\n\\n\\n--------------------------------------------------------------------------------\\n\\nThe react code is not packaged into the product at this point.\\n\\n\\nconsole.info(React);\\n\\n\\n</CH.Spotlight>\\n\\n\\nPACKAGING THIRD-PARTY DEPENDENCIES\\n\\nHowever there are cases where you want to package these third-party dependencies\\ninto the product. The benefits of packaging third-party dependencies into the\\nproduct are: Reducing the time spent downloading third-party dependencies.\\n\\nThis way of handling third-party dependencies is generally more common in\\ndeveloping command-line tools, which can improve the loading speed of\\ncommand-line tools and give users a better experience.\\n\\nSo how do you enable the packaging of third-party dependencies in your module\\nproject?\\n\\nThe following APIs are provided in the build configuration to handle third-party\\ndependencies:\\n\\n * buildConfig.autoExternal\\n * buildConfig.externals\\n\\n\\nTURN OFF DEFAULT BEHAVIOR\\n\\nWhen we want to turn off the default handling behavior for third-party\\ndependencies, we can do so by:\\n\\nexport default defineConfig({\\n buildConfig: {\\n autoExternal: false,\\n },\\n});\\n\\n\\nThis way the dependencies under \\\"dependencies\\\" and \\\"peerDependencies\\\" will be\\npackaged. If you want to turn off the processing of only one of these\\ndependencies, you can use the buildConfig.autoExternal in the form of an object.\\n\\nexport default defineConfig({\\n buildConfig: {\\n autoExternal: {\\n dependencies: false,\\n peerDependencies: false,\\n },\\n },\\n});\\n\\n\\n\\nEXCLUDE SPECIFIED THIRD-PARTY DEPENDENCIES\\n\\nAnd in addition to the buildConfig.autoExternal API, buildConfig.externals can\\nalso control which third-party dependencies are to be handled. We can combine\\nthese two APIs to handle the project's dependencies in a more granular way.\\n\\nFor example, when we need to leave only certain dependencies unpacked, we can\\nconfigure it as follows.\\n\\n> In this case, it is likely that some dependencies are not suitable for\\n> packaging. If this is the case, then you can handle it as follows.\\n\\nepxort default defineConfig({\\n buildConfig: {\\n autoExternal: false,\\n externals: ['pkg-1', /pkg-2/],\\n }\\n});\\n\",\"frontmatter\":{\"sidebar_position\":4}},{\"title\":\"In-depth understanding of build\",\"routePath\":\"/en/guide/advance/in-depth-about-build\",\"toc\":[{\"id\":\"in-depth-understanding-of-buildconfig\",\"text\":\"In-depth understanding of buildConfig\",\"depth\":2},{\"id\":\"bundle-and-bundleless\",\"text\":\"Bundle and Bundleless\",\"depth\":3},{\"id\":\"relationship-between-input-and-sourcedir\",\"text\":\"Relationship between input and sourceDir\",\"depth\":3},{\"id\":\"object-type-of-input\",\"text\":\"Object type of input\",\"depth\":4},{\"id\":\"sourcedir-1\",\"text\":\"sourceDir\",\"depth\":4},{\"id\":\"declaration-type-files\",\"text\":\"Declaration Type Files\",\"depth\":3},{\"id\":\"turn-off-type-generation\",\"text\":\"Turn off type generation\",\"depth\":4},{\"id\":\"build-type-files\",\"text\":\"Build type files\",\"depth\":4},{\"id\":\"alias-conversion\",\"text\":\"Alias Conversion\",\"depth\":4},{\"id\":\"some-examples-of-the-use-of-dts\",\"text\":\"Some examples of the use of dts\",\"depth\":4},{\"id\":\"buildconfigdefine-usage-for-different-scenarios\",\"text\":\"buildConfig.define Usage for different scenarios\",\"depth\":3},{\"id\":\"environment-variable-replacement\",\"text\":\"Environment variable replacement\",\"depth\":4},{\"id\":\"global-variable-replacement\",\"text\":\"Global variable replacement\",\"depth\":4},{\"id\":\"build-process\",\"text\":\"Build process\",\"depth\":2},{\"id\":\"build-errors\",\"text\":\"Build errors\",\"depth\":2}],\"content\":\"IN-DEPTH UNDERSTANDING OF BUILD\\n\\nIn the [Basic Usage] section, we already knew that you can modify the output\\nproduct of a project through the buildConfig configuration. buildConfig not only\\ndescribes some of the features of the product, but also provides some\\nfunctionality for building the product.\\n\\nIf you are not sure what buildConfig is, it is recommended to take some time to\\nunderstand it by following this link.\\n\\n * [modify-output-product]\\n\\nIn this chapter we'll dive into the use of certain build configurations and\\nunderstand what happens when the modern build command is executed.\\n\\n\\nIN-DEPTH UNDERSTANDING OF BUILDCONFIG\\n\\n\\nBUNDLE AND BUNDLELESS\\n\\nSo first let's understand Bundle and Bundleless.\\n\\nA Bundle is a package of build products, which may be a single file or multiple\\nfiles based on a certain code splitting strategy.\\n\\nBundleless, on the other hand, means that each source file is compiled and built\\nseparately, but not packaged together. Each product file can be found with its\\ncorresponding source code file. The process of Bundleless build can also be\\nunderstood as the process of code conversion of source files only.\\n\\nIn buildConfig you can specify whether the current build task is Bundle or\\nBundleless by using buildConfig.buildType.\\n\\n\\nRELATIONSHIP BETWEEN INPUT AND SOURCEDIR\\n\\nbuildConfig.input is used to specify the file path or directory path where the\\nsource code is read, and its default value differs between Bundle and Bundleless\\nbuilds.\\n\\n * When buildType: 'bundle', input defaults to ['src/index.ts']\\n * When buildType: 'bundleless', input defaults to ['src']\\n \\n > In fact, at buildType: 'bundle', the build tool detects the existence of a\\n > file matching the name rule src/index.(j|t)sx? and uses it as an entry\\n > file.\\n\\nIt is recommended that you do not specify multiple source file directories\\nduring a Bundleless build, as unintended results may occur. Bundleless builds\\nwith multiple source directories are currently in an unstable stage.\\n\\nWe know from the defaults: Bundle builds can generally specify a file path as\\nthe entry point to the build, while Bundleless builds are more expected to use\\ndirectory paths to find source files.\\n\\nOBJECT TYPE OF INPUT\\n\\nIn addition to setting input to an array, you can also set it to an object\\nduring the Bundle build process. By using the object form, we can modify the\\nname of the file that the build product outputs. So for the following example, .\\n/src/index.ts corresponds to the path of the build product file as .\\n/dist/main.js.\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n input: {\\n main: ['./src/index.ts'],\\n },\\n outDir: './dist',\\n },\\n});\\n\\n\\nThe Bundleless build process also supports such use, but it is not recommended.\\n\\nSOURCEDIR\\n\\nsourceDir is used to specify the source code directory, which is related to\\nboth.\\n\\n * type file generation\\n * outbase for specifying the build process\\n\\nIn general:\\n\\n * During the Bundleless build process, the values of sourceDir and input should\\n be the same, and their default values are both src.\\n * It is rarely necessary to use sourceDir during the Bundle build process.\\n\\n\\nDECLARATION TYPE FILES\\n\\nThe buildConfig.dts configuration is mainly used for type file generation.\\n\\nTURN OFF TYPE GENERATION\\n\\nType generation is turned on by default, if you need to turn it off, you can\\nconfigure it as follows:\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n dts: false,\\n },\\n});\\n\\n\\nThe build speed is generally improved by closing the type file.\\n\\nBUILD TYPE FILES\\n\\nWith buildType: 'bundleless', type files are generated using the project's tsc\\ncommand to complete production.\\n\\nThe module engineering solution also supports packaging of type files, although\\ncare needs to be taken when using this feature.\\n\\n * Some third-party dependencies have incorrect syntax that can cause the\\n packaging process to fail. So in this case, you need to exclude such\\n third-party packages manually with buildConfig.externals.\\n * It is not possible to handle the case where the type file of a third-party\\n dependency points to a .ts file. For example, the package.json of a\\n third-party dependency contains something like this: {\\\"types\\\": \\\".\\n /src/index.ts\\\"}.\\n\\nALIAS CONVERSION\\n\\nDuring the Bundleless build process, if an alias appears in the source code,\\ne.g.\\n\\n\\n\\nNormally, product type files generated with tsc will also contain these aliases.\\nHowever, Module Tools will convert the aliases in the type file generated by tsc\\nto:\\n\\n * Alias conversion is possible for code of the form ``.\\n * Aliasing is possible for code of the form export { utils } from\\n '@common/utils'.\\n\\nHowever, there are some cases that cannot be handled at this time.\\n\\n * Output types of the form Promise<import('@common/utils')> cannot be converted\\n at this time.\\n\\nSOME EXAMPLES OF THE USE OF DTS\\n\\nGeneral usage:\\n\\n\\n\\nexport default defineConfig({\\n // The output path of the packaged type file at this point is `./dist/types`\\n buildConfig: {\\n buildType: 'bundle',\\n dts: {\\n tsconfigPath: './other-tsconfig.json',\\n distPath: './types',\\n },\\n outDir: './dist',\\n },\\n});\\n\\n\\nFor the use of dts.only:\\n\\n\\n\\nexport default defineConfig({\\n // At this moment the type file is not packaged and the output path is `./dist/types`\\n buildConfig: [\\n {\\n buildType: 'bundle',\\n dts: false,\\n outDir: './dist',\\n },\\n {\\n buildType: 'bundleless',\\n dts: {\\n only: true,\\n },\\n outDir: './dist/types',\\n },\\n ],\\n});\\n\\n\\n\\nBUILDCONFIG.DEFINE USAGE FOR DIFFERENT SCENARIOS\\n\\nbuildConfig.define functions somewhat similar to webpack.DefinePlugin. A few\\nusage scenarios are described here.\\n\\nENVIRONMENT VARIABLE REPLACEMENT\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n define: {\\n 'process.env.VERSION': JSON.stringify(process.env.VERSION || '0.0.0'),\\n },\\n },\\n});\\n\\n\\nWith the above configuration, we can put the following code.\\n\\n// pre-compiler code\\nconsole.log(process.env.VERSION);\\n\\n\\nWhen executing VERSION=1.0.0 modern build, the conversion is:\\n\\n// compiled code\\nconsole.log('1.0.0');\\n\\n\\nGLOBAL VARIABLE REPLACEMENT\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n define: {\\n VERSION: JSON.stringify(require('. /package.json').version || '0.0.0'),\\n },\\n },\\n});\\n\\n\\nWith the above configuration, we can put the following code.\\n\\n// pre-compile code\\nconsole.log(VERSION);\\n\\n\\nConvert to:\\n\\n// post-compile code\\nconsole.log('1.0.0');\\n\\n\\nNote, however: If the project is a TypeScript project, then you may need to add\\nthe following to the .d.ts file in the project source directory.\\n\\n> If the .d.ts file does not exist, then you can create it manually.\\n\\ndeclare const YOUR_ADD_GLOBAL_VAR;\\n\\n\\n\\nBUILD PROCESS\\n\\nWhen the modern build command is executed, the\\n\\n * Clear the products directory according to buildConfig.outDir.\\n * Compile js/ts source code to generate the JS build product for\\n Bundle/Bundleless.\\n * Generate Bundle/Bundleless type files using tsc.\\n * Handle Copy tasks.\\n\\n\\nBUILD ERRORS\\n\\nWhen a build error occurs, based on the information learned above, it is easy to\\nunderstand what error appears in the terminal.\\n\\nErrors reported for js or ts builds:\\n\\nerror ModuleBuildError:\\n\\n╭───────────────────────╮\\n│ bundle failed: │\\n│ - format is \\\"cjs\\\" │\\n│ - target is \\\"esnext\\\" │\\n╰───────────────────────╯\\n\\nDetailed Information:\\n\\n\\nErrors reported for the type file generation process:\\n\\nerror ModuleBuildError:\\n\\nbundle DTS failed:\\n\\n\\nFor js/ts build errors, we can tell from the error message.\\n\\n * By 'bundle failed:' to determine if the error is reported for a Bundle build\\n or a Bundleless build?\\n * What is the format of the build process?\\n * What is the target of the build process?\\n * The specific error message.\",\"frontmatter\":{\"sidebar_position\":1}},{\"title\":\"深入理解 dev 命令\",\"routePath\":\"/en/guide/advance/in-depth-about-dev-command\",\"toc\":[{\"id\":\"深入理解-buildconfig\",\"text\":\"深入理解 buildConfig\",\"depth\":2},{\"id\":\"bundle-和-bundleless\",\"text\":\"bundle 和 bundleless\",\"depth\":3},{\"id\":\"input-与-sourcedir-的关系\",\"text\":\"input 与 sourceDir 的关系\",\"depth\":3},{\"id\":\"构建过程\",\"text\":\"构建过程\",\"depth\":2}],\"content\":\"深入理解 DEV 命令\\n\\n在【基础使用】的部分,我们已经知道可以通过 buildConfig 配置对项目的输出产物进行修改。buildConfig\\n不仅描述了产物的一些特性,同时还为构建产物提供了一些功能。\\n\\n如果你还不清楚 buildConfig 是什么,建议花一些时间通过下面的链接了解一下:\\n\\n * 【修改输出产物】\\n\\n而在本章里我们将要深入理解某些构建配置的使用以及了解执行 modern build 命令的时候发生了什么。\\n\\n\\n深入理解 BUILDCONFIG\\n\\n那么首先我们来理解 bundle 和 bundleless 的构建模式。\\n\\n\\nBUNDLE 和 BUNDLELESS\\n\\n\\nINPUT 与 SOURCEDIR 的关系\\n\\n\\n构建过程\",\"frontmatter\":{\"sidebar_position\":2}},{\"title\":\"Theme Configuration\",\"routePath\":\"/en/guide/advance/theme-config\",\"toc\":[{\"id\":\"motivation-and-rationale\",\"text\":\"Motivation and rationale\",\"depth\":2},{\"id\":\"usage-examples\",\"text\":\"Usage examples\",\"depth\":2},{\"id\":\"tailwindcss-1\",\"text\":\"tailwindcss\",\"depth\":3},{\"id\":\"html-class-1\",\"text\":\"HTML Class\",\"depth\":4},{\"id\":\"apply-directives\",\"text\":\"@apply Directives\",\"depth\":4}],\"content\":\"THEME CONFIGURATION\\n\\nThe module project provides the ability to configure themes through the\\ndesignSystem API.\\n\\n\\nMOTIVATION AND RATIONALE\\n\\nTheme configuration is somewhat similar to the custom theme functionality in the\\ncomponent library and is mainly used in style development. We can use the\\ndesignToken generated by the designSystem configuration in different style\\ndevelopment environments.\\n\\nThe so-called designToken corresponds to different things in different style\\ndevelopment environments.\\n\\n * tailwindcss: use designSystem as the theme configuration for tailwindcss. So\\n you can use.\\n * The name of the HTML class supported by tailwindcss.\\n * @apply custom directive under css/less/sass to use a string with the same\\n name as the HTML class name supported by tailwindcss.\\n * css/less/scss: Generate global style variables via designSystem.\\n\\nThe data structure of the designSystem API is borrowed from the theme API in the\\ntailwindcss configuration object, so a default set of designToken exists. For\\nthe default values, see the designSystem API.\\n\\nThe css/less/sass global variables are not supported yet.\\n\\n\\nUSAGE EXAMPLES\\n\\n\\nTAILWINDCSS\\n\\nWhen using tailwindcss, its theme configuration can be set via designSystem.\\n\\nFor example, the following configuration extends the original color\\nconfiguration:\\n\\nexport default {\\n designSystem: {\\n extend: {\\n colors: {\\n primary: '#1677ff',\\n },\\n },\\n },\\n};\\n\\n\\nWe can have two ways of using tailwindcss in our code.\\n\\nHTML CLASS\\n\\nimport 'tailwindcss/utilities.css';\\n\\nexport default () => {\\n return <div className=\\\"bg-primary\\\"></div>;\\n};\\n\\n\\n@APPLY DIRECTIVES\\n\\nAbout @apply。\\n\\n<CH.Code>\\n\\nimport './index.css';\\n\\nexport default () => {\\n return <div className=\\\"btn-primary\\\"></div>;\\n};\\n\\n\\n.btn-primary {\\n @apply bg-primary;\\n}\\n\\n\\n</CH.Code>\",\"frontmatter\":{\"sidebar_position\":7}},{\"title\":\"Before you start\",\"routePath\":\"/en/guide/basic/before-getting-started\",\"toc\":[{\"id\":\"environment-preparation\",\"text\":\"Environment preparation\",\"depth\":2},{\"id\":\"getting-started-with-npm\",\"text\":\"Getting Started with npm\",\"depth\":2},{\"id\":\"npm-package-type-project\",\"text\":\"npm package type project\",\"depth\":2},{\"id\":\"using-third-party-npm-packages\",\"text\":\"Using third-party npm packages\",\"depth\":2},{\"id\":\"other-npm-bits-and-pieces-to-know\",\"text\":\"Other npm bits and pieces to know\",\"depth\":2},{\"id\":\"program-entry-for-npm-packages\",\"text\":\"Program entry for npm packages\",\"depth\":3},{\"id\":\"scripts\",\"text\":\"\\\"scripts\\\"\",\"depth\":3},{\"id\":\"npm-install\",\"text\":\"npm install\",\"depth\":4},{\"id\":\"npm-publish\",\"text\":\"npm publish\",\"depth\":4},{\"id\":\"peerdependencies-1\",\"text\":\"peerDependencies\",\"depth\":3},{\"id\":\"npm-package-manager\",\"text\":\"npm package manager\",\"depth\":2},{\"id\":\"module-tools-configuration-file\",\"text\":\"Module Tools configuration file\",\"depth\":2}],\"content\":\"BEFORE YOU START\\n\\n\\nENVIRONMENT PREPARATION\\n\\nIn order to use the Modern.js module engineering solution, you first need NodeJS\\nengine, we recommend the latest LTS version, and make sure the Node version is\\n>=14.17.6. because non-stable NodeJS releases frequently have bugs. You might\\nconsider installing via nvm-windows and nvm (Mac/linux), so you can easily\\nswitch to different NodeJS versions that might be required for different\\nprojects that you work on.\\n\\n\\nGETTING STARTED WITH NPM\\n\\nOnce NodeJS is installed, not only can you access the node executable from the\\ncommand line, but you can also execute the npm command.\\n\\nNpm is the standard package manager for NodeJS. It started out as a tool for\\ndownloading and managing NodeJS package dependencies, but it has since evolved\\ninto a tool for front-end JavaScript.\\n\\nIf you already know something about usage of npm and npm packages, then you can\\ndirectly see npm package manager section.\\n\\n\\nNPM PACKAGE TYPE PROJECT\\n\\nSo what is an npm package type project? When we execute the npm init command in\\nan empty project directory, it creates a JSON file with the file name\\npackage.json under the current directory. During the creation process, we will\\nneed to fill in information including but not limited to the name, version\\nnumber, description, etc. of the npm package, which will be found in the\\nresulting package.json file as follows\\n\\n{\\n \\\"name\\\": \\\"npm-demo\\\",\\n \\\"version\\\": \\\"1.0.0\\\",\\n \\\"description\\\": \\\"\\\",\\n \\\"main\\\": \\\"index.js\\\",\\n \\\"scripts\\\": {\\n \\\"test\\\": \\\"echo \\\\\\\"Error: no test specified\\\\\\\" && exit 1\\\"\\n },\\n \\\"author\\\": \\\"\\\",\\n \\\"license\\\": \\\"ISC\\\"\\n}\\n\\n\\nAt this point the project containing the initialized package.json file is an npm\\npackage type project, and you can execute the npm publish command to publish the\\nproject to the npm Registry.\\n\\nThe npm Registry is a npm package store where developers can not only publish\\ntheir own npm packages to the npm Registry, but also use npm packages published\\nby other developers through the npm Registry.\\n\\nA quality npm package will be used by more people because it not only saves a\\nlot of code implementation work, but is also less likely to cause problems with\\nthe project.\\n\\n\\nUSING THIRD-PARTY NPM PACKAGES\\n\\nWhen adding a third-party npm package to an initial project, we can call this\\nprocess \\\"installing dependencies for the project\\\" or \\\"adding dependencies to the\\nproject\\\". Before adding dependencies, we need to know one thing in particular --\\nthe types of packages npm depends on.\\n\\n * \\\"dependencies\\\": a type of package that your application will need in a\\n production environment.\\n * \\\"devDependencies\\\": another type of package that is only needed for local\\n development and testing.\\n \\n > packages can be understood as third-party npm packages.\\n\\nYou can install the packages you need in a production environment by running npm\\ninstall npm-package-name or npm add npm-package-name, or you can manually write\\nthe packages you need to install and the corresponding semantic version in\\n\\\"dependencies\\\" in the package.json file, and run the npm install command to.\\n\\n{\\n \\\"name\\\": \\\"your-npm-project\\\",\\n \\\"dependencies\\\": {\\n \\\"npm-package-name\\\": \\\"0.1.0\\\"\\n }\\n}\\n\\n\\nSimilarly, you can install only packages needed for local development and\\ntesting by running npm install npm-package-name --save-dev or npm add\\nnpm-package-name --save-dev, or you can manually write the packages to be\\ninstalled and the corresponding semantic version in \\\"devDependencies\\\" in the\\npackage.json file, and run the npm install command as follows\\n\\n{\\n \\\"name\\\": \\\"your-npm-project\\\",\\n \\\"devDependencies\\\": {\\n \\\"npm-package-name\\\": \\\"0.1.0\\\"\\n }\\n}\\n\\n\\nWhen installing or using third-party npm packages be sure to determine what they\\nare for and whether they should be placed in \\\"dependencies\\\" or \\\"devDependencies\\\"\\nby distinguishing between their types.\\n\\nIn general, packages that need to be used in source code are dependencies\\ndependencies. Unless you are exporting dependent code locally via packaging, in\\nwhich case it can be treated as a devDependencies dependency.\\n\\n\\nOTHER NPM BITS AND PIECES TO KNOW\\n\\n\\nPROGRAM ENTRY FOR NPM PACKAGES\\n\\nThere is a \\\"main\\\" attribute in package.json that corresponds to a module ID or,\\nmore intuitively, a NodeJS file path, which is the main entry point for your\\napplication.\\n\\nFor example, if your package is named foo and the user installs it, and then\\nexecutes the require(\\\"foo\\\") code, then the file corresponding to the \\\"main\\\"\\nfield of the npm package foo will be exported.\\n\\nIt is recommended to set the \\\"main\\\" field in your npm package. If \\\"main\\\" is not\\nset, the default entry will be the index.js file in the root of the package.\\n\\nIn addition to the \\\"main\\\" attribute, the \\\"module\\\" attribute is usually set. It\\nis similar to the \\\"main\\\" attribute in that it is mainly used in webpack\\nscenarios. webpack reads the npm package entry (file) in most cases in the order\\n\\\"module\\\" -> \\\"main \\\".\\n\\n> To learn more about how webpack does this, check out this link.\\n\\n\\n\\\"SCRIPTS\\\"\\n\\nThe \\\"scripts\\\" attribute of the package.json file supports a number of built-in\\nscripts and npm-preset lifecycle events, as well as arbitrary scripts.\\n\\nThese can be executed by running npm run-script <stage> or simply npm run\\n<stage>.\\n\\nName matching pre and post commands will also be run (e.g. premyscript,\\nmyscript, postmyscript ).\\n\\n{\\n \\\"scripts\\\": {\\n \\\"premyscript\\\": \\\"\\\",\\n \\\"myscript\\\": \\\"\\\",\\n \\\"postmyscript\\\": \\\"\\\"\\n }\\n}\\n\\n\\nWhen npm run myscripts is executed, the script corresponding to premyscripts\\nwill be executed before it, and the script corresponding to postmyscripts will\\nbe executed after it.\\n\\nScript commands from dependencies can be run with npm explore <pkg> -- npm run\\n<stage>.\\n\\nThere are also special lifecycle scripts that occur only under certain\\ncircumstances. Here are a few that are usually necessary to know.\\n\\nNPM INSTALL\\n\\nWhen you run npm install -g <pkg-name>, the following scripts will run.\\n\\n * preinstall\\n * install\\n * postinstall\\n * prepublish\\n * preprepare\\n * prepare\\n * postprepare\\n\\nIf your package root has a binding.gyp file and you don't define an install or\\npreinstall script, then npm will build with node-gyp rebuild as the default\\ninstall command, using node-gyp.\\n\\nNPM PUBLISH\\n\\nWhen publishing a project, executing this command will trigger the following\\nscript.\\n\\n * prepublishOnly\\n * prepack\\n * prepare\\n * postpack\\n * publish\\n * postpublish\\n\\nWhen running in -dry-run mode, the script corresponding to prepare will not be\\nexecuted.\\n\\n\\nPEERDEPENDENCIES\\n\\nIn some cases, your npm project has a compatibility relationship with its host\\ntool or library (e.g. a webpack plugin project and webpack), and your npm\\nproject does not want to use the host as a necessary dependency, which usually\\nmeans that your project is probably a plugin for that host tool or library. Your\\nnpm project will have certain requirements for the version of the host package,\\nas only the APIs required by the npm project will be exposed under a specific\\nversion.\\n\\nFor more explanation of peerDependencies, you can learn about the different ways\\nnpm, pnpm, and Yarn handle it at the following links.\\n\\n * npm's explanation of peerDependencies\\n * pnpm vs npm vs Yarn\\n\\n\\nNPM PACKAGE MANAGER\\n\\nIn addition to the standard package manager like npm, the mainstream ones are\\npnpm and Yarn, both of which are good alternatives to npm cli.\\n\\nIt is recommended to use pnpm to manage project dependencies, which can be\\ninstalled as follows.\\n\\nnpm install -g pnpm\\n\\n\\n\\nMODULE TOOLS CONFIGURATION FILE\\n\\nA configuration file for Module Tools is provided in the initial module project\\ndirectory -- modern.config.(j|t)s. By default, no configuration is required, so\\nthe modern.config configuration file is not required to exist.\\n\\nThe contents of the initial configuration file are as follows.\\n\\n// modern.config.ts\\n\\n\\nexport default defineConfig({});\\n\\n\\n// modern.config.js\\nconst { defineConfig } = require('@modern-js/module-tools');\\n\\nmodule.exports = defineConfig({});\\n\\n\\nWe recommend using the defineConfig function, but it is not mandatory to use it.\\nSo you can also return an object directly in the configuration file: the:\\n\\n// modern.config.ts\\nexport default {};\\n\\n\\n// modern.config.js\\nmodule.exports = {};\\n\",\"frontmatter\":{\"sidebar_position\":1}},{\"title\":\"Command Preview\",\"routePath\":\"/en/guide/basic/command-preview\",\"toc\":[{\"id\":\"modern-build\",\"text\":\"modern build\",\"depth\":2},{\"id\":\"modern-new\",\"text\":\"modern new\",\"depth\":2},{\"id\":\"modern-dev\",\"text\":\"modern dev\",\"depth\":2},{\"id\":\"modern-test\",\"text\":\"modern test\",\"depth\":2},{\"id\":\"modern-lint\",\"text\":\"modern lint\",\"depth\":2},{\"id\":\"-modern-change\",\"text\":\"-modern change\",\"depth\":2},{\"id\":\"modern-pre\",\"text\":\"modern pre\",\"depth\":2},{\"id\":\"modern-bump\",\"text\":\"modern bump\",\"depth\":2},{\"id\":\"modern-release\",\"text\":\"modern release\",\"depth\":2},{\"id\":\"modern-gen-release-note\",\"text\":\"modern gen-release-note\",\"depth\":2},{\"id\":\"modern-upgrade\",\"text\":\"modern upgrade\",\"depth\":2}],\"content\":\"COMMAND PREVIEW\\n\\nCommands available for module engineering projects.\\n\\n\\nMODERN BUILD\\n\\nUsage: modern build [options]\\n\\nBuild module command\\n\\nOptions:\\n -w, --watch Build code in listening mode\\n --tsconfig [tsconfig] Specify the path to the tsconfig.json file (default:\\n \\\". /tsconfig.json\\\")\\n --platform [platform] Build products for all or specified platforms\\n --no-dts disables DTS type file generation and type checking\\n --no-clear disables automatic clearing of product output directories\\n -h, --help Show information about the current command\\n\\n\\nWhen you want to start a project build, you can execute the modern build\\ncommand. When using this command, we can:\\n\\n * When wanting to start a build in watch mode, use the --watch option.\\n * When you want to specify the path to the TypeScript configuration file read\\n by the project build, use -build --tsconfig . /path/config.json option. This\\n option overrides all buildConfig configurations in dts.tsconfigPath.\\n * The -no-dts option can be used when the DTS type file generation and type\\n checking behavior of the project needs to be turned off. Note: The generation\\n of type files depends on the results of type checking. If type checking is\\n turned off, then type files will not be generated either.\\n * The --no-clear option can be used when the automatic clearing of the product\\n output directory needs to be turned off.\\n\\nIn addition to the above, module projects also support platform build mode,\\nwhich can be used to perform build tasks for other tools. For example, it is\\ncurrently officially supported to start a Storybook build task to generate\\nStorybook products by executing the modern build --platform or modern build\\n--platform storybook commands after installing the @modern-js/plugin-storybook\\nplugin.\\n\\nWhen executing a Storybook build, it needs to read the project's build product.\\nSo when running the modern build --platform command to start a Storybook build,\\nrun modern build once to ensure that the source build product exists.\\n\\n\\nMODERN NEW\\n\\nUsage: modern new [options]\\n\\nExecute the generator in a modular project scenario\\n\\nOptions:\\n -d, --debug Enable Debug mode, print debug log messages (default: false)\\n -c, --config <config> Generators run default configuration (JSON string)\\n --dist-tag <tag> Generator uses a special version of npm Tag\\n --registry customize npm Registry during generator runtime\\n -h, --help display help for command\\n\\n\\nThe modern new command is used to start the microgenerator functionality, which\\nenables features for the project that are not provided by default.\\n\\nThe following features can currently be enabled.\\n\\n * Storybook debugging\\n * Tailwind CSS support\\n * Modern.js Runtime API\\n\\nYou can learn more about these features in the Using the micro generator\\nsection.\\n\\n\\nMODERN DEV\\n\\nUsage: modern dev [options]\\n\\nLocal development commands\\n\\nOptions:\\n -h, --help display help for command\\n\\nCommands:\\n[dev-tools-subCommand]\\n\\n\\nThe module engineering solution provides the ability to use debugging tools,\\nwhich can be started with the modern dev command. Note, however, that no\\ndebugging-related plugins are provided by default, so executing modern dev will\\nprompt: \\\"No dev tools found available \\\".\\n\\nThe officially supported debugging tool is Storybook, so you can run modern dev\\nor modern dev storybook to execute it after you run modern new to enable it.\\n\\n\\nMODERN TEST\\n\\nUsage: modern test [options]\\n\\nOptions:\\n -h, --help display help for command\\n\\n\\nThe modern test command will automatically run the\\nsrc/tests/*.test.(js|ts|jsx|tsx) file as a test case.\\n\\n\\nMODERN LINT\\n\\nUsage: modern lint [options] [. .files]\\n\\nlint and fix source files\\n\\nOptions:\\n --no-fix disable auto fix source file\\n -h, --help display help for command\\n\\n\\nRun ESLint to check the syntax of the code. Usually, we only need to check the\\npart of the code that was changed in this commit with lint-staged during the\\n-git commit phase.\\n\\n * The -no-fix argument turns off the ability to automatically fix lint error\\n code.\\n\\n\\n-MODERN CHANGE\\n\\nUsage: modern change [options]\\n\\nCreate a changeset\\n\\nOptions:\\n --empty Create an empty changeset (default: false)\\n --open Open the created changeset in the editor (default: false)\\n -h, --help display help for command\\n\\n\\nThe modern change command is used to generate the required Markdown file for\\nchangesets.\\n\\n\\nMODERN PRE\\n\\nUsage: modern pre [options] <enter|exit> [tag]\\n\\nEntering and exiting pre-publishing mode\\n\\nOptions:\\n -h, --help display help for command\\n\\n\\nYou can use the modern pre command to pre-release a version before the official\\nrelease.\\n\\n\\nMODERN BUMP\\n\\nUsage: modern bump [options]\\n\\nUse changesets to automatically update releases and changelogs\\n\\nOptions:\\n --canary Create a pre-release for testing (default: false)\\n --preid <tag> Specify an identifier when versioning a pre-release (default: \\\"next\\\")\\n --snapshot Create a special version for testing (default: false)\\n -h, --help display help for command\\n\\n\\nModify the version number in package.json according to the Markdown file of the\\nchangelog generated by changesets, and generate the CHANGELOG.md file.\\n\\n\\nMODERN RELEASE\\n\\nUsage: modern release [options]\\n\\nRelease npm packages\\n\\nOptions:\\n --tag <tag> Release npm packages with a specific tag (default: \\\"\\\")\\n --ignore-scripts release ignores the scripts command in package.json, only supported in pnpm monorepo\\n (default: \\\"\\\")\\n -h, --help display help for command\\n\\n\\nThe -modern release command releases the module to the npm Registry.\\n\\n * The -tag argument specifies the specific dist tags to be used for the\\n release.\\n\\n\\nMODERN GEN-RELEASE-NOTE\\n\\nUsage: modern gen-release-note [options]\\n\\nGenerate Release Note based on current repository changeset information\\n\\nOptions:\\n --repo <repo> The name of the repository to generate the Pull Request link, e.g.: modern-js-dev/modern.js\\n --custom <cumtom> Custom Release Note generation function\\n -h, --help display help for command\\n\\n\\nAutomatically generate Release Note based on the changeset information of the\\ncurrent repository.\\n\\nneeds to be executed before the bump command.\\n\\n\\nMODERN UPGRADE\\n\\nUsage: modern upgrade [options]\\n\\nUpgrade Modern.js to the latest version\\n\\nOptions:\\n --registry <registry> customize npm registry (default: \\\"\\\")\\n -d,--debug Enable Debug mode to print debug log messages (default: false)\\n --cwd <cwd> project path (default: \\\"\\\")\\n -h, --help display help for command\\n\\n\\nThe modern upgrade command is used to upgrade the project Modern.js related\\ndependencies to the latest version.\\n\\nExecuting the command npx modern upgrade in the project root directory will\\nupdate the Modern.js dependencies in package.json of the currently executing\\nproject to the latest version by default.\\n\\ncommand is provided in @modern-js/module-tools version >= 1.17.0, previous\\nversions can be upgraded using npx @modern-js/upgrade.\",\"frontmatter\":{\"sidebar_position\":2}},{\"title\":\"modify-output-product\",\"routePath\":\"/en/guide/basic/modify-output-product\",\"toc\":[{\"id\":\"modify-output-product\",\"text\":\"Modify output product\",\"depth\":2},{\"id\":\"default-output-products\",\"text\":\"Default output products\",\"depth\":2},{\"id\":\"buildpreset\",\"text\":\"buildPreset\",\"depth\":2},{\"id\":\"string-form-of-buildpreset\",\"text\":\"String form of buildPreset\",\"depth\":3},{\"id\":\"function-form-of-buildpreset\",\"text\":\"Function form of buildPreset\",\"depth\":3},{\"id\":\"build-configuration-object\",\"text\":\"Build configuration (object)\",\"depth\":2},{\"id\":\"when-to-use-buildconfig\",\"text\":\"When to use buildConfig\",\"depth\":2}],\"content\":\"MODIFY-OUTPUT-PRODUCT\\n\\n\\nMODIFY OUTPUT PRODUCT\\n\\n\\nDEFAULT OUTPUT PRODUCTS\\n\\nWhen the modern build command is used in an initialized project, the products\\nare generated according to the default configuration supported by Module Tools.\\nThe default supported configurations are as follows.\\n\\n\\n\\nexport default defineConfig({\\n buildPreset: 'base-config',\\n});\\n\\n\\nThe default generated product has the following characteristics:\\n\\n * The code format is CommonJS, or simply cjs.\\n * Code syntax is supported up to ES6.\\n * All code is packaged into a single file, i.e. bundle processing is performed.\\n * The output root directory is the dist directory under the project, and the\\n output directory for type files is dist/types.\\n\\n 1. By \\\"code syntax support up to ES6\\\", we mean that the syntax supported by the\\n product code will not exceed ES6. If the source code uses syntax above ES6\\n (e.g. ES2017), it will be converted.\\n\\nYou may have the following questions when you see this:\\n\\n 1. what is buildPreset?\\n 2. what determines these characteristics of the output?\\n\\nThen the next step is to first explain buildPreset.\\n\\n\\nBUILDPRESET\\n\\nbuildPreset represents one or more sets of build-related configurations prepared\\nin advance. By using the corresponding preset values of buildPreset, you can\\neliminate the troublesome and complicated configuration work and get the\\nexpected product.\\n\\n\\nSTRING FORM OF BUILDPRESET\\n\\nThe value of a build preset can be in the form of a string, so a build preset of\\nthis form is called a preset string.\\n\\nThe module engineering solution provides generic build preset strings and\\ncorresponding variants, depending on the generic scenario in which the npm\\npackage is used. All currently supported preset strings can be viewed via the\\nBuildPreset API. The relationship between generic preset strings and variants is\\nexplained here.\\n\\nAmong the generic preset strings, \\\"npm-library\\\" can be used in the scenario of\\ndeveloping npm packages of the library type, which is suitable for most common\\nmodule type projects. When \\\"npm-library\\\" is set, the output product of the\\nproject will have the following characteristics:\\n\\n * In the dist/lib directory you will get the product in the code format cjs,\\n with syntax support up to es6 and after packaging.\\n * In the dist/es directory, you get code in the format esm, with syntax support\\n up to es6 and packaged.\\n * In the dist/types directory, you get the type files. If it is not a\\n TypeScript project, there is no such directory.\\n\\nThe default string \\\"npm-library\\\" is a variant of the original product with\\nmodified code-syntax support and a string naming change to \\\"npm-library-[es5 |\\nes2016.... . es2020 | esnext]\\\".\\n\\nFor example, if the output product is based on the preset string \\\"npm-library\\\"\\nand the syntax supported by the product code is changed to es2017, then simply\\nchanging \\\"npm-library\\\" to \\\"npm-library-es2017\\\" would be sufficient.\\n\\n\\nFUNCTION FORM OF BUILDPRESET\\n\\nIn addition to the string form, the value of a build preset can also be in the\\nform of a function, where the specific configuration corresponding to a preset\\nvalue can be printed or modified.\\n\\nFor example, if the same effect as the preset string \\\"npm-library-es2017\\\" is\\nachieved using the preset function form, it can be done as follows:\\n\\n\\n\\nexport default defineConfig({\\n buildPreset({ preset }) {\\n return preset.NPM_LIBRARY.map(config => {\\n return { ... .config, target: 'es2017' }\\n });\\n },\\n});\\n\\n\\nIn the above code implementation, preset.NPM_LIBRARY corresponds to the preset\\nstring \\\"npm-library\\\", which represents the \\\"npm-library\\\" equivalent of a\\nmulti-group build-related configuration. We traverse the NPM_LIBRARY array,\\nwhich contains multiple buildConfig objects, with the map method. We make a\\nshallow copy of the original buildConfig object and modify the shallow copy to\\nget buildConfig.target, specifying it as es2017.\\n\\n> The specific value of preset.NPM_LIBRARY can be viewed via the BuildPreset\\n> API. The preset object contains not only NPM_LIBRARY, but also other similar\\n> constants.\\n\\nSo what is the buildConfig object here? And what are the previously mentioned\\nbuild product features based on?\\n\\nWe explain it next.\\n\\n\\nBUILD CONFIGURATION (OBJECT)\\n\\nbuildConfig is a configuration object that describes how to compile and generate\\nbuild products. What was mentioned at the beginning about \\\"features of build\\nproducts\\\" are actually properties supported by buildConfig. The currently\\nsupported properties cover the needs of most module type projects when building\\nproducts. buildConfig not only contains some of the properties that products\\nhave, but also some of the features needed to build products. The following is a\\nbrief list from a classification point of view:\\n\\nThe basic attributes of a build product include:\\n\\n * Whether the product is packaged or not: the corresponding API is\\n buildConfig.buildType.\\n * Product support for syntax: the corresponding API is buildConfig.target.\\n * Output format: The corresponding API is buildConfig.format.\\n * How to handle the output type file: the corresponding API is buildConfig.dts.\\n * How the sourceMap of the product is handled: the corresponding API is\\n buildConfig.sourceMap.\\n * The input (or source file) corresponding to the output: the corresponding API\\n is buildConfig.input.\\n * The directory of the output of the product: the corresponding API is\\n buildConfig.outDir.\\n * The source directory of the build: the corresponding API is\\n buildConfig.sourceDir.\\n\\nCommon functions needed to build products include:\\n\\n * Alias: The corresponding API is buildConfig.alias.\\n * Static resource handling: The corresponding API is buildConfig.asset.\\n * Third-party dependency handling: The corresponding APIs are\\n * buildConfig.autoExternal.\\n * buildConfig.externals.\\n * Copy: The corresponding API is buildConfig.copy.\\n * Global variable substitution: the corresponding API is buildConfig.define.\\n * Specify JSX compilation method, the corresponding API is buildConfig.jsx.\\n\\nSome advanced properties or less frequently used functions:\\n\\n * Product code compression: The corresponding API is buildConfig.minify.\\n * Code splitting: buildConfig.splitting\\n * Specify whether the build product is for the NodeJS environment or the\\n browser environment: the corresponding API is buildConfig.platform.\\n * umd product-related.\\n * Specifies the global variables imported externally to the umd product: the\\n corresponding API is buildConfig.umdGlobals.\\n * Specify the module name of the umd product: the corresponding API is\\n buildConfig.umdModuleName.\\n\\nIn addition to the above categories, frequently asked questions and best\\npractices about these APIs can be found at the following links.\\n\\n * What are bundle and bundleless?\\n * The relationship between input and sourceDir\\n * The multiple ways of generating type files in products\\n * The use of buildConfig.define for different scenarios.\\n * How to handle third-party dependencies?\\n * How to use copy?\\n * How to build umd products?\\n * The capabilities currently supported by static resources.\\n\\n\\nWHEN TO USE BUILDCONFIG\\n\\nbuildConfig is one of the ways used to modify the product, and only buildConfig\\nwill take effect when configured in conjunction with buildPreset. So if\\nconfigured as follows.\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: [{}],\\n buildPreset: 'base-config',\\n});\\n\\n\\nThen at this point you will see the following prompt.\\n\\nSince both 'buildConfig' and 'buildPreset' are present, only the 'buildConfig' configuration will take effect\\n\\n\\nThe set or sets of build-related configurations represented by buildPreset are\\ncomposed of buildConfig, which can be used to customize output products when the\\ncurrent project needs cannot be met using buildPreset.\\n\\nThe process of using buildConfig is the process of thinking about \\\"what kind of\\nbuild product to get\\\".\",\"frontmatter\":{\"sidebar_position\":3}},{\"title\":\"Versioning and Publishing\",\"routePath\":\"/en/guide/basic/publish-your-project\",\"toc\":[{\"id\":\"tracking-changes\",\"text\":\"Tracking changes\",\"depth\":2},{\"id\":\"version-update\",\"text\":\"Version update\",\"depth\":2},{\"id\":\"publish\",\"text\":\"Publish\",\"depth\":2},{\"id\":\"pre-releases\",\"text\":\"Pre-releases\",\"depth\":2}],\"content\":\"VERSIONING AND PUBLISHING\\n\\nAn npm-type module project release process consists of two phases.\\n\\n * The first phase is during development, where the developer needs to provide a\\n change file to record changes that need to be released.\\n * The second phase is during release, where Module Tools can collect all the\\n change files to update the version, update the release log, and release new\\n packages to the npm Registry.\\n\\n\\nTRACKING CHANGES\\n\\nChanges need to be logged when they happen to the project. Changes that occur in\\na project are typically.\\n\\n * New features\\n * Fixes to issues\\n * Configuration file changes\\n * ...\\n\\nOnce these changes have been made, the current changes need to be documented\\nwith the following command.\\n\\n * modern change\\n\\nExecuting the modern change command asks the developer several questions and\\ngenerates a change log based on the developer's answers. The changelog file\\ncontains the type of change and its description, and is committed to the git\\nrepository.\\n\\n$ npx modern change\\n🦋 What kind of change is this for module-example? (current version is 0.1.0) - patch\\n🦋 Please enter a summary for this change (this will be in the changelogs). Submit empty line to open external editor\\n🦋 Summary - publish test\\n🦋 === Releasing the following packages ===\\n🦋 [Patch]\\n🦋 module\\n🦋 Is this your desired changeset? (Y/n) - true\\n🦋 Changeset added! - you can now commit it\\n🦋\\n🦋 If you want to modify or expand on the changeset summary, you can find it here\\n🦋 info /xxxxxx/module/.changeset/brave-dryers-agree.md\\n\\n\\nWhen executed successfully, the resulting Markdown file containing the change\\nlog is saved in the project's .changeset directory. The contents will look like\\nthe following.\\n\\n---\\n\\\"``module-example'': patch\\n---\\n\\npublish test\\n\\n\\n\\nVERSION UPDATE\\n\\nWhen the project version needs to be updated, execute the following command.\\n\\n * modern bump\\n\\nExecuting modern bump will modify the version number in package.json based on\\nthe contents of the Markdown file in the .changeset/ directory where the changes\\nwere recorded, and generate the CHANGELOG.md file. These Markdown files are also\\ndeleted when the version update is complete, so they are \\\"consumed \\\".\\n\\n# module\\n\\n## 0.1.1\\n\\n### Patch Changes\\n\\n- publish test\\n\\n\\n\\nPUBLISH\\n\\nTo publish a project, you can execute the following command.\\n\\n * modern publish\\n\\nThe modern release command publishes the project to the npm Registry.\\n\\nThe release is the latest version, which is also the official version. If you\\nwant to change the dist-tag, you can specify it with the modern release --tag\\ncommand. For example.\\n\\nmodern release --tag beta\\n\\n\\nHowever, if you want to change the version number of the current project to a\\npre-release as well, you need to use the modern pre command.\\n\\n> dist-tag can be understood as: tagging the current release. Generally\\n> speaking, the dist-tag for the default release is latest, so you can consider\\n> latest as the dist-tag for the official release.\\n\\n\\nPRE-RELEASES\\n\\nWhen a pre-release is needed before the official release, the following command\\nis executed.\\n\\n * modern pre\\n\\nFirst modern pre enter <tag> to enter pre-release mode, <tag> can be the same as\\nthe tag specified with the modern release --tag command when releasing the\\nproject.\\n\\n$ npx modern pre enter next\\n🦋 success Entered pre mode with tag next\\n🦋 info Run `changeset version` to version packages with prerelease versions\\n✨ Done in 5.30s.\\nDone in 5.30s. ```\\n\\nThen you can update the specific version number with the `modern bump` command, **which doesn't actually \\\"consume\\\" the Markdown file that records the changes**: ``` bash\\n\\n``` bash\\n$ npx modern bump\\n🦋 warn ===============================IMPORTANT!===============================\\n🦋 warn You are in prerelease mode\\n🦋 warn If you meant to do a normal release you should revert these changes and run `changeset pre exit`\\n🦋 warn You can then run `changeset version` again to do a normal release\\n🦋 warn ----------------------------------------------------------------------\\n🦋 All files have been updated. review them and commit at your leisure\\n\\n\\nThen you can see that the updated version number in package.json will look like\\nthis: 0.1.2-next.0.\\n\\nFinally, if you don't need to do a pre-release anymore, be sure to run the\\nmodern pre exit command to exit the pre-release state and to release the\\nofficial version when you run the modern bump command again.\",\"frontmatter\":{\"sidebar_position\":7}},{\"title\":\"Testing Projects\",\"routePath\":\"/en/guide/basic/test-your-project\",\"toc\":[{\"id\":\"prerequisites-and-conventions\",\"text\":\"Prerequisites and conventions\",\"depth\":2},{\"id\":\"run-the-tests\",\"text\":\"Run the tests\",\"depth\":2},{\"id\":\"usage-configuration\",\"text\":\"Usage Configuration\",\"depth\":2},{\"id\":\"test-example\",\"text\":\"Test example\",\"depth\":2},{\"id\":\"common-modules\",\"text\":\"Common modules\",\"depth\":3},{\"id\":\"components\",\"text\":\"Components\",\"depth\":3}],\"content\":\"TESTING PROJECTS\\n\\nThis chapter will describe how to test modules.\\n\\n\\nPREREQUISITES AND CONVENTIONS\\n\\nTo use the testing functionality of the project, you need to make sure that the\\nproject contains the following dependencies:\\n\\n * \\\"@modern-js/plugin-testing\\\"\\n\\nIn the module engineering scheme, the following conventions are in place for\\ntest cases, or files for writing tests:\\n\\n * The tests directory in the project directory is the directory for test cases\\n and test files, no support for changing the directory for running test cases.\\n * Files with the suffix .test.[tj]sx? are automatically recognized as test\\n files by default.\\n * Other . [tj]sx? suffixes are recognized as normal files that can be used as\\n test utils files or for other purposes.\\n\\n\\nRUN THE TESTS\\n\\nOnce the dependencies are prepared and we know where to write the test cases, we\\ncan execute the tests with the following command:\\n\\nmodern test\\n\\n// Update snapshot\\nmodern test --updateSnapshot\\n\\n\\nAfter execution, you will see the results of the test:\\n\\n\\n\\n\\nUSAGE CONFIGURATION\\n\\nThe Module Engineering Program provides the following configurations for\\ntesting.\\n\\n * testing\\n\\nYou can add it in modern.config.(j|t)s.\\n\\n\\nTEST EXAMPLE\\n\\n\\nCOMMON MODULES\\n\\nFor common modules, we can use the test function as follows:\\n\\n<CH.Spotlight>\\n\\nexport default function () {\\n return 'hello world';\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nFirst is the code of the module.\\n\\nexport default function () {\\n return 'hello world';\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nThen in the test file, we can do this.\\n\\nWhere @ points to the source directory, defined in tests/tsconfig.json in the\\ninitialization project.\\n\\n\\n\\ndescribe('default cases', () => {\\n test('Have returns', () => {\\n const drink = jest.fn(main);\\n drink();\\n expect(drink).toHaveReturned();\\n });\\n});\\n\\n\\n--------------------------------------------------------------------------------\\n\\nFinally we can execute modern test.\\n\\npnpm test\\n## or\\nyarn test\\n## or\\nnpm run test\\n\\n\\n</CH.Spotlight>\\n\\n\\nCOMPONENTS\\n\\n{/* 链接待补充 */}\\n\\nFor components, Modern.js's Runtime API provides functionality for testing UI\\ncomponents, which is provided by @modern-js/runtime/testing.\\n\\nIf you need to use the Runtime API, then you can turn it on via microgenerator.\\n\\n<CH.Spotlight>\\n\\nexport const default () {\\n return (\\n <div>This is a UI Component</div>\\n );\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nFirst is the code of the component.\\n\\nexport const default () {\\n return (\\n <div>This is a UI Component</div>\\n );\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nThen in the test file, we can do this.\\n\\nWhere @ points to the source directory, defined in tests/tsconfig.json in the\\ninitialization project.\\n\\n\\n\\n\\n\\ndescribe('default cases', () => {\\n test('Rendered', () => {\\n render(<Component />);\\n expect(screen.getByText('This is a UI Component')).toBeInTheDocument();\\n });\\n});\\n\\n\\n--------------------------------------------------------------------------------\\n\\nFinally we can execute modern test.\\n\\npnpm test\\n## or\\nyarn test\\n## or\\nnpm run test\\n\\n\\n</CH.Spotlight>\",\"frontmatter\":{\"sidebar_position\":6}},{\"title\":\"Using the Microgenerator\",\"routePath\":\"/en/guide/basic/use-micro-generator\",\"toc\":[{\"id\":\"storybook\",\"text\":\"Storybook\",\"depth\":2},{\"id\":\"tailwind-css-support\",\"text\":\"Tailwind CSS support\",\"depth\":2},{\"id\":\"modernjs-runtime-api\",\"text\":\"Modern.js Runtime API\",\"depth\":2}],\"content\":\"USING THE MICROGENERATOR\\n\\nThe Module Engineering solution provides the Microgenerator tool, which allows\\nfor the current project to.\\n\\n * add new directories and files\\n * Modify the contents of the package.json file\\n * Execute commands\\n\\nThus with these capabilities, Microgenerator can enable additional feature\\nfunctionality for the project.\\n\\nThe microgenerator can be started via modern new. The current Microgenerator\\nfeatures supported by the Module Engineering program are:\\n\\n\\nSTORYBOOK\\n\\nThe Storybook feature can be enabled when we want to debug a component or a\\ncommon module. When this feature is enabled, the stories directory and related\\nfiles are created in the project directory, and a new\\n\\\"@modern-js/plugin-storybook\\\" dependency is added to package.json.\\n\\nFor more information on how to start Storybook and how to use it, check out the\\nfollowing link.\\n\\n * modern dev\\n * using Storybook\\n\\n\\nTAILWIND CSS SUPPORT\\n\\nThis can be enabled when we want to add Tailwind CSS support to our project.\\nTailwind CSS is a CSS library that provides out-of-the-box styling.\\n\\nFor more information on how to use Tailwind CSS in your module projects, check\\nout.\\n\\n * Using Tailwind CSS\\n\\n\\nMODERN.JS RUNTIME API\\n\\nModern.js provides Runtime API capabilities that can only be used in the\\nModern.js application project environment. If you need to develop a component\\nfor use in a Modern.js application environment, then you can turn on this\\nfeature and the microgenerator will add the \\\"@modern-js/runtime\\\" dependency.\\n\\nAlso, the Storybook debugging tool will determine if the project needs to use\\nthe Runtime API by checking the project's dependencies and providing the same\\nRuntime API runtime environment as the Modern.js application project.\",\"frontmatter\":{\"sidebar_position\":4}},{\"title\":\"Using Storybook\",\"routePath\":\"/en/guide/basic/using-storybook\",\"toc\":[{\"id\":\"debugging-code\",\"text\":\"Debugging code\",\"depth\":2},{\"id\":\"referencing-component-products\",\"text\":\"Referencing component products\",\"depth\":3},{\"id\":\"referencing-component-source-code\",\"text\":\"Referencing component source code\",\"depth\":3},{\"id\":\"configure-storybook\",\"text\":\"Configure Storybook\",\"depth\":2},{\"id\":\"configuration-file\",\"text\":\"Configuration file\",\"depth\":3},{\"id\":\"devstorybook\",\"text\":\"dev.storybook\",\"depth\":3},{\"id\":\"building-storybook-products\",\"text\":\"Building Storybook Products\",\"depth\":3}],\"content\":\"USING STORYBOOK\\n\\nFirst of all, if you haven't read the following, take a few minutes to\\nunderstand it first.\\n\\n * use micro-generator to enable Storybook debugging\\n * modern dev\\n\\nStorybook is a tool dedicated to component debugging, providing around component\\ndevelopment.\\n\\n * Develop UIs that are more durable\\n * Test UIs with less effort and no flakes\\n * Document UI for your team to reuse\\n * Share how the UI actually works\\n * Automate UI workflows\\n\\nSo it is a complex and powerful tool.\\n\\nThe modular engineering solution is integrated with Storybook, so you can pretty\\nmuch follow the official Storybook documentation. However, there are still a few\\nthings to keep in mind, which are explained below.\\n\\n\\nDEBUGGING CODE\\n\\nComponent code needs to be introduced during debugging code, and currently\\ncomponent code can be introduced in two ways:\\n\\n * Referencing the component product\\n * Referencing component source code\\n\\nWe recommend the first way of \\\"referencing component product\\\". Because it is\\nalmost close to the real usage scenario, not only can we debug the component\\nfunctionality, but also verify the correctness of the build product.\\n\\nNext, we will talk about how to use each of these two methods.\\n\\n\\nREFERENCING COMPONENT PRODUCTS\\n\\nIf the TypeScript project foo exists.\\n\\n<CH.Spotlight>\\n\\n{\\n \\\"name\\\": \\\"foo\\\",\\n \\\"main\\\": \\\"./dist/index.js\\\",\\n \\\"types\\\": \\\"./dist/types/index.d.ts\\\"\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nMake sure the main and types of package.json values are real paths.\\n\\n{\\n \\\"name\\\": \\\"foo\\\",\\n \\\"main\\\": \\\"./dist/index.js\\\",\\n \\\"types\\\": \\\"./dist/types/index.d.ts\\\"\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nThe source code of the foo project.\\n\\nexport const content = 'hello world';\\n\\n\\n--------------------------------------------------------------------------------\\n\\nMake sure that the paths configuration pointing to the project root is set in\\nstories/tsconfig.json. The key of paths is the same as the project name.\\n\\n{\\n \\\"extends\\\": \\\"../tsconfig.json\\\",\\n \\\"include\\\": [\\\"./\\\"],\\n \\\"compilerOptions\\\": {\\n \\\"jsx\\\": \\\"preserve\\\",\\n \\\"baseUrl\\\": \\\".\\\",\\n \\\"paths\\\": {\\n \\\"foo\\\": [\\\"../\\\"]\\n }\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nFinally, it is referenced directly in the Story code by the project name.\\n\\n\\n\\nconst Component = () => <div>this is a Story Component {content}</div>;\\n\\nexport const YourStory = () => <Component />;\\n\\nexport default {\\n title: 'Your Stories',\\n};\\n\\n\\n</CH.Spotlight>\\n\\nIf, during development, you encounter a situation where the type definition is\\nnot available in real time, at that point.\\n\\nFor pnpm projects, package.json can be modified as follows.\\n\\n{\\n \\\"name\\\": \\\"foo\\\",\\n \\\"main\\\": \\\"./dist/index.js\\\",\\n \\\"types\\\": \\\"./src/index.ts\\\",\\n \\\"publishConfig\\\": {\\n \\\"types\\\": \\\"./dist/index.d.ts\\\",\\n }\\n}\\n\\n\\n> For the use of pnpm's publishConfig, you can read the following link.\\n\\nFor npm and Yarn projects, the values of types of package.json can only be\\nchanged manually in development phase and release phase.\\n\\nSo why is it possible to reference the product directly?\\n\\n 1. the modern build command is executed automatically before the modern dev\\n storybook command, ensuring the existence of the project build product.\\n 2. The project name is added as an alias inside Storybook to ensure that the\\n path to the project's product can be parsed according to package.json.\\n\\n\\nREFERENCING COMPONENT SOURCE CODE\\n\\nReferencing component source code can be done by means of relative paths to:\\n\\n\\n\\nconst Component = () => <div>this is a Story Component {content}</div>;\\n\\nexport const YourStory = () => <Component />;\\n\\nexport default {\\n title: 'Your Stories',\\n};\\n\\n\\nSo why is the source code approach not recommended?\\n\\nNot only is it impossible to verify that the component product is correct using\\nthe component source code, but also some of the configurations supported by the\\nmodule project for building the product cannot be fully translated into\\nStorybook internal configuration. If some of the configurations cannot be\\nconverted to each other, there will be unintended results during Storybook\\ndebugging.\\n\\n\\nCONFIGURE STORYBOOK\\n\\n\\nCONFIGURATION FILE\\n\\nStorybook is officially configured for projects through a folder called\\n.storybook, which contains various configuration files. In a module project\\nscenario, Storybook configuration files can be added to the config/storybook\\ndirectory of the project.\\n\\nFor more information on how to use the various Storybook configuration files,\\nsee the following links:\\n\\n * Configure Storybook\\n\\nBut there are some limitations to Storybooking in a module project:\\n\\n * It is currently not possible to change the location of the Story file, i.e.,\\n you cannot change the stories configuration in the main.js file.\\n * Currently you cannot modify Webpack and Babel related configuration, i.e. you\\n cannot modify webpackFinal and babel configuration in the main.js file.\\n\\nIn the future we will consider whether these configurations can be allowed to be\\nmodified, but for now we are limiting their use to reduce unpredictable issues.\\n\\n\\nDEV.STORYBOOK\\n\\nIn addition to the configuration file, the module engineering solution also\\nprovides a dev.storybook configuration item in the modern.config.(j|t)s project\\nconfiguration file.\\n\\nThe webpack configuration of Storybook can be modified via this configuration.\\n\\n{/* 链接待补充 */}\\n\\n * dev.storybook.webpack\\n\\n\\nBUILDING STORYBOOK PRODUCTS\\n\\nIn addition to Storybook debugging of components or common modules, you can also\\nperform Storybook build tasks with the following commands.\\n\\nmodern build --platform storybook\\n\\n\\nFor the modern build --platform command you can see.\\n\\n * modern build\\n\\nAfter the build is complete, you can see the build product files in the\\ndist/storybook-static directory.\",\"frontmatter\":{\"sidebar_position\":5}},{\"title\":\"# Initialize the project\",\"routePath\":\"/en/guide/best-practices/components\",\"toc\":[{\"id\":\"debugging-code-with-storybook\",\"text\":\"Debugging code with Storybook\",\"depth\":2},{\"id\":\"developing-styles\",\"text\":\"Developing Styles\",\"depth\":2},{\"id\":\"csspostcss\",\"text\":\"CSS/PostCSS\",\"depth\":3},{\"id\":\"less-1\",\"text\":\"Less\",\"depth\":3},{\"id\":\"sassscss\",\"text\":\"Sass/Scss\",\"depth\":3},{\"id\":\"tailwind-css\",\"text\":\"Tailwind CSS\",\"depth\":3},{\"id\":\"html-class\",\"text\":\"HTML class\",\"depth\":4},{\"id\":\"apply\",\"text\":\"@apply\",\"depth\":4},{\"id\":\"recommended-method\",\"text\":\"Recommended method\",\"depth\":4},{\"id\":\"the-difference-between-bundle-and-bundleless-build-products\",\"text\":\"The difference between bundle and bundleless build products\",\"depth\":4},{\"id\":\"css-modules\",\"text\":\"CSS Modules\",\"depth\":3},{\"id\":\"configuring-build-products\",\"text\":\"Configuring build products\",\"depth\":2},{\"id\":\"testing-components\",\"text\":\"Testing components\",\"depth\":2},{\"id\":\"releasing-components\",\"text\":\"Releasing components\",\"depth\":2}],\"content\":\"DEVELOPING COMPONENTS\\n\\nThis chapter will describe how to develop component projects using the module\\nengineering solution.\\n\\n\\n# INITIALIZE THE PROJECT\\n\\n<CH.Spotlight>\\n\\nnpx @modern-js/create components-project\\n\\n? Please select the solution you want to create Module Solution\\n? Package Name components-demo\\n? Development Language TS\\n? Package Management Tool pnpm\\n\\n\\n--------------------------------------------------------------------------------\\n\\nIt is recommended to use the @modern-js/create command to initialize an npm\\nproject.\\n\\nnpx @modern-js/create components-project\\n\\n? Please select the solution you want to create Module Solution\\n? Package Name components-demo\\n? Development Language TS\\n? Package Management Tool pnpm\\n\\n\\n--------------------------------------------------------------------------------\\n\\nThe initialized directory structure.\\n\\n.\\n├── README.md\\n├── node_modules/\\n├── dist/\\n├── modern.config.ts\\n├── package.json\\n├── pnpm-lock.yaml\\n├── src\\n│ ├── index.ts\\n│ └── modern-app-env.d.ts\\n└── tsconfig.json\\n\\n\\n--------------------------------------------------------------------------------\\n\\nModify the . /src/index.ts file suffix and content.\\n\\nAt this point, a component project is initialized.\\n\\nexport default () => {\\n return <div>hello world</div>;\\n};\\n\\n\\n</CH.Spotlight>\\n\\n\\nDEBUGGING CODE WITH STORYBOOK\\n\\n<CH.Spotlight>\\n\\npnpm run new\\n\\n? Action Enable features\\n? Enable features Enable Visual Testing (Storybook)\\n\\n\\n--------------------------------------------------------------------------------\\n\\nExecute the new command in the project root directory to enable the Storybook\\nfeature.\\n\\npnpm run new\\n\\n? Action Enable features\\n? Enable features Enable Visual Testing (Storybook)\\n\\n\\n--------------------------------------------------------------------------------\\n\\nOnce successfully opened, you will see that a new dependency has been added to\\npackage.json. The stories directory and related initialization files are also\\ncreated.\\n\\n<CH.Code>\\n\\n{\\n \\\"name\\\": \\\"components-demo\\\",\\n \\\"devDependencies\\\": {\\n \\\"@modern-js/plugin-storybook\\\": \\\"x.y.z\\\",\\n \\\"@modern-js/runtime\\\": \\\"x.y.z\\\",\\n \\\"react\\\": \\\"^17\\\",\\n \\\"react-dom\\\": \\\"^17\\\"\\n }\\n}\\n\\n\\n.\\n├── src\\n│ ├── index.ts\\n│ └── modern-app-env.d.ts\\n├── stories\\n│ ├── .eslintrc.js\\n│ ├── index.stories.tsx\\n│ └── tsconfig.json\\n\\n\\n</CH.Code>\\n\\n--------------------------------------------------------------------------------\\n\\nAfter initialization, the tsconfig.json file in the . /stories directory, the\\ntsconfig.json file is set by default with the paths configuration of the same\\nname as the project.\\n\\n{\\n \\\"extends\\\": \\\"../tsconfig.json\\\",\\n \\\"compilerOptions\\\": {\\n \\\"baseUrl\\\": \\\"../\\\",\\n \\\"paths\\\": {\\n \\\"components-demo\\\": [\\\"./\\\"],\\n \\\"components-demo/*\\\": [\\\"./*\\\"]\\n }\\n },\\n \\\"include\\\": [\\\"**/*\\\"]\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nSuch a configuration allows you to introduce code in Story code directly using\\nthe name of the project.\\n\\n<CH.Code>\\n\\n\\n\\nexport const YourStory = () => <Component />;\\n\\nexport default {\\n title: 'Your Stories',\\n};\\n\\n\\n--------------------------------------------------------------------------------\\n\\nexport default () => {\\n return <div>hello world</div>;\\n};\\n\\n\\n</CH.Code>\\n\\n--------------------------------------------------------------------------------\\n\\nAt this point Storybook identifies the entry point for the imported code based\\non fields like main, exports in the project's package.json file. The location of\\nthe type file is determined by the types field.\\n\\n{\\n \\\"name\\\": \\\"components-demo\\\",\\n \\\"main\\\": \\\"./dist/esm/index.js\\\",\\n \\\"types\\\": \\\"./dist/types/index.d.ts\\\"\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nWhile importing source code for debugging is also supported, debugging using\\nproject artifacts is more reliable.\\n\\nDebugging with source code has a limitation: some configurations are not\\nequivalent in Storybook and in the original build support.\\n\\nThis is why debugging with the product is recommended.\\n\\n\\n\\nexport const YourStory = () => <Component />;\\n\\nexport default {\\n title: 'Your Stories',\\n};\\n\\n\\n</CH.Spotlight>\\n\\n\\nDEVELOPING STYLES\\n\\nNext we can add styles to the component.\\n\\nThe following capabilities are currently supported for developing styles.\\n\\n * CSS/PostCSS\\n * Less\\n * Scss/Sass\\n * Tailwind CSS\\n * CSS Modules\\n\\n\\nCSS/POSTCSS\\n\\nThe module project supports PostCSS and has the following built-in postcss\\nplugins.\\n\\n * flexbugs-fixes\\n * custom-properties\\n * initial\\n * page-break\\n * font-variant\\n * media-minmax\\n * nesting\\n\\nSo we can create .css files in our projects and use the syntax support and\\ncapabilities provided by these plugins directly in our css files.\\n\\n<CH.Spotlight>\\n\\na,\\nb {\\n color: red;\\n\\n /* \\\"&\\\" comes first */\\n & c,\\n & d {\\n color: white;\\n }\\n\\n /* \\\"&\\\" comes later, requiring \\\"@nest\\\" */\\n @nest e & {\\n color: yellow;\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nSource Code.\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\ncss product.\\n\\na,\\nb {\\n color: red;\\n}\\na c,\\nb c,\\na d,\\nb d {\\n color: white;\\n}\\ne a,\\ne b {\\n color: yellow;\\n}\\n\\n\\n</CH.Spotlight>\\n\\n\\nLESS\\n\\nModule projects support development styles using Less.\\n\\n> Currently supported version is 4.1.3\\n\\n<CH.Spotlight>\\n\\n@bg: black;\\n@bg-light: boolean(luma(@bg) > 50%);\\n\\ndiv {\\n background: @bg;\\n color: if(@bg-light, black, white);\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nSource Code.\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\nLess product.\\n\\ndiv {\\n background: black;\\n color: white;\\n}\\n\\n\\n</CH.Spotlight>\\n\\n\\nSASS/SCSS\\n\\nModule projects support developing styles using Scss/Sass.\\n\\n> Currently supported version is 1.54.4\\n\\n<CH.Spotlight>\\n\\n$font-stack: Helvetica, sans-serif;\\n$primary-color: #333;\\n\\nbody {\\n font: 100% $font-stack;\\n color: $primary-color;\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n源代码。\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\nLess product.\\n\\nbody {\\n font: 100% Helvetica, sans-serif;\\n color: #333;\\n}\\n\\n\\n</CH.Spotlight>\\n\\n\\nTAILWIND CSS\\n\\nThe module project supports the development of component styles using Tailwind\\nCSS.\\n\\nBy default, this feature is not enabled in the module project, you need to\\nenable it as follows.\\n\\n<CH.Spotlight>\\n\\npnpm run new\\n\\n? Action Enable features\\n? Enable features Enable Visual Testing (Storybook)\\n\\n\\n--------------------------------------------------------------------------------\\n\\nThe Tailwind CSS feature can be enabled by executing the new command in the\\nproject root directory.\\n\\npnpm run new\\n\\n? Action Enable features\\n? Enable features Enable Tailwind CSS\\n\\n\\n--------------------------------------------------------------------------------\\n\\nOnce successfully opened, you will see that a new dependency has been added to\\npackage.json.\\n\\n{\\n \\\"devDependencies\\\": {\\n \\\"@modern-js/plugin-tailwindcss\\\": \\\"x.y.z\\\"\\n }\\n}\\n\\n\\n</CH.Spotlight>\\n\\nTailwind CSS offers two ways to use it.\\n\\nHTML CLASS\\n\\n<CH.Spotlight>\\n\\nimport 'tailwindcss/utilities.css';\\n\\nexport default () => {\\n return <div className=\\\"bg-black text-white\\\">hello world</div>;\\n};\\n\\n\\n--------------------------------------------------------------------------------\\n\\nTailwind CSS supports adding styles to HTML tags by using class names.\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\n**When using HTML class names, be sure to import the Tailwind CSS equivalent css\\nfile. **\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\nStyle product.\\n\\n> This is a bundle build.\\n\\n/* ../../node_modules/.pnpm/tailwindcss@2.2.19/node_modules/tailwindcss/utilities.css */\\n.table {\\n display: table;\\n}\\n@keyframes spin {\\n to {\\n transform: rotate(360deg);\\n }\\n}\\n@keyframes ping {\\n 75%,\\n 100% {\\n transform: scale(2);\\n opacity: 0;\\n }\\n}\\n@keyframes pulse {\\n 50% {\\n opacity: 0.5;\\n }\\n}\\n@keyframes bounce {\\n 0%,\\n 100% {\\n transform: translateY(-25%);\\n animation-timing-function: cubic-bezier(0.8, 0, 1, 1);\\n }\\n 50% {\\n transform: none;\\n animation-timing-function: cubic-bezier(0, 0, 0.2, 1);\\n }\\n}\\n.bg-black {\\n --tw-bg-opacity: 1;\\n background-color: rgba(0, 0, 0, var(--tw-bg-opacity));\\n}\\n.text-white {\\n --tw-text-opacity: 1;\\n color: rgba(255, 255, 255, var(--tw-text-opacity));\\n}\\n*,\\n::before,\\n::after {\\n --tw-shadow: 0 0 #0000;\\n}\\n*,\\n::before,\\n::after {\\n --tw-ring-inset: var(--tw-empty);\\n --tw-ring-offset-width: 0px;\\n --tw-ring-offset-color: #fff;\\n --tw-ring-color: rgba(59, 130, 246, 0.5);\\n --tw-ring-offset-shadow: 0 0 #0000;\\n --tw-ring-shadow: 0 0 #0000;\\n}\\n@media (min-width: 640px) {\\n}\\n@media (min-width: 768px) {\\n}\\n@media (min-width: 1024px) {\\n}\\n@media (min-width: 1280px) {\\n}\\n@media (min-width: 1536px) {\\n}\\n\\n\\n</CH.Spotlight>\\n\\n@APPLY\\n\\nTailwind CSS provides the @apply directive, which allows us to inline the styles\\nprovided by Tailwind CSS into the styles we write.\\n\\n@apply can be used in CSS, Less, and Sass.\\n\\n.btn {\\n @apply font-bold py-2 px-4 rounded;\\n}\\n\\n\\nHowever, there are some things to keep in mind when using Less and Sass.\\n\\nSASS\\n\\nWhen using Tailwind with Sass, the presence of !important after @apply requires\\ninterpolation to get Sass to compile correctly.\\n\\n<CH.Spotlight>\\n\\n.alert {\\n @apply bg-red-500 !important;\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nIt does not work properly.\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\nCan work properly.\\n\\n.alert {\\n @apply bg-red-500 #{!important};\\n}\\n\\n\\n</CH.Spotlight>\\n\\nLESS\\n\\nWhen using Tailwind with Less, you cannot nest Tailwind's @screen directive.\\n\\n<CH.Spotlight>\\n\\n.card {\\n @apply rounded-none;\\n\\n @screen sm {\\n @apply rounded-lg;\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nIt does not work properly.\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\nInstead, use regular media queries and the theme() function to reference your\\nscreen size, or simply don't nest your @screen directive.\\n\\n<CH.Code>\\n\\n// Use a regular media query and theme()\\n.card {\\n @apply rounded-none;\\n\\n @media (min-width: theme('screens.sm')) {\\n @apply rounded-lg;\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n// Use the @screen directive at the top-level\\n.card {\\n @apply rounded-none;\\n\\n @media (min-width: theme('screens.sm')) {\\n @apply rounded-lg;\\n }\\n}\\n\\n\\n</CH.Code>\\n\\n</CH.Spotlight>\\n\\nRECOMMENDED METHOD\\n\\n**It is recommended to develop styles in the way specified by @apply, so that\\nonly styles inlined by directives are included in the style product. **\\n\\nWhen adding styles using HTML class names, by default Tailwind will not only add\\nthe styles corresponding to its own class name to the product, but will also\\nhave additional style code that may not affect its own styles.\\n\\nTHE DIFFERENCE BETWEEN BUNDLE AND BUNDLELESS BUILD PRODUCTS\\n\\nFor the following code, there is a big difference between the bundle and\\nbundleless modes of building products.\\n\\n> The so-called bundle and bundleless can be found in [[Bundle and\\n> Bundleless]](/en/guide/advance/in-depth-about-build#bundle- and-bundleless)\\n\\nimport 'tailwindcss/utilities.css';\\n\\nexport default () => {\\n return <div className=\\\"bg-black text-white\\\">hello world11</div>;\\n};\\n\\n\\nIn Bundle mode, third-party dependencies are packaged in.\\n\\nFor styles, a separate product file is generated, and there is no code related\\nto importing styles in the Js product file.\\n\\nIf you need to inject styles into Js products, you can enable the style.inject\\nAPI.\\n\\n<CH.Code>\\n\\n/* ../../node_modules/.pnpm/tailwindcss@2.2.19/node_modules/tailwindcss/utilities.css */\\n.table {\\n display: table;\\n}\\n@keyframes spin {\\n to {\\n transform: rotate(360deg);\\n }\\n}\\n@keyframes ping {\\n 75%, 100% {\\n transform: scale(2);\\n opacity: 0;\\n }\\n}\\n@keyframes pulse {\\n 50% {\\n opacity: .5;\\n }\\n}\\n@keyframes bounce {\\n 0%, 100% {\\n transform: translateY(-25%);\\n animation-timing-function: cubic-bezier(0.8, 0, 1, 1);\\n }\\n 50% {\\n transform: none;\\n animation-timing-function: cubic-bezier(0, 0, 0.2, 1);\\n }\\n}\\n.bg-black {\\n --tw-bg-opacity: 1;\\n background-color: rgba(0, 0, 0, var(--tw-bg-opacity));\\n}\\n.text-white {\\n --tw-text-opacity: 1;\\n color: rgba(255, 255, 255, var(--tw-text-opacity));\\n}\\n*,\\n::before,\\n::after {\\n --tw-shadow: 0 0 #0000 ;\\n}\\n*,\\n::before,\\n::after {\\n --tw-ring-inset: var(--tw-empty, );\\n --tw-ring-offset-width: 0px;\\n --tw-ring-offset-color: #fff;\\n --tw-ring-color: rgba(59, 130, 246, 0.5);\\n --tw-ring-offset-shadow: 0 0 #0000;\\n --tw-ring-shadow: 0 0 #0000 ;\\n}\\n@media (min-width: 640px) {\\n}\\n@media (min-width: 768px) {\\n}\\n@media (min-width: 1024px) {\\n}\\n@media (min-width: 1280px) {\\n}\\n@media (min-width: 1536px) {\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n// src/index.tsx\\n\\nvar src_default = () => {\\n return /* @__PURE__ */ jsx(\\\"div\\\", {\\n className: \\\"bg-black text-white\\\",\\n children: \\\"hello world11\\\"\\n });\\n};\\nexport {\\n src_default as default\\n};\\n\\n\\n</CH.Code>\\n\\nIn Bundleless mode, no third-party dependencies are packaged in, and no style\\nproducts are generated at this time.\\n\\n\\nimport 'tailwindcss/utilities.css';\\nvar src_default = () => {\\n return /* @__PURE__ */ jsx('div', {\\n className: 'bg-black text-white',\\n children: 'hello world11',\\n });\\n};\\nexport { src_default as default };\\n\\n\\n\\nCSS MODULES\\n\\nModule projects support the development of styles using CSS Modules. By default,\\nthe following files are recognized as CSS Module files.\\n\\n * .module.css\\n * .module.less\\n * .module.scss\\n * .module.sass\\n\\nIf you need to configure CSS Modules, you can check out the API at\\n\\n * autoModules\\n * modules\\n\\nThe following is a code example.\\n\\n<CH.Code>\\n\\n\\n\\nexport default () => {\\n return <div className={style.btn}>hello world</div>;\\n};\\n\\n\\n.btn {\\n color: blue;\\n}\\n\\n\\n</CH.Code>\\n\\n\\nCONFIGURING BUILD PRODUCTS\\n\\nBased on most scenarios of component project usage, it is recommended to use the\\nnpm-component build preset. This preset yields a product directory structure of\\n\\n.\\n├── dist\\n│ ├── es\\n│ ├── lib\\n│ └── types\\n\\n\\n * . /dist/es: Contains bundleless products in ES modules format that support\\n the es6 syntax.\\n * . /dist/lib: Contains bundleless products in CommonJS format with support for\\n es6 syntax.\\n * . /dist/types: Contains the types file.\\n\\nThe buildPreset can be configured manually if there is a requirement to use\\nsyntax support, and supports modifying the supported syntax by adding a suffix\\nto npm-component.\\n\\nexport default defineConfig({\\n buildPreset: 'npm-component-es2019',\\n});\\n\\n\\nIf you have special needs for the build product directory structure, you can use\\nthe buildConfig API, which can be used by the following documentation.\\n\\n * modify-output-product\\n * in-depth-about-build\\n\\n\\nTESTING COMPONENTS\\n\\nFor more information on how to test components, please refer to [Test project].\\n\\n\\nRELEASING COMPONENTS\\n\\nIt is recommended to use module project to provide version publishing function,\\nyou can refer to [Versioning and publishing].\",\"frontmatter\":{}},{\"title\":\"Quick start\",\"routePath\":\"/en/guide/intro/getting-started\",\"toc\":[{\"id\":\"3-minute-demo\",\"text\":\"3 minute demo\",\"depth\":2},{\"id\":\"lets-get-started\",\"text\":\"Let's get started\",\"depth\":2}],\"content\":\"QUICK START\\n\\n\\n3 MINUTE DEMO\\n\\nWant to experience Module Tools in action? The only prerequisite you need is\\nNode.js LTS and make sure your Node version is >= 14.17.6.\\n\\nFrom your shell, install the following dependencies in your project.\\n\\n * @modern-js/module-tools\\n * @modern-js/plugin-testing\\n\\n> If it's a TypeScript project, add the \\\"typescript\\\" dependency.\\n\\nnpm install -D @modern-js/module-tools @modern-js/plugin-testing\\n\\n\\n> For projects that use pnpm or the Yarn package manager, just replace npm. pnpm\\n> is recommended.\\n\\nThen add the command \\\"build\\\": \\\"modern build\\\" to your project's package.json\\nfile.\\n\\n{\\n \\\"scripts\\\": {\\n \\\"build\\\": \\\"modern build\\\"\\n }\\n}\\n\\n\\nIf your project has a src/index.(js|jsx) file or both src/index.(ts|tsx) and\\ntsconfig.json files, then congratulations you can run the npm run build command\\ndirectly to build your project with Module Tools.\\n\\nIf you want to see real projects that use the module engineering solution, you\\ncan execute the following command.\\n\\ngit clone https://github.com/modern-js-dev/module-tools-examples\\ncd module-tools-example\\n\\n## Execute the build.\\npnpm build\\n\\n## Execute the build in listening mode.\\npnpm build --watch\\n\\n## Start Storybook\\npnpm dev storybook\\n\\n## Test\\npnpm test\\npnpm test\\n\\n\\nIf you want to create a complete module project, you can execute the following\\ncommand:\\n\\nnpx @modern-js/create your-project-dir-name\\n\\n\\nNext, in the issue interaction, follow the options below.\\n\\n? Please select the type of project you want to create Module\\n? Please fill in the project name library\\n? Please select the development language TS\\n? Please select the package management tool pnpm\\n\\n\\n> The project name is the value of the \\\"name\\\" field in package.json.\\n\\nThen the process of initializing the project will start. After the project\\ndirectory and files are generated and the dependencies are installed, a complete\\nmodule project is created.\\n\\nWe can start the project build directly with the pnpm build command, and start\\nthe build in watching mode with the pnpm build --watch command.\\n\\n\\nLET'S GET STARTED\\n\\nChoose your tutorial scenario...\\n\\n * I'm a beginner and need to learn basic usage of Module Tools.\\n * I have learned the basic usage of Module Tools and can learn advanced usage\\n of Module Tools.\\n * I am the maintainer of the project and need to learn how to develop plugins\\n for Module Tools and learn more about Module Tools Advanced.\",\"frontmatter\":{\"sidebar_position\":3}},{\"title\":\"Welcome to Module Tools\",\"routePath\":\"/en/guide/intro/welcome\",\"toc\":[],\"content\":\"WELCOME TO MODULE TOOLS\\n\\nModule Tools is a modules engineering solution for Modern.js, as well as a core\\ndependency. It allows developers to build, debug, and publish module type\\nproject more easily. A module type project can mostly be thought of as an npm\\npackage type project, which may be a component, component library or tool\\nlibrary project.\\n\\nIf you are planning to develop a project of the npm package type, then you came\\nto the right place! Modern.js provides a professional module engineering\\nsolution. It gives you:\\n\\n * Simple project initialization: simply execute the npx @modern-js/create\\n project-dir command, followed by a few interactive questions, to create a\\n complete module type project. The created project also supports the choice of\\n two package managers, pnpm and Yarn.\\n * Code formatting: In a module project, you can execute modern lint to format\\n the code. The initialized module project includes the ESLint ruleset for\\n Modern.js for most scenarios.\\n * Comprehensive build capabilities and faster builds: Module Tools provides\\n high-performance build capabilities based on esbuild and SWC, and provides\\n rich configurations for different build scenarios.\\n * Storybook debugging tools: Module Tools provides Storybook debugging tools\\n for debugging module projects. After installing the Storybook plugin for\\n Module Tools, you can start it with the modern dev storybook command. You can\\n use Storybook not only for debugging components, but also for other types of\\n modules.\\n * Testing capabilities with Jest: When you need to test a module, you can use\\n the modern test command of Module Tools, which not only integrates with Jest,\\n but also provides an API for configuring Jest.\\n * Versioning based on Changesets: When you need to record changes to a project,\\n you can use the modern change command to generate a Markdown file containing\\n the changes; when you need to upgrade a project, you can use the modern bump\\n command to analyze and upgrade the version through the Markdown file; when\\n you need to release a project, you can use the modern release command to\\n release the project; Module Tools implements these commands based on\\n Changesets.\\n * Extensible plug-in mechanism: Want to integrate additional debugging tools\\n for your project? Or maybe you want to do some extra processing during the\\n build process, Module Tools provides a plugin mechanism and plugin hooks that\\n cover both the dev command and the build command process. You can use them to\\n extend the capabilities of your project.\\n * Lots more! Module Tools will continue to optimize its build and debug\\n features in the future. If there are important issues to be solved in module\\n project building, or if a mainstream module project debugging tool or pattern\\n emerges, then they will probably be supported by Module Tools.\",\"frontmatter\":{\"sidebar_position\":1}},{\"title\":\"Why module project solution\",\"routePath\":\"/en/guide/intro/why-module-engineering-solution\",\"toc\":[],\"content\":\"WHY MODULE PROJECT SOLUTION\\n\\nYou've probably all experienced it: when developing a component library or tool\\nlibrary from scratch, we have to consider not only how to write the code logic\\nof the project itself, but also how to build, debug, test, format the code, and\\nother things that have nothing to do with the code logic.\\n\\nFor example, when we consider which builder is used to build the code for a\\nmodule project, we might previously consider webpack or Rollup, but now we might\\nalso consider esbuild or SWC.\\n\\nRegardless of which builder is chosen, this is going to be a costly learning\\ncurve for developers who are not skilled in the use of these build tools. Even\\nif you want to use them quickly, it will take a lot of time and effort.\\n\\nIn addition to the build, things like providing debugging tools for projects,\\nsupporting testing capabilities, adding code format validation, etc. can take a\\nlong time and effort for a novice to understand or master them and actually\\nserve the current project.\\n\\nTo ensure the quality of the code and the integrity of the project, we often\\nneed to do these things that are not related to the logical implementation of\\nthe code. However, these things are likely to affect the overall project\\ndevelopment progress, reduce the developer's development experience, and make\\nthe developer feel that the development threshold of the module project is very\\nhigh.\\n\\nIf you have to go through all this work every time you develop a module type\\nproject, you will spend most of your development time in the beginning on these\\nthings that are not related to code implementation. If we could provide a module\\nengineering solution that would help developers to solve the project engineering\\nissues and allow them to focus more on code implementation, it would greatly\\nimprove the module type project development experience.\\n\\n\\n\\nModern.js, in order to make developing module type projects easier, provides a\\nmodule engineering solution in order to solve the above mentioned problems and\\nprovides the main features using Module Tools. Module-tools can be understood as\\na tool dedicated to the development of module type projects.\",\"frontmatter\":{\"sidebar_position\":2}},{\"title\":\"index\",\"routePath\":\"/en/\",\"toc\":[],\"content\":\"INDEX\",\"frontmatter\":{\"pageType\":\"home\",\"hero\":{\"name\":\"Module tools\",\"text\":\"Module engineering solutions\",\"tagline\":\"simple, powerful, high-performance modern npm package development solution\",\"actions\":[{\"theme\":\"brand\",\"text\":\"welcome\",\"link\":\"/guide/intro/welcome\"}]},\"features\":[{\"title\":\"Esbuild: The High Performance JS Bundler\",\"details\":\"Built on Esbuild, the build is extremely fast and gives you the ultimate development experience.\",\"icon\":\"🚀\"},{\"title\":\"Storybook: The community popular UI development tool\",\"details\":\"Integrated with Storybook, you can use it to debug UI.\",\"icon\":\"📦\"},{\"title\":\"transform + bundle\",\"details\":\"Both bundle and bundleless build modes are supported.\",\"icon\":\"✨\"},{\"title\":\"zero configuration\",\"details\":\"Develop your npm packages without any configuration, with built-in presets covering multiple scenarios.\",\"icon\":\"🛠️\"},{\"title\":\"Extensible: Provides a powerful plugin mechanism\",\"details\":\"With its plugin extension mechanism, you can easily extend the capabilities of Module tools.\",\"icon\":\"🎨\"}]}},{\"title\":\"Quick Start\",\"routePath\":\"/en/plugins/guide/getting-started\",\"toc\":[],\"content\":\"QUICK START\\n\\nModule engineering solution not only provides a rich set of features, but also\\nsupports extending the capabilities of the current project by way of plugins.\\n\\nWe can quickly see how to write a module-tools plugin by using the following\\nexample.\\n\\n<CH.Spotlight>\\n\\n. /project .\\n├── plugins\\n│ └── example.ts\\n├── src/\\n└── modern.config.ts\\n\\n\\n--------------------------------------------------------------------------------\\n\\nFirst we create . /plugins/example.ts file under the initialized project.\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\nNext add the code for the plugin to the example.ts file.\\n\\n\\n\\nexport const ExamplePlugin = (): CliPlugin<ModuleTools> => {\\n return {\\n name: 'example',\\n setup() {\\n console.info('this is example plugin');\\n return {\\n // use hooks\\n afterBuild() {\\n console.info('build over');\\n }\\n };\\n };\\n };\\n};\\n\\n\\n--------------------------------------------------------------------------------\\n\\nThen we register the plugin we just wrote via the plugins API.\\n\\n\\nexport default defineConfig({\\n plugins: [ExamplePlugin()],\\n});\\n\\n\\n--------------------------------------------------------------------------------\\n\\nFinally, run modern build and you will see.\\n\\nThis is example plugin\\nBuild succeed: 510.684ms\\nbuild over\\n\\n\\n</CH.Spotlight>\\n\\nWith the above example, we learned the following things.\\n\\n * The recommended plugin directory structure\\n * The initialization code of the plugin\\n * Plugin registration\\n\\nIn addition to the above, we also need to understand.\\n\\n * plugin objects, type definitions and recommended configuration items\\n * setup functions, api object parameters, lifecycle hooks\",\"frontmatter\":{\"sidebar_position\":1}},{\"title\":\"Plugin Object\",\"routePath\":\"/en/plugins/guide/plugin-object\",\"toc\":[{\"id\":\"plugin-type-definitions\",\"text\":\"Plugin type definitions\",\"depth\":2},{\"id\":\"plugin-configuration-items\",\"text\":\"Plugin configuration items\",\"depth\":2}],\"content\":\"PLUGIN OBJECT\\n\\nThe module-tools plugin is an object, and the object contains the following\\nproperties.\\n\\n * name: The name of the plugin, a unique identifier.\\n * setup: plugin initialization function, which will be executed only once.\\n setup function can return a Hooks object, and module-tools will execute the\\n function corresponding to the Hook defined on the Hooks object at a specific\\n time.\\n\\nFor example, in the following plugin code example, the beforeBuild function is\\ntriggered before the project starts the build task and the build start log is\\nprinted.\\n\\n<CH.Code>\\n\\n\\n\\nconst MyPlugin: CliPlugin<ModuleTools> = {\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n // this is hook\\n beforeBuild: () => {\\n console.info('build start');\\n },\\n };\\n },\\n};\\n\\n\\n--------------------------------------------------------------------------------\\n\\n\\nexport default {\\n plugins: [MyPlugin()],\\n};\\n\\n\\n</CH.Code>\\n\\n\\nPLUGIN TYPE DEFINITIONS\\n\\nWhen using TypeScript, you can introduce the built-in CliPlugin and ModuleTools\\ntypes to provide the correct type derivation for plugins: ``\\n\\n\\n\\nconst MyPlugin: CliPlugin<ModuleTools> = {\\n name: 'my-plugin',\\n\\n setup() {\\n const foo = '1';\\n\\n return {\\n // this is hook\\n afterBuild: () => {\\n //...\\n },\\n };\\n },\\n};\\n\\n\\n\\nPLUGIN CONFIGURATION ITEMS\\n\\nIt is recommended to write the plugin as a function, so that the plugin can\\nreceive configuration items via function entry.\\n\\n\\n\\ntype MyPluginOptions = {\\n foo: string;\\n};\\n\\nconst MyPlugin = (options: MyPluginOptions): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n console.log(options.foo);\\n },\\n});\\n\",\"frontmatter\":{\"sidebar_position\":2}},{\"title\":\"Setup function\",\"routePath\":\"/en/plugins/guide/setup-function\",\"toc\":[{\"id\":\"plugin-api-objects\",\"text\":\"Plugin API objects\",\"depth\":2},{\"id\":\"apiuseappcontext\",\"text\":\"api.useAppContext\",\"depth\":3},{\"id\":\"apiuseresolvedconfigcontext\",\"text\":\"api.useResolvedConfigContext\",\"depth\":3},{\"id\":\"apiusehookrunners\",\"text\":\"api.useHookRunners\",\"depth\":3},{\"id\":\"asynchronous-setup\",\"text\":\"Asynchronous setup\",\"depth\":2},{\"id\":\"life-cycle-hooks\",\"text\":\"Life cycle hooks\",\"depth\":2}],\"content\":\"SETUP FUNCTION\\n\\nIn the [Plugin object] section we know that the plug-in object contains a setup\\nfunction that not only contains an api object parameter, but also returns a\\nHooks object.\\n\\n\\nPLUGIN API OBJECTS\\n\\nThe setup function of the plugin will provide an api object parameter, and you\\ncan call some of the methods provided on this object to get information about\\nthe configuration, project context, etc.\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup(api) {\\n // Get the original configuration of the application\\n const config = api.useConfigContext();\\n // Get the application runtime context\\n const appContext = api.useAppContext();\\n // Get the final configuration after resolving\\n const resolvedConfig = api.useResolvedConfigContext();\\n },\\n});\\n\\n\\n\\nAPI.USEAPPCONTEXT\\n\\nUsed to get project context information.\\n\\nconst useAppContext: () => IAppContext;\\n\\ninterface IAppContext {\\n appDirectory: string;\\n configFile: string | false;\\n packageName: string;\\n nodeModulesDirectory: string;\\n internalDirectory: string;\\n plugins: {\\n cli?: any;\\n server?: any;\\n }[];\\n}\\n\\n\\nWe can see through the actual type file that there are other fields, but the\\nonly ones that make sense for the module project at the moment are the above.\\napi object other methods are the same.\\n\\n\\nAPI.USERESOLVEDCONFIGCONTEXT\\n\\nUsed to get the final configuration after parsing.\\n\\nIf you need to get the build-related final configuration, you need to use the\\nbeforeBuild Hook.\\n\\nconst useResolvedConfigContext: () => NormalizedConfig;\\n\\ninterface NormalizedConfig {\\n buildConfig: PartialBuildConfig;\\n buildPreset: BuildPreset;\\n designSystem?: Record<string, any>;\\n dev: Dev;\\n plugins: PluginConfig;\\n runtime: RuntimeConfig;\\n runtimeByEntries?: RuntimeByEntriesConfig;\\n _raw: UserConfig;\\n}\\n\\n\\n\\nAPI.USEHOOKRUNNERS\\n\\nUsed to get the executors of Hooks and trigger the execution of a specific Hook.\\n\\n\\n\\nexport default (): CliPlugin => ({\\n name: 'my-plugin',\\n\\n async setup(api) {\\n const hookRunners = api.useHookRunners();\\n // trigger the afterBuild Hook\\n await hookRunners.afterBuild();\\n },\\n});\\n\\n\\n\\nASYNCHRONOUS SETUP\\n\\nThe setup of a CLI plugin can be an asynchronous function that performs\\nasynchronous logic during the initialization process.\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n async setup(api) {\\n await doSomething();\\n },\\n});\\n\\n\\n\\nLIFE CYCLE HOOKS\\n\\nWe know that the setup function returns a Hooks object, which can also be\\nunderstood as an object with module-tools lifecycle hooks.\\n\\nCurrently there are two main types of hooks.\\n\\n * build hooks: triggered only when the build command is executed to build the\\n source code product.\\n * buildPlatform hook: triggered only when the build --platform command is\\n executed to generate other build products.\\n * debug hooks: hooks that are triggered when running the dev command.\\n\\nSee the API documentation for a full list of lifecycle hooks.\",\"frontmatter\":{\"sidebar_position\":3}},{\"title\":\"Overview\",\"routePath\":\"/en/plugins/official-list/overview\",\"toc\":[{\"id\":\"official-plugin\",\"text\":\"Official Plugin\",\"depth\":2}],\"content\":\"OVERVIEW\\n\\n\\nOFFICIAL PLUGIN\\n\\n(Under Building)\",\"frontmatter\":{}},{\"title\":\"BuildConfig\",\"routePath\":\"/api/config/build-config\",\"toc\":[{\"id\":\"alias-1\",\"text\":\"alias\",\"depth\":2},{\"id\":\"asset-1\",\"text\":\"asset\",\"depth\":2},{\"id\":\"path-1\",\"text\":\"path\",\"depth\":3},{\"id\":\"limit-1\",\"text\":\"limit\",\"depth\":3},{\"id\":\"publicpath-1\",\"text\":\"publicPath\",\"depth\":3},{\"id\":\"svgr-2\",\"text\":\"svgr\",\"depth\":3},{\"id\":\"include-1\",\"text\":\"include\",\"depth\":4},{\"id\":\"exclude-1\",\"text\":\"exclude\",\"depth\":4},{\"id\":\"autoexternal-1\",\"text\":\"autoExternal\",\"depth\":2},{\"id\":\"dependencies-1\",\"text\":\"dependencies\",\"depth\":3},{\"id\":\"peerdependencies-2\",\"text\":\"peerDependencies\",\"depth\":3},{\"id\":\"buildtype-1\",\"text\":\"buildType\",\"depth\":2},{\"id\":\"copy-1\",\"text\":\"copy\",\"depth\":2},{\"id\":\"copypatterns\",\"text\":\"copy.patterns\",\"depth\":3},{\"id\":\"copyoptions\",\"text\":\"copy.options\",\"depth\":3},{\"id\":\"define-1\",\"text\":\"define\",\"depth\":2},{\"id\":\"dts-1\",\"text\":\"dts\",\"depth\":2},{\"id\":\"tsconfigpath-1\",\"text\":\"tsconfigPath\",\"depth\":3},{\"id\":\"distpath-1\",\"text\":\"distPath\",\"depth\":3},{\"id\":\"only-1\",\"text\":\"only\",\"depth\":3},{\"id\":\"externals-1\",\"text\":\"externals\",\"depth\":2},{\"id\":\"format-1\",\"text\":\"format\",\"depth\":2},{\"id\":\"input-1\",\"text\":\"input\",\"depth\":2},{\"id\":\"jsx-1\",\"text\":\"jsx\",\"depth\":2},{\"id\":\"minify-1\",\"text\":\"minify\",\"depth\":2},{\"id\":\"outdir-1\",\"text\":\"outDir\",\"depth\":2},{\"id\":\"platform-1\",\"text\":\"platform\",\"depth\":2},{\"id\":\"sourcedir-2\",\"text\":\"sourceDir\",\"depth\":2},{\"id\":\"sourcemap-1\",\"text\":\"sourceMap\",\"depth\":2},{\"id\":\"splitting-1\",\"text\":\"splitting\",\"depth\":2},{\"id\":\"style-1\",\"text\":\"style\",\"depth\":2},{\"id\":\"less-2\",\"text\":\"less\",\"depth\":3},{\"id\":\"lessoptions-1\",\"text\":\"lessOptions\",\"depth\":4},{\"id\":\"additionaldata-2\",\"text\":\"additionalData\",\"depth\":4},{\"id\":\"implementation-2\",\"text\":\"implementation\",\"depth\":4},{\"id\":\"sass-1\",\"text\":\"sass\",\"depth\":3},{\"id\":\"sassoptions-1\",\"text\":\"sassOptions\",\"depth\":4},{\"id\":\"additionaldata-3\",\"text\":\"additionalData\",\"depth\":4},{\"id\":\"implementation-3\",\"text\":\"implementation\",\"depth\":4},{\"id\":\"postcss-1\",\"text\":\"postcss\",\"depth\":3},{\"id\":\"inject-1\",\"text\":\"inject\",\"depth\":3},{\"id\":\"automodules-1\",\"text\":\"autoModules\",\"depth\":3},{\"id\":\"modules-1\",\"text\":\"modules\",\"depth\":3},{\"id\":\"tailwindcss-2\",\"text\":\"tailwindcss\",\"depth\":3},{\"id\":\"target-1\",\"text\":\"target\",\"depth\":2},{\"id\":\"umdglobals-1\",\"text\":\"umdGlobals\",\"depth\":2},{\"id\":\"umdmodulename-1\",\"text\":\"umdModuleName\",\"depth\":2}],\"content\":\"BUILDCONFIG\\n\\n本章节描述了 Module tools 关于构建的所有配置\\n\\n\\nALIAS\\n\\n * 类型:Record<string, string | string[]> | Function\\n * 默认值:{'@': 'src',}\\n\\n对于 TypeScript 项目,只需要在 tsconfig.json 中配置 compilerOptions.paths, Module tools\\n会自动识别 tsconfig.json 里的别名,因此不需要额外配置 alias 字段。\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n alias: {\\n '@common': './src/common',\\n },\\n },\\n});\\n\\n\\n以上配置完成后,如果在代码中引用 @common/Foo.tsx, 则会映射到 <root>/src/common/Foo.tsx 路径上。\\n\\nalias 的值定义为函数时,可以接受预设的 alias 对象,并对其进行修改。\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n alias: alias => {\\n alias['@common'] = './src/common';\\n },\\n },\\n});\\n\\n\\n也可以在函数中返回一个新对象作为最终结果,新对象会覆盖预设的 alias 对象。\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n alias: alias => {\\n return {\\n '@common': './src/common',\\n };\\n },\\n },\\n});\\n\\n\\n\\nASSET\\n\\n\\nPATH\\n\\n静态资源输出路径,会基于 outDir 进行输出。\\n\\n * 类型: string\\n * 默认值: assets\\n\\n\\nLIMIT\\n\\n打包时自动内联静态资源的阈值,小于 10KB 的资源会被自动内联进 bundle 产物中。\\n\\n * 类型: number\\n * 默认值: 10 * 1024\\n\\n\\nPUBLICPATH\\n\\n打包时给未内联资源的 CDN 前缀。\\n\\n * 类型: string\\n * 默认值: undefined\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n asset: {\\n publicPath: 'https://xxx/',\\n },\\n },\\n});\\n\\n\\n此时,所有静态资源都会添加 https://xxx/ 前缀。\\n\\n\\nSVGR\\n\\n打包时将 svg 作为一个 React 组件处理,options 参考 svgr,另外还支持了 include 和 exclude\\n两个配置项,用于匹配需要处理的 svg 文件。\\n\\n * 类型: boolean | Object\\n * 默认值: false\\n\\n开启svgr后,仍然使用default export导出svg,所以你只能导入默认值。\\n\\n// true\\n\\n\\n// false\\n\\n\\n\\nINCLUDE\\n\\n设定匹配的 svg 文件\\n\\n * 类型: string | RegExp | (string | RegExp)[]\\n * 默认值: /\\\\.svg$/\\n\\nEXCLUDE\\n\\n设定不匹配的 svg 文件\\n\\n * 类型: string | RegExp | (string | RegExp)[]\\n * 默认值: undefined\\n\\n\\nAUTOEXTERNAL\\n\\n自动外置项目的 \\\"dependencies\\\" 和 \\\"peerDependencies\\\",不会将其打包到最终的 bundle 产物中。\\n\\n * 类型: boolean | Object\\n * 默认值: true\\n\\n\\nDEPENDENCIES\\n\\n是否需要外置项目的 \\\"dependencies\\\" 依赖。\\n\\n * 类型: boolean\\n * 默认值: true\\n\\n\\nPEERDEPENDENCIES\\n\\n是否需要外置项目的 \\\"peerDependencies\\\" 依赖。\\n\\n * 类型: boolean\\n * 默认值: true\\n\\n\\nBUILDTYPE\\n\\n构建类型,bundle 会打包你的代码,bundleless 只做代码的转换。\\n\\n * 类型: 'bundle' | 'bundleless'\\n * 默认值: bundle\\n\\n\\nCOPY\\n\\n将文件或目录拷贝到指定位置。\\n\\n * 类型: Object\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n copy: {\\n patterns: [{ from: './src/assets', to: '' }],\\n },\\n },\\n});\\n\\n\\n\\nCOPY.PATTERNS\\n\\n * 类型: CopyPattern[]\\n * 默认值: []\\n\\nexport interface CopyPattern {\\n from: string;\\n to?: string;\\n context?: string;\\n globOptions?: globby.GlobbyOptions;\\n}\\n\\n\\n\\nCOPY.OPTIONS\\n\\n * 类型: Object\\n * 默认值: { concurrency: 100, enableCopySync: false }\\n\\ntype Options = {\\n concurrency?: number;\\n enableCopySync?: boolean;\\n};\\n\\n\\n * concurrency: 指定并行执行多少个复制任务。\\n * enableCopySync: 使用 fs.copySync,默认情况下 fs.copy。\\n\\n\\nDEFINE\\n\\n定义全局变量,会被注入到代码中\\n\\n * 类型: Record<string, string>\\n * 默认值: {}\\n\\n由于 define 功能是由全局文本替换实现的,所以需要保证全局变量值为字符串,更为安全的做法是将每个全局变量的值转化为字符串,使用\\nJSON.stringify 进行转换,如下所示:\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n define: {\\n VERSION: JSON.stringify('1.0'),\\n },\\n },\\n});\\n\\n\\n为了防止全局替换替换过度,建议使用时遵循以下两个原则:\\n\\n * 全局常量使用大写\\n * 自定义全局常量前缀后缀,确保独一无二\\n\\n\\nDTS\\n\\n类型文件生成的相关配置,默认会生成。\\n\\n * 类型: false | Object\\n * 默认值: {}\\n\\n\\nTSCONFIGPATH\\n\\nTypeScript 配置文件的路径。\\n\\n * 类型: string\\n * 默认值: ./tsconfig.json\\n\\n\\nDISTPATH\\n\\n类型文件的输出路径,基于 outDir 进行输出。\\n\\n * 类型: string\\n * 默认值: ./types\\n\\n\\nONLY\\n\\n只生成类型文件,不生成 js 文件。\\n\\n * 类型: boolean\\n * 默认值: false\\n\\n\\nEXTERNALS\\n\\n配置外部依赖,不会被打包到最终的 bundle 中。\\n\\n * 类型: (string | RegExp)[]\\n * 默认值: []\\n\\n\\nFORMAT\\n\\njs 产物输出的格式,其中 iife 和 umd 只能在 buildType 为 bundle 时生效。\\n\\n * 类型: 'esm' | 'cjs' | 'iife' | 'umd'\\n * 默认值: cjs\\n\\n\\nINPUT\\n\\n指定构建的入口文件,数组形式可以指定目录。\\n\\n * 类型: string[] | Record<string, string>\\n * 默认值: bundle 模式下默认为 ['src/index.ts'],bundleless 模式下默认为 ['src']\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n input: ['src/index.ts', 'src/index2.ts'],\\n },\\n});\\n\\n\\n\\nJSX\\n\\n指定 jsx 的编译方式, 默认支持 React17 以上,自动注入 jsx 运行时代码。\\n\\n * 类型: automatic | classic\\n * 默认值: automatic\\n\\n\\nMINIFY\\n\\n使用 esbuild 或者 terser 压缩代码,也可以传入 terserOptions。\\n\\n * 类型: 'terser' | 'esbuild' | false | Object\\n * 默认值: false\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n minify: {\\n compress: {\\n drop_console: true,\\n },\\n },\\n },\\n});\\n\\n\\n\\nOUTDIR\\n\\n指定构建的输出目录\\n\\n * 类型: string\\n * 默认值: dist\\n\\n\\nPLATFORM\\n\\n默认生成用于 Node.js 环境下的代码,你也可以指定为 browser,会生成用于浏览器环境的代码。\\n\\n * 类型: 'browser' | 'node'\\n * 默认值: node\\n\\n\\nSOURCEDIR\\n\\n指定构建的源码目录,默认为 src,用于在 bundleless 构建时基于源码目录结构生成对应的产物目录。\\n\\n * 类型: string\\n * 默认值: src\\n\\n\\nSOURCEMAP\\n\\n控制 sourceMap 如何生成。\\n\\n * 类型: boolean | 'inline' | 'external'\\n * 默认值: false\\n\\n\\nSPLITTING\\n\\n是否开启代码分割。\\n\\n * 类型: boolean\\n * 默认值: false\\n\\n\\nSTYLE\\n\\n配置样式相关的配置。\\n\\n\\nLESS\\n\\nless 相关配置。\\n\\nLESSOPTIONS\\n\\n详细配置参考 less。\\n\\n * 类型: Object\\n * 默认值: { javascriptEnabled: true }\\n\\nADDITIONALDATA\\n\\n在入口文件起始添加 Less 代码。\\n\\n * 类型: string\\n * 默认值: undefined\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n style: {\\n less: {\\n additionalData: `@base-color: #c6538c;`,\\n },\\n },\\n },\\n});\\n\\n\\nIMPLEMENTATION\\n\\n配置 Less 使用的实现库,在不指定的情况下,使用的内置版本是 4.1.3。\\n\\n * 类型: string | Object\\n * 默认值: undefined\\n\\nObject 类型时,指定 Less 的实现库\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n style: {\\n less: {\\n implementation: require('less'),\\n },\\n },\\n },\\n});\\n\\n\\nstring 类型时,指定 Less 的实现库的路径\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n style: {\\n less: {\\n implementation: require.resolve('less'),\\n },\\n },\\n },\\n});\\n\\n\\n\\nSASS\\n\\nSass 相关配置。\\n\\nSASSOPTIONS\\n\\n详细配置参考 node-sass\\n\\n * 类型: Object\\n * 默认值: {}\\n\\nADDITIONALDATA\\n\\n在入口文件起始添加 Sass 代码。\\n\\n * 类型: string | Function\\n * 默认值: undefined\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n style: {\\n sass: {\\n additionalData: `$base-color: #c6538c;\\n $border-dark: rgba($base-color, 0.88);`,\\n },\\n },\\n },\\n});\\n\\n\\nIMPLEMENTATION\\n\\n配置 Sass 使用的实现库,在不指定的情况下,使用的内置版本是 1.5.4。\\n\\n * 类型: string | Object\\n * 默认值: undefined\\n\\nObject 类型时,指定 Sass 的实现库\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n style: {\\n sass: {\\n implementation: require('sass'),\\n },\\n },\\n },\\n});\\n\\n\\nstring 类型时,指定 Sass 的实现库的路径\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n style: {\\n sass: {\\n implementation: require.resolve('sass'),\\n },\\n },\\n },\\n});\\n\\n\\n\\nPOSTCSS\\n\\n * plugins\\n * processOptions\\n\\n详细配置查看 postcss。\\n\\n\\nINJECT\\n\\n配置打包模式下是否将 style 插入到 js 中\\n\\n * 类型: boolean\\n * 默认值: false\\n\\n\\nAUTOMODULES\\n\\n根据文件名自动启用 CSS Modules。\\n\\n * 类型: boolean | RegExp\\n * 默认值: true\\n\\ntrue : 为以 .module.css .module.less .module.scss .module.sass 文件名结尾的样式文件启用 CSS\\nModules。\\n\\nfalse : 禁用 CSS Modules.\\n\\nRegExp : 为匹配正则条件的所有文件启用 CSS Modules.\\n\\n\\nMODULES\\n\\nCSS Modules 配置\\n\\n * 类型: Object\\n * 默认值: {}\\n\\n一个常用的配置是 localsConvention,它可以改变 CSS Modules 的类名生成规则。\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n style: {\\n modules: {\\n localsConvention: 'camelCaseOnly',\\n },\\n },\\n },\\n});\\n\\n\\n对于以下样式:\\n\\n.box-title {\\n color: red;\\n}\\n\\n\\n你可以使用 styles.boxTitle 来访问\\n\\n详细配置查看 postcss-modules\\n\\n\\nTAILWINDCSS\\n\\nTailwind CSS 相关配置。\\n\\n * 类型: Object | Function\\n * 默认值: 见下方配置详情\\n\\nconst tailwind = {\\n content: [\\n './config/html/**/*.html',\\n './config/html/**/*.ejs',\\n './config/html/**/*.hbs',\\n './src/**/*.js',\\n './src/**/*.jsx',\\n './src/**/*.ts',\\n './src/**/*.tsx',\\n './storybook/**/*',\\n ],\\n};\\n\\n\\n值为 Object 类型时,与默认配置通过 Object.assign 合并。\\n\\n值为 Function 类型时,函数返回的对象与默认配置通过 Object.assign 合并。\\n\\n不允许出现 theme 属性,否则会构建失败, 使用 designSystem 作为 Tailwind CSS Theme 配置。\\n\\n其他的使用方式和 Tailwind CSS 一致: 快速传送门。\\n\\n\\nTARGET\\n\\n指定构建的目标环境\\n\\n * 类型: 'es5' | 'es6' | 'es2015' | 'es2016' | 'es2017' | 'es2018' | 'es2019' |\\n 'es2020' | 'es2021' | 'es2022' | 'esnext'\\n * 默认值: 'es2015'\\n\\n\\nUMDGLOBALS\\n\\n指定 UMD 产物外部导入的全局变量。\\n\\n * 类型: Record<string, string>\\n * 默认值: {}\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n umdGlobals: {\\n react: 'React',\\n 'react-dom': 'ReactDOM',\\n },\\n },\\n});\\n\\n\\n此时,react 和 react-dom 会被看做是外部导入的全局变量,不会被打包进 UMD 产物中,而是通过 global.React 和\\nglobal.ReactDOM 的方式进行访问。\\n\\n\\nUMDMODULENAME\\n\\n指定 UMD 产物的模块名。\\n\\n * 类型: string | Function\\n * 默认值: name => name\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n format: 'umd',\\n umdModuleName: 'myLib',\\n },\\n});\\n\\n\\n此时 UMD 产物会去挂载到 global.myLib 上。\\n\\n * 需要遵守 UMD 规范,UMD 产物的模块名不能和全局变量名冲突\\n * 模块名不能含有 -,@,/ 等特殊字符\\n\\n同时函数形式可以接收一个参数,为当前打包文件的输出路径\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n format: 'umd',\\n umdModuleName: path => {\\n if (path.includes('index')) {\\n return 'myLib';\\n } else {\\n return 'myLib2';\\n }\\n },\\n },\\n});\\n\",\"frontmatter\":{\"sidebar_position\":1}},{\"title\":\"BuildPreset\",\"routePath\":\"/api/config/build-preset\",\"toc\":[{\"id\":\"string-1\",\"text\":\"string\",\"depth\":2},{\"id\":\"npm-library-1\",\"text\":\"'npm-library'\",\"depth\":3},{\"id\":\"npm-library-with-umd-1\",\"text\":\"'npm-library-with-umd'\",\"depth\":3},{\"id\":\"npm-component-1\",\"text\":\"'npm-component'\",\"depth\":3},{\"id\":\"npm-component-with-umd-1\",\"text\":\"'npm-component-with-umd'\",\"depth\":3},{\"id\":\"关于预设值支持的-ecmascript-版本以及-es5esnext\",\"text\":\"关于预设值支持的 ECMAScript 版本以及 {es5...esnext}\",\"depth\":3},{\"id\":\"function-1\",\"text\":\"Function\",\"depth\":2}],\"content\":\"BUILDPRESET\\n\\n构建的预设字符串或者预设函数。提供开箱即用的构建配置。\\n\\n * type: string | Function\\n * default: undefined\\n\\n\\nSTRING\\n\\n字符串的形式可以让你直接使用内置的预设。\\n\\n\\n\\nexport default defineConfig({\\n buildPreset: 'npm-library',\\n});\\n\\n\\n\\n'NPM-LIBRARY'\\n\\n在类 NPM 包管理器下使用的 Library 通用模式,包含 esm 和 cjs 两种 Bundle 产物,并且包含一份类型文件。\\n\\n关于类 NPM 包管理器\\n\\n * npm\\n * yarn\\n * pnpm\\n\\n{\\n \\\"main\\\": \\\"./dist/lib/index.js\\\",\\n \\\"module\\\": \\\"./dist/es/index.js\\\",\\n \\\"types\\\": \\\"./dist/types/index.d.ts\\\"\\n}\\n\\n\\n预设字符串对应的构建配置:\\n\\nexport const buildConfig = [\\n {\\n format: 'cjs',\\n target: 'es6',\\n buildType: 'bundle',\\n outDir: './lib',\\n },\\n {\\n format: 'esm',\\n target: 'es6',\\n buildType: 'bundle',\\n outDir: './es',\\n },\\n {\\n buildType: 'bundle',\\n outDir: './types',\\n dts: {\\n only: true,\\n },\\n },\\n];\\n\\n\\n\\n'NPM-LIBRARY-WITH-UMD'\\n\\n在类 NPM 包管理器下使用,并且 Library 支持类似 unpkg 的模式。在预设 'npm-library' 的基础上,额外提供 umd 产物。\\n\\n{\\n \\\"main\\\": \\\"./dist/lib/index.js\\\",\\n \\\"module\\\": \\\"./dist/es/index.js\\\",\\n \\\"types\\\": \\\"./dist/types/index.d.ts\\\",\\n \\\"unpkg\\\": \\\"./dist/umd/index.js\\\",\\n};\\n\\n\\n预设字符串对应的构建配置:\\n\\nexport const buildConfig = [\\n {\\n format: 'cjs',\\n target: 'es6',\\n buildType: 'bundle',\\n outDir: './lib',\\n },\\n {\\n format: 'esm',\\n target: 'es6',\\n buildType: 'bundle',\\n outDir: './es',\\n },\\n {\\n format: 'umd',\\n target: 'es6',\\n buildType: 'bundle',\\n outDir: './umd',\\n },\\n {\\n buildType: 'bundle',\\n outDir: './types',\\n dts: {\\n only: true,\\n },\\n },\\n];\\n\\n\\n\\n'NPM-COMPONENT'\\n\\n在类 NPM 包管理器下使用的 组件(库)通用模式。包含 esm 和 cjs 两种 Bundleless 产物(便于 Tree shaking\\n优化),以及包含一份类型文件。\\n\\n对于源码中包含的样式文件,产物中提供样式的编译产物和样式的源文件。\\n\\n{\\n \\\"main\\\": \\\"./dist/lib/index.js\\\", // bundleless type\\n \\\"module\\\": \\\"./dist/es/index.js\\\", // bundleless type\\n \\\"types\\\": \\\"./dist/types/index.d.ts\\\",\\n};\\n\\n\\n预设字符串对应的构建配置:\\n\\nexport const buildConfig = [\\n {\\n format: 'cjs',\\n target: 'es6',\\n buildType: 'bundleless',\\n outDir: './lib',\\n },\\n {\\n format: 'esm',\\n target: 'es6',\\n buildType: 'bundleless',\\n outDir: './es',\\n },\\n {\\n buildType: 'bundleless',\\n outDir: './types',\\n dts: {\\n only: true,\\n },\\n },\\n];\\n\\n\\n\\n'NPM-COMPONENT-WITH-UMD'\\n\\n在类 NPM 包管理器下使用的组件(库),同时支持类 unpkg 的模式。 在预设 'npm-component' 的基础上,额外提供 umd 产物。\\n\\n{\\n \\\"main\\\": \\\"./dist/lib/index.js\\\", // bundleless type\\n \\\"module\\\": \\\"./dist/es/index.js\\\", // bundleless type\\n \\\"types\\\": \\\"./dist/types/index.d.ts\\\",\\n \\\"unpkg\\\": \\\"./dist/umd/index.js\\\",\\n};\\n\\n\\nexport const buildConfig = [\\n {\\n format: 'cjs',\\n target: 'es6',\\n buildType: 'bundleless',\\n outDir: './lib',\\n },\\n {\\n format: 'esm',\\n target: 'es6',\\n buildType: 'bundleless',\\n outDir: './es',\\n },\\n {\\n format: 'umd',\\n target: 'es6',\\n buildType: 'bundle',\\n outDir: './umd',\\n },\\n {\\n buildType: 'bundleless',\\n outDir: './types',\\n dts: {\\n only: true,\\n },\\n },\\n];\\n\\n\\n\\n关于预设值支持的 ECMASCRIPT 版本以及 {ES5...ESNEXT}\\n\\n当想要使用支持其他 ECMAScript 版本的 buildPreset 预设的时候,可以直接在\\n'npm-library'、'npm-library-with-umd'、'npm-component'、'npm-component-with-umd'\\n这些预设值后面增加想要支持的版本。\\n\\n例如希望 'npm-library' 预设支持 es2017,则可以按照如下方式配置:\\n\\n\\n\\nexport default defineConfig({\\n buildPreset: 'npm-library-es2017',\\n});\\n\\n\\n\\nFUNCTION\\n\\n函数的配置方式,可以通过 preset 参数获取到预设值,然后对里面的构建配置进行修改来自定义你的构建配置。\\n以下是一个函数的配置方式的例子,它配置了压缩构建产物的功能:\\n\\n\\n\\nexport default defineConfig({\\n buildPreset({ preset }) {\\n const { NPM_LIBRARY } = preset;\\n return NPM_LIBRARY.map(config => {\\n config.minify = {\\n compress: {\\n drop_console: true,\\n },\\n };\\n return config;\\n });\\n },\\n});\\n\",\"frontmatter\":{\"sidebar_position\":2}},{\"title\":\"DesignSystem\",\"routePath\":\"/api/config/design-system\",\"toc\":[{\"id\":\"screens\",\"text\":\"Screens\",\"depth\":2},{\"id\":\"max-width-断点\",\"text\":\"Max-width 断点\",\"depth\":3},{\"id\":\"多个范围的断点\",\"text\":\"多个范围的断点\",\"depth\":3},{\"id\":\"自定义媒体查询\",\"text\":\"自定义媒体查询\",\"depth\":3},{\"id\":\"print-样式\",\"text\":\"Print 样式\",\"depth\":3},{\"id\":\"dark-mode-1\",\"text\":\"Dark Mode\",\"depth\":3},{\"id\":\"colors-1\",\"text\":\"Colors\",\"depth\":2},{\"id\":\"spacing-1\",\"text\":\"Spacing\",\"depth\":2},{\"id\":\"核心插件\",\"text\":\"核心插件\",\"depth\":2},{\"id\":\"自定义默认配置\",\"text\":\"自定义默认配置\",\"depth\":2},{\"id\":\"覆盖默认配置\",\"text\":\"覆盖默认配置\",\"depth\":3},{\"id\":\"扩展默认配置\",\"text\":\"扩展默认配置\",\"depth\":3},{\"id\":\"引用其他值\",\"text\":\"引用其他值\",\"depth\":3},{\"id\":\"禁用整个核心插件\",\"text\":\"禁用整个核心插件\",\"depth\":3},{\"id\":\"添加自己的-key\",\"text\":\"添加自己的 key\",\"depth\":3},{\"id\":\"配置引用\",\"text\":\"配置引用\",\"depth\":2}],\"content\":\"DESIGNSYSTEM\\n\\n本章描述了有关 designSystem 相关的配置\\n\\n需要先通过 pnpm run new 启用 Tailwind CSS 功能。\\n\\n * type: Object\\n * default: 见下方配置详情。\\n\\nconst designSystem = {\\n screens: {\\n sm: '640px',\\n md: '768px',\\n lg: '1024px',\\n xl: '1280px',\\n },\\n colors: {\\n transparent: 'transparent',\\n current: 'currentColor',\\n\\n black: '#000',\\n white: '#fff',\\n\\n gray: {\\n 100: '#f7fafc',\\n 200: '#edf2f7',\\n 300: '#e2e8f0',\\n 400: '#cbd5e0',\\n 500: '#a0aec0',\\n 600: '#718096',\\n 700: '#4a5568',\\n 800: '#2d3748',\\n 900: '#1a202c',\\n },\\n red: {\\n 100: '#fff5f5',\\n 200: '#fed7d7',\\n 300: '#feb2b2',\\n 400: '#fc8181',\\n 500: '#f56565',\\n 600: '#e53e3e',\\n 700: '#c53030',\\n 800: '#9b2c2c',\\n 900: '#742a2a',\\n },\\n orange: {\\n 100: '#fffaf0',\\n 200: '#feebc8',\\n 300: '#fbd38d',\\n 400: '#f6ad55',\\n 500: '#ed8936',\\n 600: '#dd6b20',\\n 700: '#c05621',\\n 800: '#9c4221',\\n 900: '#7b341e',\\n },\\n yellow: {\\n 100: '#fffff0',\\n 200: '#fefcbf',\\n 300: '#faf089',\\n 400: '#f6e05e',\\n 500: '#ecc94b',\\n 600: '#d69e2e',\\n 700: '#b7791f',\\n 800: '#975a16',\\n 900: '#744210',\\n },\\n green: {\\n 100: '#f0fff4',\\n 200: '#c6f6d5',\\n 300: '#9ae6b4',\\n 400: '#68d391',\\n 500: '#48bb78',\\n 600: '#38a169',\\n 700: '#2f855a',\\n 800: '#276749',\\n 900: '#22543d',\\n },\\n teal: {\\n 100: '#e6fffa',\\n 200: '#b2f5ea',\\n 300: '#81e6d9',\\n 400: '#4fd1c5',\\n 500: '#38b2ac',\\n 600: '#319795',\\n 700: '#2c7a7b',\\n 800: '#285e61',\\n 900: '#234e52',\\n },\\n blue: {\\n 100: '#ebf8ff',\\n 200: '#bee3f8',\\n 300: '#90cdf4',\\n 400: '#63b3ed',\\n 500: '#4299e1',\\n 600: '#3182ce',\\n 700: '#2b6cb0',\\n 800: '#2c5282',\\n 900: '#2a4365',\\n },\\n indigo: {\\n 100: '#ebf4ff',\\n 200: '#c3dafe',\\n 300: '#a3bffa',\\n 400: '#7f9cf5',\\n 500: '#667eea',\\n 600: '#5a67d8',\\n 700: '#4c51bf',\\n 800: '#434190',\\n 900: '#3c366b',\\n },\\n purple: {\\n 100: '#faf5ff',\\n 200: '#e9d8fd',\\n 300: '#d6bcfa',\\n 400: '#b794f4',\\n 500: '#9f7aea',\\n 600: '#805ad5',\\n 700: '#6b46c1',\\n 800: '#553c9a',\\n 900: '#44337a',\\n },\\n pink: {\\n 100: '#fff5f7',\\n 200: '#fed7e2',\\n 300: '#fbb6ce',\\n 400: '#f687b3',\\n 500: '#ed64a6',\\n 600: '#d53f8c',\\n 700: '#b83280',\\n 800: '#97266d',\\n 900: '#702459',\\n },\\n },\\n spacing: {\\n px: '1px',\\n 0: '0',\\n 1: '0.25rem',\\n 2: '0.5rem',\\n 3: '0.75rem',\\n 4: '1rem',\\n 5: '1.25rem',\\n 6: '1.5rem',\\n 8: '2rem',\\n 10: '2.5rem',\\n 12: '3rem',\\n 16: '4rem',\\n 20: '5rem',\\n 24: '6rem',\\n 32: '8rem',\\n 40: '10rem',\\n 48: '12rem',\\n 56: '14rem',\\n 64: '16rem',\\n },\\n backgroundColor: theme => theme('colors'),\\n backgroundOpacity: theme => theme('opacity'),\\n backgroundPosition: {\\n bottom: 'bottom',\\n center: 'center',\\n left: 'left',\\n 'left-bottom': 'left bottom',\\n 'left-top': 'left top',\\n right: 'right',\\n 'right-bottom': 'right bottom',\\n 'right-top': 'right top',\\n top: 'top',\\n },\\n backgroundSize: {\\n auto: 'auto',\\n cover: 'cover',\\n contain: 'contain',\\n },\\n borderColor: theme => ({\\n ...theme('colors'),\\n default: theme('colors.gray.300', 'currentColor'),\\n }),\\n borderOpacity: theme => theme('opacity'),\\n borderRadius: {\\n none: '0',\\n sm: '0.125rem',\\n default: '0.25rem',\\n md: '0.375rem',\\n lg: '0.5rem',\\n full: '9999px',\\n },\\n borderWidth: {\\n default: '1px',\\n 0: '0',\\n 2: '2px',\\n 4: '4px',\\n 8: '8px',\\n },\\n boxShadow: {\\n xs: '0 0 0 1px rgba(0, 0, 0, 0.05)',\\n sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',\\n default: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',\\n md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',\\n lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',\\n xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',\\n '2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',\\n inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',\\n outline: '0 0 0 3px rgba(66, 153, 225, 0.5)',\\n none: 'none',\\n },\\n container: {},\\n cursor: {\\n auto: 'auto',\\n default: 'default',\\n pointer: 'pointer',\\n wait: 'wait',\\n text: 'text',\\n move: 'move',\\n 'not-allowed': 'not-allowed',\\n },\\n divideColor: theme => theme('borderColor'),\\n divideOpacity: theme => theme('borderOpacity'),\\n divideWidth: theme => theme('borderWidth'),\\n fill: {\\n current: 'currentColor',\\n },\\n flex: {\\n 1: '1 1 0%',\\n auto: '1 1 auto',\\n initial: '0 1 auto',\\n none: 'none',\\n },\\n flexGrow: {\\n 0: '0',\\n default: '1',\\n },\\n flexShrink: {\\n 0: '0',\\n default: '1',\\n },\\n fontFamily: {\\n sans: [\\n 'system-ui',\\n '-apple-system',\\n 'BlinkMacSystemFont',\\n '\\\"Segoe UI\\\"',\\n 'Roboto',\\n '\\\"Helvetica Neue\\\"',\\n 'Arial',\\n '\\\"Noto Sans\\\"',\\n 'sans-serif',\\n '\\\"Apple Color Emoji\\\"',\\n '\\\"Segoe UI Emoji\\\"',\\n '\\\"Segoe UI Symbol\\\"',\\n '\\\"Noto Color Emoji\\\"',\\n ],\\n serif: ['Georgia', 'Cambria', '\\\"Times New Roman\\\"', 'Times', 'serif'],\\n mono: [\\n 'Menlo',\\n 'Monaco',\\n 'Consolas',\\n '\\\"Liberation Mono\\\"',\\n '\\\"Courier New\\\"',\\n 'monospace',\\n ],\\n },\\n fontSize: {\\n xs: '0.75rem',\\n sm: '0.875rem',\\n base: '1rem',\\n lg: '1.125rem',\\n xl: '1.25rem',\\n '2xl': '1.5rem',\\n '3xl': '1.875rem',\\n '4xl': '2.25rem',\\n '5xl': '3rem',\\n '6xl': '4rem',\\n },\\n fontWeight: {\\n hairline: '100',\\n thin: '200',\\n light: '300',\\n normal: '400',\\n medium: '500',\\n semibold: '600',\\n bold: '700',\\n extrabold: '800',\\n black: '900',\\n },\\n height: theme => ({\\n auto: 'auto',\\n ...theme('spacing'),\\n full: '100%',\\n screen: '100vh',\\n }),\\n inset: {\\n 0: '0',\\n auto: 'auto',\\n },\\n letterSpacing: {\\n tighter: '-0.05em',\\n tight: '-0.025em',\\n normal: '0',\\n wide: '0.025em',\\n wider: '0.05em',\\n widest: '0.1em',\\n },\\n lineHeight: {\\n none: '1',\\n tight: '1.25',\\n snug: '1.375',\\n normal: '1.5',\\n relaxed: '1.625',\\n loose: '2',\\n 3: '.75rem',\\n 4: '1rem',\\n 5: '1.25rem',\\n 6: '1.5rem',\\n 7: '1.75rem',\\n 8: '2rem',\\n 9: '2.25rem',\\n 10: '2.5rem',\\n },\\n listStyleType: {\\n none: 'none',\\n disc: 'disc',\\n decimal: 'decimal',\\n },\\n margin: (theme, { negative }) => ({\\n auto: 'auto',\\n ...theme('spacing'),\\n ...negative(theme('spacing')),\\n }),\\n maxHeight: {\\n full: '100%',\\n screen: '100vh',\\n },\\n maxWidth: (theme, { breakpoints }) => ({\\n none: 'none',\\n xs: '20rem',\\n sm: '24rem',\\n md: '28rem',\\n lg: '32rem',\\n xl: '36rem',\\n '2xl': '42rem',\\n '3xl': '48rem',\\n '4xl': '56rem',\\n '5xl': '64rem',\\n '6xl': '72rem',\\n full: '100%',\\n ...breakpoints(theme('screens')),\\n }),\\n minHeight: {\\n 0: '0',\\n full: '100%',\\n screen: '100vh',\\n },\\n minWidth: {\\n 0: '0',\\n full: '100%',\\n },\\n objectPosition: {\\n bottom: 'bottom',\\n center: 'center',\\n left: 'left',\\n 'left-bottom': 'left bottom',\\n 'left-top': 'left top',\\n right: 'right',\\n 'right-bottom': 'right bottom',\\n 'right-top': 'right top',\\n top: 'top',\\n },\\n opacity: {\\n 0: '0',\\n 25: '0.25',\\n 50: '0.5',\\n 75: '0.75',\\n 100: '1',\\n },\\n order: {\\n first: '-9999',\\n last: '9999',\\n none: '0',\\n 1: '1',\\n 2: '2',\\n 3: '3',\\n 4: '4',\\n 5: '5',\\n 6: '6',\\n 7: '7',\\n 8: '8',\\n 9: '9',\\n 10: '10',\\n 11: '11',\\n 12: '12',\\n },\\n padding: theme => theme('spacing'),\\n placeholderColor: theme => theme('colors'),\\n placeholderOpacity: theme => theme('opacity'),\\n space: (theme, { negative }) => ({\\n ...theme('spacing'),\\n ...negative(theme('spacing')),\\n }),\\n stroke: {\\n current: 'currentColor',\\n },\\n strokeWidth: {\\n 0: '0',\\n 1: '1',\\n 2: '2',\\n },\\n textColor: theme => theme('colors'),\\n textOpacity: theme => theme('opacity'),\\n width: theme => ({\\n auto: 'auto',\\n ...theme('spacing'),\\n '1/2': '50%',\\n '1/3': '33.333333%',\\n '2/3': '66.666667%',\\n '1/4': '25%',\\n '2/4': '50%',\\n '3/4': '75%',\\n '1/5': '20%',\\n '2/5': '40%',\\n '3/5': '60%',\\n '4/5': '80%',\\n '1/6': '16.666667%',\\n '2/6': '33.333333%',\\n '3/6': '50%',\\n '4/6': '66.666667%',\\n '5/6': '83.333333%',\\n '1/12': '8.333333%',\\n '2/12': '16.666667%',\\n '3/12': '25%',\\n '4/12': '33.333333%',\\n '5/12': '41.666667%',\\n '6/12': '50%',\\n '7/12': '58.333333%',\\n '8/12': '66.666667%',\\n '9/12': '75%',\\n '10/12': '83.333333%',\\n '11/12': '91.666667%',\\n full: '100%',\\n screen: '100vw',\\n }),\\n zIndex: {\\n auto: 'auto',\\n 0: '0',\\n 10: '10',\\n 20: '20',\\n 30: '30',\\n 40: '40',\\n 50: '50',\\n },\\n gap: theme => theme('spacing'),\\n gridTemplateColumns: {\\n none: 'none',\\n 1: 'repeat(1, minmax(0, 1fr))',\\n 2: 'repeat(2, minmax(0, 1fr))',\\n 3: 'repeat(3, minmax(0, 1fr))',\\n 4: 'repeat(4, minmax(0, 1fr))',\\n 5: 'repeat(5, minmax(0, 1fr))',\\n 6: 'repeat(6, minmax(0, 1fr))',\\n 7: 'repeat(7, minmax(0, 1fr))',\\n 8: 'repeat(8, minmax(0, 1fr))',\\n 9: 'repeat(9, minmax(0, 1fr))',\\n 10: 'repeat(10, minmax(0, 1fr))',\\n 11: 'repeat(11, minmax(0, 1fr))',\\n 12: 'repeat(12, minmax(0, 1fr))',\\n },\\n gridColumn: {\\n auto: 'auto',\\n 'span-1': 'span 1 / span 1',\\n 'span-2': 'span 2 / span 2',\\n 'span-3': 'span 3 / span 3',\\n 'span-4': 'span 4 / span 4',\\n 'span-5': 'span 5 / span 5',\\n 'span-6': 'span 6 / span 6',\\n 'span-7': 'span 7 / span 7',\\n 'span-8': 'span 8 / span 8',\\n 'span-9': 'span 9 / span 9',\\n 'span-10': 'span 10 / span 10',\\n 'span-11': 'span 11 / span 11',\\n 'span-12': 'span 12 / span 12',\\n },\\n gridColumnStart: {\\n auto: 'auto',\\n 1: '1',\\n 2: '2',\\n 3: '3',\\n 4: '4',\\n 5: '5',\\n 6: '6',\\n 7: '7',\\n 8: '8',\\n 9: '9',\\n 10: '10',\\n 11: '11',\\n 12: '12',\\n 13: '13',\\n },\\n gridColumnEnd: {\\n auto: 'auto',\\n 1: '1',\\n 2: '2',\\n 3: '3',\\n 4: '4',\\n 5: '5',\\n 6: '6',\\n 7: '7',\\n 8: '8',\\n 9: '9',\\n 10: '10',\\n 11: '11',\\n 12: '12',\\n 13: '13',\\n },\\n gridTemplateRows: {\\n none: 'none',\\n 1: 'repeat(1, minmax(0, 1fr))',\\n 2: 'repeat(2, minmax(0, 1fr))',\\n 3: 'repeat(3, minmax(0, 1fr))',\\n 4: 'repeat(4, minmax(0, 1fr))',\\n 5: 'repeat(5, minmax(0, 1fr))',\\n 6: 'repeat(6, minmax(0, 1fr))',\\n },\\n gridRow: {\\n auto: 'auto',\\n 'span-1': 'span 1 / span 1',\\n 'span-2': 'span 2 / span 2',\\n 'span-3': 'span 3 / span 3',\\n 'span-4': 'span 4 / span 4',\\n 'span-5': 'span 5 / span 5',\\n 'span-6': 'span 6 / span 6',\\n },\\n gridRowStart: {\\n auto: 'auto',\\n 1: '1',\\n 2: '2',\\n 3: '3',\\n 4: '4',\\n 5: '5',\\n 6: '6',\\n 7: '7',\\n },\\n gridRowEnd: {\\n auto: 'auto',\\n 1: '1',\\n 2: '2',\\n 3: '3',\\n 4: '4',\\n 5: '5',\\n 6: '6',\\n 7: '7',\\n },\\n transformOrigin: {\\n center: 'center',\\n top: 'top',\\n 'top-right': 'top right',\\n right: 'right',\\n 'bottom-right': 'bottom right',\\n bottom: 'bottom',\\n 'bottom-left': 'bottom left',\\n left: 'left',\\n 'top-left': 'top left',\\n },\\n scale: {\\n 0: '0',\\n 50: '.5',\\n 75: '.75',\\n 90: '.9',\\n 95: '.95',\\n 100: '1',\\n 105: '1.05',\\n 110: '1.1',\\n 125: '1.25',\\n 150: '1.5',\\n },\\n rotate: {\\n '-180': '-180deg',\\n '-90': '-90deg',\\n '-45': '-45deg',\\n 0: '0',\\n 45: '45deg',\\n 90: '90deg',\\n 180: '180deg',\\n },\\n translate: (theme, { negative }) => ({\\n ...theme('spacing'),\\n ...negative(theme('spacing')),\\n '-full': '-100%',\\n '-1/2': '-50%',\\n '1/2': '50%',\\n full: '100%',\\n }),\\n skew: {\\n '-12': '-12deg',\\n '-6': '-6deg',\\n '-3': '-3deg',\\n 0: '0',\\n 3: '3deg',\\n 6: '6deg',\\n 12: '12deg',\\n },\\n transitionProperty: {\\n none: 'none',\\n all: 'all',\\n default:\\n 'background-color, border-color, color, fill, stroke, opacity, box-shadow, transform',\\n colors: 'background-color, border-color, color, fill, stroke',\\n opacity: 'opacity',\\n shadow: 'box-shadow',\\n transform: 'transform',\\n },\\n transitionTimingFunction: {\\n linear: 'linear',\\n in: 'cubic-bezier(0.4, 0, 1, 1)',\\n out: 'cubic-bezier(0, 0, 0.2, 1)',\\n 'in-out': 'cubic-bezier(0.4, 0, 0.2, 1)',\\n },\\n transitionDuration: {\\n 75: '75ms',\\n 100: '100ms',\\n 150: '150ms',\\n 200: '200ms',\\n 300: '300ms',\\n 500: '500ms',\\n 700: '700ms',\\n 1000: '1000ms',\\n },\\n transitionDelay: {\\n 75: '75ms',\\n 100: '100ms',\\n 150: '150ms',\\n 200: '200ms',\\n 300: '300ms',\\n 500: '500ms',\\n 700: '700ms',\\n 1000: '1000ms',\\n },\\n};\\n\\n\\n更多关于TailwindCSS 配置\\n\\ndesignSystem 用于定义项目的调色板、排版比例(Typographic Scales 或者 Type\\nScale)、字体列表、断点、边框圆角值等等。因为 Modern.js 借用了 Tailwind Theme 的设计方式,并且内部也集成了 Tailwind\\nCSS,所以 designSystem 使用方式与 Tailwind CSS Theme 相同\\n\\ndesignSystem 对象包含 screens、colors 和 spacing 的属性,以及每个可自定义核心插件。\\n\\n\\nSCREENS\\n\\n使用screens 可以自定义项目中的响应断点:\\n\\nconst designSystem = {\\n screens: {\\n sm: '640px',\\n md: '768px',\\n lg: '1024px',\\n xl: '1280px',\\n },\\n};\\n\\n\\n其中 screens 对象里的属性名是屏幕名称(用作 Tailwind CSS 生成的自适应实用程序变体的前缀,例如\\nmd:text-center),值是该断点应在其开始的 min-width。\\n\\n默认断点受常见设备分辨率的启发:\\n\\nconst designSystem = {\\n screens: {\\n sm: '640px',\\n // => @media (min-width: 640px) { ... }\\n\\n md: '768px',\\n // => @media (min-width: 768px) { ... }\\n\\n lg: '1024px',\\n // => @media (min-width: 1024px) { ... }\\n\\n xl: '1280px',\\n // => @media (min-width: 1280px) { ... }\\n },\\n};\\n\\n\\n你可以在你的项目中使用任意你喜欢的名称作为断点的属性:\\n\\nconst designSystem = {\\n screens: {\\n tablet: '640px',\\n // => @media (min-width: 640px) { ... }\\n\\n laptop: '1024px',\\n // => @media (min-width: 1024px) { ... }\\n\\n desktop: '1280px',\\n // => @media (min-width: 1280px) { ... }\\n },\\n};\\n\\n\\n这些屏幕名称反映在 utilities 中,因此 text-center 现在是这样的:\\n\\n.text-center {\\n text-align: center;\\n}\\n\\n@media (min-width: 640px) {\\n .tablet\\\\:text-center {\\n text-align: center;\\n }\\n}\\n\\n@media (min-width: 1024px) {\\n .laptop\\\\:text-center {\\n text-align: center;\\n }\\n}\\n\\n@media (min-width: 1280px) {\\n .desktop\\\\:text-center {\\n text-align: center;\\n }\\n}\\n\\n\\n\\nMAX-WIDTH 断点\\n\\n如果要使用 max-width 断点而不是 min-width,可以将屏幕指定为具有 max 属性的对象:\\n\\nconst designSystem = {\\n screens: {\\n xl: { max: '1279px' },\\n // => @media (max-width: 1279px) { ... }\\n\\n lg: { max: '1023px' },\\n // => @media (max-width: 1023px) { ... }\\n\\n md: { max: '767px' },\\n // => @media (max-width: 767px) { ... }\\n\\n sm: { max: '639px' },\\n // => @media (max-width: 639px) { ... }\\n },\\n};\\n\\n\\n如有必要,以创建带有 min-width 和 max-width 定义的断点,例如:\\n\\nconst designSystem = {\\n screens: {\\n sm: { min: '640px', max: '767px' },\\n md: { min: '768px', max: '1023px' },\\n lg: { min: '1024px', max: '1279px' },\\n xl: { min: '1280px' },\\n },\\n};\\n\\n\\n\\n多个范围的断点\\n\\n有时,将单个断点定义应用于多个范围会很有用。\\n\\n例如,假设您有一个 sidebar,并且希望断点基于内容区域宽度而不是整个视口。您可以模拟这种情况,当 sidebar\\n可见并缩小内容区域时,断点的样式使用较小的断点样式:\\n\\nconst designSystem = {\\n screens: {\\n sm: '500px',\\n md: [\\n // Sidebar appears at 768px, so revert to `sm:` styles between 768px\\n // and 868px, after which the main content area is wide enough again to\\n // apply the `md:` styles.\\n { min: '668px', max: '767px' },\\n { min: '868px' },\\n ],\\n lg: '1100px',\\n xl: '1400px',\\n },\\n};\\n\\n\\n\\n自定义媒体查询\\n\\n如果需要为断点提供完全自定义的媒体查询,则可以使用带有 raw 属性的对象:\\n\\nconst designSystem = {\\n extend: {\\n screens: {\\n portrait: { raw: '(orientation: portrait)' },\\n // => @media (orientation: portrait) { ... }\\n },\\n },\\n};\\n\\n\\n\\nPRINT 样式\\n\\n如果需要为打印应用不同的样式,则 raw 选项可能特别有用。\\n\\n需要做的就是在 designSystem.extend.screens 下添加一个 print:\\n\\nconst designSystem = {\\n extend: {\\n screens: {\\n print: { raw: 'print' },\\n // => @media print { ... }\\n },\\n },\\n};\\n\\n\\n然后,可以使用诸如 print:text-black 之类的类来指定仅当某人尝试打印页面时才应用的样式:\\n\\n<div class=\\\"text-gray-700 print:text-black\\\">\\n <!-- ... -->\\n</div>\\n\\n\\n\\nDARK MODE\\n\\nraw 选项可以用于实现 “暗模式” 屏幕:\\n\\nconst designSystem = {\\n extend: {\\n screens: {\\n dark: { raw: '(prefers-color-scheme: dark)' },\\n // => @media (prefers-color-scheme: dark) { ... }\\n },\\n },\\n};\\n\\n\\n然后,您可以使用 dark: 前缀在暗模式下为元素设置不同的样式:\\n\\n<div class=\\\"text-gray-700 dark:text-gray-200\\\">\\n <!-- ... -->\\n</div>\\n\\n\\n请注意,由于这些 screen variants 是在 Tailwind CSS 中实现的,因此无法使用这种方法将断点与暗模式结合使用 ,例如\\nmd:dark:text-gray-300 将不起作用。\\n\\n\\nCOLORS\\n\\ncolors 属性可让您自定义项目的全局调色板。\\n\\nconst designSystem = {\\n colors: {\\n transparent: 'transparent',\\n black: '#000',\\n white: '#fff',\\n gray: {\\n 100: '#f7fafc',\\n // ...\\n 900: '#1a202c',\\n },\\n\\n // ...\\n },\\n};\\n\\n\\n默认情况下,这些颜色由 backgroundColor,textColor 和 borderColor 核心插件继承。\\n\\n想了解更多,可以查看:Customizing Colors。\\n\\n\\nSPACING\\n\\n使用 space 属性,可以自定义项目的全局间距和缩放比例:\\n\\nconst designSystem = {\\n spacing: {\\n px: '1px',\\n 0: '0',\\n 1: '0.25rem',\\n 2: '0.5rem',\\n 3: '0.75rem',\\n 4: '1rem',\\n 5: '1.25rem',\\n 6: '1.5rem',\\n 8: '2rem',\\n 10: '2.5rem',\\n 12: '3rem',\\n 16: '4rem',\\n 20: '5rem',\\n 24: '6rem',\\n 32: '8rem',\\n 40: '10rem',\\n 48: '12rem',\\n 56: '14rem',\\n 64: '16rem',\\n },\\n};\\n\\n\\n默认情况下,这些值由 padding,margin,negativeMargin,width 和 height 核心插件继承。\\n\\n想要了解更多,看 Customizing Spacing。\\n\\n\\n核心插件\\n\\n主题部分的其余部分用于配置每个核心插件可用的值。\\n\\n例如,borderRadius 属性可让您自定义将生成的圆角的 utilities:\\n\\nconst designSystem = {\\n borderRadius: {\\n none: '0',\\n sm: '.125rem',\\n default: '.25rem',\\n lg: '.5rem',\\n full: '9999px',\\n },\\n};\\n\\n\\n属性名确定所生成类的后缀,值确定实际 CSS 声明的值。 上面的示例borderRadius配置将生成以下 CSS 类:\\n\\n.rounded-none {\\n border-radius: 0;\\n}\\n.rounded-sm {\\n border-radius: 0.125rem;\\n}\\n.rounded {\\n border-radius: 0.25rem;\\n}\\n.rounded-lg {\\n border-radius: 0.5rem;\\n}\\n.rounded-full {\\n border-radius: 9999px;\\n}\\n\\n\\n会注意到,在主题配置中使用 default 属性创建了不带后缀的 rounded 类。这是许多(尽管不是全部)核心插件支持的 Tailwind CSS\\n中的通用约定。\\n\\n要了解有关自定义特定核心插件的更多信息,请访问该插件的文档。\\n\\n\\n自定义默认配置\\n\\n开箱即用,您的项目将自动从默认主题配置继承值。如果想自定义默认主题,则根据目标有几种不同的选择。\\n\\n\\n覆盖默认配置\\n\\n要覆盖默认配置中的选项,请在 designSystem 中添加要覆盖的属性:\\n\\n\\n\\nconst designSystem = {\\n // Replaces all of the default `opacity` values\\n opacity: {\\n 0: '0',\\n 20: '0.2',\\n 40: '0.4',\\n 60: '0.6',\\n 80: '0.8',\\n 100: '1',\\n },\\n};\\n\\nexport default defineConfig({\\n designSystem,\\n});\\n\\n\\n这将完全替换默认属性配置,因此在上面的示例中,不会生成默认的 opacity utilities。\\n\\n您未提供的任何属性都将从默认主题继承,因此在上面的示例中,将保留颜色,间距,边框圆角,背景位置等内容的默认主题配置。\\n\\n\\n扩展默认配置\\n\\n如果您想保留主题选项的默认值,但又要添加新值,请在 designSystem.extend 属性下添加扩展的内容。\\n\\n例如,如果您想添加一个额外的断点但保留现有的断点,则可以扩展 screens 属性:\\n\\n\\n\\nconst designSystem = {\\n extend: {\\n // Adds a new breakpoint in addition to the default breakpoints\\n screens: {\\n '2xl': '1440px',\\n },\\n },\\n};\\n\\nexport default defineConfig({\\n designSystem,\\n});\\n\\n\\n您当然可以覆盖默认主题的某些部分,并在同一配置中扩展默认主题的其他部分:\\n\\n\\n\\nconst designSystem = {\\n opacity: {\\n 0: '0',\\n 20: '0.2',\\n 40: '0.4',\\n 60: '0.6',\\n 80: '0.8',\\n 100: '1',\\n },\\n extend: {\\n screens: {\\n '2xl': '1440px',\\n },\\n },\\n};\\n\\nexport default defineConfig({\\n designSystem,\\n});\\n\\n\\n\\n引用其他值\\n\\n如果需要在配置中引用另一个值,可以通过提供闭包函数而不是静态值来实现。函数将收到 theme() 函数作为参数,您可以使用该函数使用点表示法在配置中查找其他值。\\n\\n例如,您可以在 fill 配置上通过引用 theme('colors') 为调色板中的每种颜色生成 fill utilities。\\n\\n\\n\\nconst designSystem = {\\n colors: {\\n // ...\\n },\\n fill: theme => theme('colors'),\\n};\\n\\nexport default defineConfig({\\n designSystem,\\n});\\n\\n\\ntheme()函数尝试从已经完全合并的配置对象中找到您要查找的值,因此它可以引用您自己的自定义设置以及默认主题值。它也可以递归工作,因此只要链末尾有一个静态值,\\n它就可以解析您要查找的值。\\n\\n引用默认配置\\n\\n如果出于任何原因想要引用默认配置中的值,则可以从 tailwindcss/defaultTheme\\n导入它。一个有用的示例是,如果要将添加默认配置提供的字体中某一个字体:\\n\\n\\n\\nconst defaultTheme = require('tailwindcss/defaultTheme');\\n\\nconst designSystem = {\\n extend: {\\n fontFamily: {\\n sans: ['Lato', ...defaultTheme.fontFamily.sans],\\n },\\n },\\n};\\n\\nexport default defineConfig({\\n designSystem,\\n});\\n\\n\\n\\n禁用整个核心插件\\n\\n如果您不想为某个核心插件生成任何类,则最好在 corePlugins 配置中将该插件设置为 false,而不是在配置中为该属性提供一个空对象:\\n\\n// Don't assign an empty object in your theme configuration\\n\\nconst designSystem = {\\n opacity: {},\\n};\\n\\n// Do disable the plugin in your corePlugins configuration\\nconst designSyttem = {\\n corePlugins: {\\n opacity: false,\\n },\\n};\\n\\n\\n最终结果是相同的,但是由于许多核心插件未公开任何配置,因此无论如何只能使用 corePlugins 禁用它们,最好保持一致。\\n\\n\\n添加自己的 KEY\\n\\n在很多情况下,将自己的属性添加到配置对象可能会很有用。\\n\\n其中一个示例是添加新属性为多个核心插件之间复用。例如,您可以提取一个 positions对象,backgroundPosition 和\\nobjectPosition 插件都可以引用该对象:\\n\\nconst designSystem = {\\n positions: {\\n bottom: 'bottom',\\n center: 'center',\\n left: 'left',\\n 'left-bottom': 'left bottom',\\n 'left-top': 'left top',\\n right: 'right',\\n 'right-bottom': 'right bottom',\\n 'right-top': 'right top',\\n top: 'top',\\n },\\n backgroundPosition: theme => theme('positions'),\\n objectPosition: theme => theme('positions'),\\n};\\n\\n\\n另一个示例是在自定义插件中添加新的属性以进行引用。例如,如果您为项目编写了渐变插件,则可以向该插件引用的主题对象添加渐变属性:\\n\\n\\n\\nconst designSystem = {\\n gradients: theme => ({\\n 'blue-green': [theme('colors.blue.500'), theme('colors.green.500')],\\n 'purple-blue': [theme('colors.purple.500'), theme('colors.blue.500')],\\n // ...\\n }),\\n};\\n\\nexport default defineConfig({\\n designSystem,\\n buildConfig: {\\n style: {\\n postcss: {\\n plugins: [require('./plugins/gradients')],\\n },\\n },\\n },\\n});\\n\\n\\n\\n配置引用\\n\\n除了 screens,colors 和 spacing 外,配置对象中的所有属性都映射到 Tailwind CSS\\n的核心插件上。由于许多插件负责仅接受静态值集(例如,例如float)的 CSS 属性,因此请注意,并非每个插件在主题对象中都有对应的属性。\\n\\n所有这些属性也可以在 designSystem.extend 属性下使用,以扩展默认主题。\\n\\n关于所有属性的作用,可以查看此 链接。\",\"frontmatter\":{\"sidebar_position\":3}},{\"title\":\"Plugins\",\"routePath\":\"/api/config/plugins\",\"toc\":[],\"content\":\"PLUGINS\\n\\n本章介绍注册 module-tools 插件的配置。\\n\\n * type:Array<ModuleToolsPlugin>\\n\\n\\nexport default defineConfig({\\n plugins: [ExamplePlugin()],\\n});\\n\\n\\n关于如何编写插件,可以查看【插件编写指南】。\",\"frontmatter\":{\"sidebar_position\":4}},{\"title\":\"Testing\",\"routePath\":\"/api/config/testing\",\"toc\":[{\"id\":\"jest-1\",\"text\":\"jest\",\"depth\":2},{\"id\":\"transformer-1\",\"text\":\"transformer\",\"depth\":2}],\"content\":\"TESTING\\n\\n本章描述了测试相关的配置\\n\\n需要先通过 pnpm run new 启用 单元测试 功能。\\n\\n\\nJEST\\n\\n * 类型: Object | Function\\n * 默认值:{}\\n\\n对应 Jest 的配置,当为 Object 类型时,可以配置 Jest 所支持的所有底层配置 。\\n\\n\\n\\nexport default defineConfig({\\n testing: {\\n jest: {\\n testTimeout: 10000,\\n },\\n },\\n});\\n\\n\\n值为 Function 类型时,默认配置作为第一个参数传入,需要返回新的 Jest 配置对象。\\n\\n\\n\\nexport default defineConfig({\\n testing: {\\n jest: options => {\\n return {\\n ...options,\\n testTimeout: 10000,\\n };\\n },\\n },\\n});\\n\\n\\n\\nTRANSFORMER\\n\\n * 类型:'babel-jest' | 'ts-jest'\\n * 默认值:'babel-jest'\\n\\n配置执行测试的时候对于源码的编译工具: babel-jest 或 ts-jest。默认使用 babel-jest。\\n\\nbabel-jest 也可以编译 TS 文件,但不会类型报错,如果你需要跑测试的时候对 TS 类型进行校验,那么请使用 ts-jest。\",\"frontmatter\":{\"sidebar_position\":5}},{\"title\":\"index\",\"routePath\":\"/api/\",\"toc\":[],\"content\":\"INDEX\",\"frontmatter\":{\"overview\":true,\"sidebar_label\":\"概览\",\"sidebar_position\":1}},{\"title\":\"Plugin Hooks\",\"routePath\":\"/api/plugin-api/plugin-hooks\",\"toc\":[{\"id\":\"构建钩子\",\"text\":\"构建钩子\",\"depth\":2},{\"id\":\"beforebuild-1\",\"text\":\"beforeBuild\",\"depth\":3},{\"id\":\"beforebuildtask-1\",\"text\":\"beforeBuildTask\",\"depth\":3},{\"id\":\"afterbuildtask-1\",\"text\":\"afterBuildTask\",\"depth\":3},{\"id\":\"afterbuild-1\",\"text\":\"afterBuild\",\"depth\":3},{\"id\":\"buildplatform-钩子\",\"text\":\"buildPlatform 钩子\",\"depth\":2},{\"id\":\"registerbuildplatform-1\",\"text\":\"registerBuildPlatform\",\"depth\":3},{\"id\":\"beforebuildplatform-1\",\"text\":\"beforeBuildPlatform\",\"depth\":3},{\"id\":\"buildplatform-1\",\"text\":\"buildPlatform\",\"depth\":3},{\"id\":\"afterbuildplatform-1\",\"text\":\"afterBuildPlatform\",\"depth\":3},{\"id\":\"调试钩子\",\"text\":\"调试钩子\",\"depth\":2},{\"id\":\"registerdev-1\",\"text\":\"registerDev\",\"depth\":3},{\"id\":\"beforedev-1\",\"text\":\"beforeDev\",\"depth\":3},{\"id\":\"beforeafterdevmenu-1\",\"text\":\"(before|after)DevMenu\",\"depth\":3},{\"id\":\"beforedevtask-1\",\"text\":\"beforeDevTask\",\"depth\":3},{\"id\":\"afterdev-1\",\"text\":\"afterDev\",\"depth\":3}],\"content\":\"PLUGIN HOOKS\\n\\n本章介绍关于 module-tools 支持的生命周期钩子。\\n\\n目前主要包含两类生命周期钩子:\\n\\n * 构建钩子:仅在执行 build 命令构建源码产物时触发。\\n * buildPlatform 钩子:仅在执行 build --platform 命令生成其他构建产物时触发。\\n * 调试钩子:运行 dev 命令时会触发的钩子。\\n\\n\\n构建钩子\\n\\n在执行 build 命令的时候,会按照顺序触发以下 Hooks:\\n\\n * beforeBuild\\n * beforeBuildTask\\n * afterBuildTask\\n * afterBuild\\n\\n\\nBEFOREBUILD\\n\\n执行整体构建流程之前触发。\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n beforeBuild(options: Options): Return {\\n return options.config;\\n },\\n };\\n },\\n});\\n\\n\\n参数和返回值类型:\\n\\ntype Options = {\\n options: { config: BuildConfig; cliOptions: BuildCommandOptions };\\n};\\n\\nexport interface BuildCommandOptions {\\n config: string;\\n clear?: boolean;\\n dts?: boolean;\\n platform?: boolean | string[];\\n tsconfig: string;\\n watch?: boolean;\\n}\\n\\ntype Return = BuildConfig;\\n\\n\\n> BuildConfig 类型参考 API 配置\\n\\n\\nBEFOREBUILDTASK\\n\\n根据构建配置,module tools 会将整体构建分成多个子构建任务。该 Hook 将会在每一个构建子任务之前触发。\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n beforeBuildTask(config: BaseBuildConfig): BaseBuildConfig {\\n return config;\\n },\\n };\\n },\\n});\\n\\n\\n参数和返回值类型:\\n\\nBaseBuildConfig 类型参考 API 配置。\\n\\n\\nAFTERBUILDTASK\\n\\n每一个构建子任务结束之后触发。\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n afterBuildTask(options: BuildTaskResult): void {\\n // ...\\n },\\n };\\n },\\n});\\n\\n\\n参数和返回值类型:\\n\\nexport interface BuildTaskResult {\\n status: 'success' | 'fail';\\n message?: string;\\n config: BaseBuildConfig;\\n}\\n\\n\\n\\nAFTERBUILD\\n\\n整体构建流程结束之后触发。\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n afterBuild(options: BuildResult): void {\\n // ...\\n },\\n };\\n },\\n});\\n\\n\\n参数和返回值类型:\\n\\nexport interface BuildResult {\\n status: 'success' | 'fail';\\n message?: string;\\n config: BuildConfig;\\n commandOptions: BuildCommandOptions;\\n totalDuration: number;\\n}\\n\\n\\n\\nBUILDPLATFORM 钩子\\n\\nmodule-tools 还提供了 build --platform 命令来执行特定的构建任务。\\n\\n例如在安装了 Storybook 插件后,就可以执行 build --platform 或者 build --platform storybook 来执行\\nStorybook 的构建任务。因为 Storybook 插件基于 buildPlatform Hooks 实现了该功能。\\n\\n在执行 build --platform 后会按照以下顺序触发 Hooks:\\n\\n * registerBuildPlatform\\n * beforeBuildPlatform\\n * buildPlatform\\n * afterBuildPlatform\\n\\n\\nREGISTERBUILDPLATFORM\\n\\n获取在执行 build --platform 命令时候需要运行的任务信息。\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n registerBuildPlatform(): RegisterBuildPlatformResult {\\n // ...\\n return {\\n platform: 'stroybook',\\n build() {\\n // run storybook logic\\n },\\n };\\n },\\n };\\n },\\n});\\n\\n\\n入参和返回的参数类型:\\n\\nexport interface RegisterBuildPlatformResult {\\n platform: string | string[];\\n build: (\\n currentPlatform: string, // 当前运行的 platform 构建任务\\n context: { isTsProject: boolean },\\n ) => void | Promise<void>;\\n}\\n\\n\\n\\nBEFOREBUILDPLATFORM\\n\\n当执行 build --platform 命令的时候,会触发所有已注册的构建任务。beforeBuildPlatform 会在执行整体的构建任务之前触发。\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n beforeBuildPlatform(platforms: RegisterBuildPlatformResult[]): void {\\n console.info(`have ${platforms.length} platform tasks`);\\n },\\n };\\n },\\n});\\n\\n\\n入参和返回的参数类型:\\n\\nexport interface RegisterBuildPlatformResult {\\n platform: string | string[];\\n build: (\\n currentPlatform: string, // 当前运行的 platform 构建任务\\n context: { isTsProject: boolean },\\n ) => void | Promise<void>;\\n}\\n\\n\\n\\nBUILDPLATFORM\\n\\n当执行 build --platform 命令的时候,会触发所有已注册的构建任务。buildPlatform 会在每个构建任务执行之前触发。\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n buildPlatform({ platform }: Options): void {\\n console.info(`current task is ${platform}`);\\n },\\n };\\n },\\n});\\n\\n\\n入参和返回的参数类型:\\n\\nexport interface Options {\\n platform: string;\\n}\\n\\n\\n\\nAFTERBUILDPLATFORM\\n\\n当执行 build --platform 命令的时候,会触发所有已注册的构建任务。afterBuildPlatform 会在整体 platform\\n构建任务结束后触发。\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n afterBuildPlatform(result: BuildPlatformResult): void {\\n if (result.status === 'success') {\\n console.info(`all platform build task success`);\\n } else {\\n console.error(result.message);\\n }\\n },\\n };\\n },\\n});\\n\\n\\n入参和返回的参数类型:\\n\\nexport interface BuildPlatformResult {\\n status: 'success' | 'fail';\\n message: string | Error | null;\\n}\\n\\n\\n\\n调试钩子\\n\\n在执行 dev 命令的时候,会按照顺序触发以下 Hooks:\\n\\n * registerDev: 在获取调试功能信息的时候触发。\\n * beforeDev: 开始执行调试整体流程之前触发。\\n * beforeDevMenu: 出现调试列表/菜单之前触发。\\n * afterDevMenu: 选择调试列表/菜单选项后触发。\\n * beforeDevTask: 执行调试任务之前触发。\\n * afterDev: 执行 dev 整体流程最后触发。\\n\\n\\nREGISTERDEV\\n\\n注册调试工具相关的数据。主要包含:\\n\\n * 调试工具的名称\\n * 显示在菜单列表中的项目名称以及对应的值。\\n * dev 子命令的定义。\\n * 是否在运行调试任务之前执行源码构建\\n * 执行调试任务的函数。\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n registerDev() {\\n return {\\n // 调试工具名称\\n name: 'storybook',\\n // 菜单显示内容\\n menuItem: {\\n name: 'Storybook',\\n value: 'storybook',\\n },\\n // 定义的 dev 子命令\\n subCommands: ['storybook', 'story'],\\n async action() {\\n // dev logic\\n },\\n };\\n },\\n };\\n },\\n});\\n\\n\\n入参和返回的参数类型:\\n\\nexport interface DevToolData {\\n name: string;\\n subCommands?: string[];\\n menuItem?: {\\n name: string;\\n value: string;\\n };\\n // 在 dev 命令执行之前,是否关闭源码构建\\n disableRunBuild?: boolean;\\n action: (\\n options: { port?: string },\\n context: { isTsProject?: boolean },\\n ) => void | Promise<void>;\\n}\\n\\n\\n在调试项目的时候,如果仅需要对代码功能进行调试的话,也许可以设置 disableRunBuild: true 来关闭对于源码执行(监听模式下的)构建任务。\\n\\n目前支持的 Storybook 调试支持将源码产物作为调试对象,因此在 Storybook 插件中 disableRunBuild: false。\\n\\n\\nBEFOREDEV\\n\\n在收集完所有调试工具元数据后,执行 dev 任务之前触发。\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n beforeDev(metas: DevToolData[]) {\\n console.info(`have ${metas.length} dev tools`);\\n },\\n };\\n },\\n});\\n\\n\\n入参和返回的参数类型:\\n\\nexport interface DevToolData {\\n name: string;\\n subCommands?: string[];\\n menuItem?: {\\n name: string;\\n value: string;\\n };\\n // 在 dev 命令执行之前,是否关闭源码构建\\n disableRunBuild?: boolean;\\n action: (\\n options: { port?: string },\\n context: { isTsProject?: boolean },\\n ) => void | Promise<void>;\\n}\\n\\n\\n\\n(BEFORE|AFTER)DEVMENU\\n\\nbeforeDevMenu 在出现调试列表/菜单之前触发。接收 inquirer question 作为参数。默认值为:\\n\\nconst question = [\\n {\\n name: 'choiceDevTool',\\n message: '选择调试工具',\\n type: 'list',\\n // 注册的调试信息\\n choices,\\n },\\n];\\n\\n\\nafterDevMenu 选择调试列表/菜单选项后触发。\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n beforeDevMenu(questions) {\\n questions[0].message += '!';\\n return questions; // required\\n },\\n afterDevMenu(options: Options) {\\n console.info(`choise ${options.result.choiceDevTool} dev tools`);\\n },\\n };\\n },\\n});\\n\\n\\n入参和返回的参数类型:\\n\\nexport type { QuestionCollection } from 'inquirer';\\n\\nexport interface Options {\\n result: PromptResult;\\n devTools: DevToolData[];\\n}\\n\\nexport type PromptResult = { choiceDevTool: string };\\nexport interface DevToolData {\\n name: string;\\n subCommands?: string[];\\n menuItem?: {\\n name: string;\\n value: string;\\n };\\n // 在 dev 命令执行之前,是否关闭源码构建\\n disableRunBuild?: boolean;\\n action: (\\n options: { port?: string },\\n context: { isTsProject?: boolean },\\n ) => void | Promise<void>;\\n}\\n\\n\\n\\nBEFOREDEVTASK\\n\\n执行调试任务之前触发。\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n beforeDevTask(currentDevData: DevToolData) {\\n console.info(`${currentDevData.name} running`);\\n },\\n };\\n },\\n});\\n\\n\\n入参和返回的参数类型:\\n\\nexport interface DevToolData {\\n name: string;\\n subCommands?: string[];\\n menuItem?: {\\n name: string;\\n value: string;\\n };\\n // 在 dev 命令执行之前,是否关闭源码构建\\n disableRunBuild?: boolean;\\n action: (\\n options: { port?: string },\\n context: { isTsProject?: boolean },\\n ) => void | Promise<void>;\\n}\\n\\n\\n\\nAFTERDEV\\n\\n在中断调试任务进程时触发。\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n afterDev() {\\n console.info(`exit!`);\\n },\\n };\\n },\\n});\\n\",\"frontmatter\":{}},{\"title\":\"处理静态资源文件\",\"routePath\":\"/guide/advance/asset\",\"toc\":[{\"id\":\"默认行为\",\"text\":\"默认行为\",\"depth\":2},{\"id\":\"设置-cdn-前缀\",\"text\":\"设置 CDN 前缀\",\"depth\":2},{\"id\":\"svgr-3\",\"text\":\"SVGR\",\"depth\":2}],\"content\":\"处理静态资源文件\\n\\n模块工程会对代码中使用的静态资源进行处理。如果需要配置,则可以使用 buildConfig.asset API。\\n\\n\\n默认行为\\n\\n默认情况下,模块工程对于以下静态资源会进行处理:\\n\\n * '.svg'、'.png'、'.jpg'、'.jpeg'、'.gif'、'.webp'\\n * '.ttf'、'.otf'、'.woff'、'.woff2'、'.eot'\\n * '.mp3'、'.mp4'、'.webm'、'.ogg'、'.wav'、'.flac'、'.aac'、'.mov'\\n\\n对于静态文件的处理,模块工程目前支持的功能有:\\n\\n * 设置静态资源路径为 ./assets。\\n * 对于超过 10kb 的文件会内联到代码中。\\n * 对于 .svg 后缀的文件使用 SVGR。\\n\\n让我们看下面的例子:\\n\\n<CH.Spotlight>\\n\\n\\n//...\\n\\n\\n--------------------------------------------------------------------------------\\n\\n项目源代码。\\n\\n\\n//...\\n\\n\\n--------------------------------------------------------------------------------\\n\\n如果 bg.png 的大小小于 10 kb,则此时产物目录结构和产物内容为。\\n\\n<CH.Code>\\n\\n./dist\\n└── asset.js\\n\\n\\n--------------------------------------------------------------------------------\\n\\nvar bg_default = 'data:image/png;base64,';\\nconsole.info(bg_default);\\n\\n\\n</CH.Code>\\n\\n如果 bg.png 的大小大于 10 kb,则此时产物目录结构和产物内容为。\\n\\n<CH.Code>\\n\\n./dist\\n├── asset.js\\n└── assets\\n └── bg.13e2aba2.png\\n\\n\\n--------------------------------------------------------------------------------\\n\\nvar bg_default = 'assets/bg.13e2aba2.png';\\nconsole.info(bg_default);\\n\\n\\n</CH.Code>\\n\\n</CH.Spotlight>\\n\\n当想要修改默认行为的时候,可以使用以下 API:\\n\\n * asset.path:修改静态资源文件输出路径。\\n * asset.limit:修改内联静态资源文件的阈值。\\n\\n\\n设置 CDN 前缀\\n\\n如果项目运行的环境是在浏览器下,我们有可能需要静态资源托管至 CDN,然后在生产环境使用。\\n\\n那么此时默认生成的构建产物中,我们需要在静态资源文件的路径前面增加 CDN 的基础路径。还是看一个例子:\\n\\n<CH.Spotlight>\\n\\n\\n//...\\n\\n\\n--------------------------------------------------------------------------------\\n\\n项目源代码。\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\nmodern.config 配置为。\\n\\nexport default defineConfig({\\n buildConfig: {\\n format: 'umd',\\n asset: {\\n publicPath: 'https://cdn/',\\n },\\n },\\n});\\n\\n\\n--------------------------------------------------------------------------------\\n\\n如果 bg.png 的大小大于 10 kb,则此时产物内容为。\\n\\n(function (global, factory) {\\n if (typeof module === 'object' && typeof module.exports === 'object')\\n factory();\\n else if (typeof define === 'function' && define.amd) define([], factory);\\n else if (\\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self)\\n )\\n factory();\\n})(this, function () {\\n 'use strict';\\n var bg_default = 'http://cdn/assets/bg.13e2aba2.png';\\n // src/asset.tsx\\n console.info(bg_default);\\n});\\n\\n\\n</CH.Spotlight>\\n\\n\\nSVGR\\n\\nWIP\",\"frontmatter\":{\"sidebar_position\":7}},{\"title\":\"构建 umd 产物\",\"routePath\":\"/guide/advance/build-umd\",\"toc\":[{\"id\":\"umd-产物的第三方依赖处理\",\"text\":\"umd 产物的第三方依赖处理\",\"depth\":2},{\"id\":\"更改项目的全局变量名称\",\"text\":\"更改项目的全局变量名称\",\"depth\":2}],\"content\":\"构建 UMD 产物\\n\\numd 全称为 Universal Module Definition,这种格式的 JS 文件可以运行在多个运行环境:\\n\\n * 浏览器环境:基于 AMD 规范进行模块加载\\n * Node.js 环境:基于 CommonJS 进行模块加载\\n * 其他情况:将模块挂载在全局对象上。\\n\\n因此我们可以通过下面的方式,将项目的构建产物指定为 umd 产物:\\n\\nexport default defineConfig({\\n buildConfig: {\\n format: 'umd',\\n },\\n});\\n\\n\\n\\nUMD 产物的第三方依赖处理\\n\\n在 【如何处理第三方依赖】 章节中,我们知道可以通过 autoExternals 和 externals API 来控制项目是否对第三方依赖打包。 因此在构建\\numd 产物的过程中,我们也可以这样使用:\\n\\n<CH.Spotlight>\\n\\n{\\n \\\"dependencies\\\": {\\n \\\"react\\\": \\\"^17\\\"\\n //...other dependencies\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n如果项目依赖了 react。\\n\\n{\\n \\\"dependencies\\\": {\\n \\\"react\\\": \\\"^17\\\"\\n //...other dependencies\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nmodern.config.ts 配置。\\n\\nexport default defineConfig({\\n buildConfig: {\\n format: 'umd',\\n autoExternal: false,\\n externals: ['react'],\\n },\\n});\\n\\n\\n--------------------------------------------------------------------------------\\n\\n当源码中使用了 react 依赖。\\n\\n\\nconsole.info(React);\\n\\n\\n--------------------------------------------------------------------------------\\n\\n此时产物中不会将 react 代码打包到产物中。\\n\\n(function (global, factory) {\\n if (typeof module === 'object' && typeof module.exports === 'object')\\n factory(exports, require('react'));\\n else if (typeof define === 'function' && define.amd)\\n define(['exports', 'react'], factory);\\n else if (\\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self)\\n )\\n factory((global.index = {}), global.react);\\n})(this, function (exports, _react) {\\n 'use strict';\\n Object.defineProperty(exports, '__esModule', {\\n value: true,\\n });\\n _react = /*#__PURE__*/ _interopRequireDefault(_react);\\n function _interopRequireDefault(obj) {\\n return obj && obj.__esModule\\n ? obj\\n : {\\n default: obj,\\n };\\n }\\n console.info(_react.default);\\n});\\n\\n\\n</CH.Spotlight>\\n\\n通过上面的例子我们知道,当使用 autoExternal 和 externals API 后:\\n\\n * 在 Node.js 环境下,可以通过 require('react') 获取 react 依赖。\\n * 在 浏览器环境下,可以通过 global.react 获取 react 依赖。\\n\\n然而在浏览器环境下,获取第三方依赖的时候,全局变量名称不一定与依赖名称完全相同,此时就要使用 buildConfig.umdGlobals API。\\n\\n还是使用之前的例子,当 react 依赖以 windows.React 或者 global.React 全局变量的形式存在于浏览器环境下,那么此时:\\n\\n<CH.Spotlight>\\n\\n{\\n \\\"devDependencies\\\": {\\n \\\"react\\\": \\\"^17\\\"\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n如果项目依赖了 react。\\n\\n{\\n \\\"devDependencies\\\": {\\n \\\"react\\\": \\\"^17\\\"\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nmodern.config.ts 配置。\\n\\nexport default defineConfig({\\n buildConfig: {\\n format: 'umd',\\n umdGlobals: {\\n react: 'React',\\n },\\n },\\n});\\n\\n\\n--------------------------------------------------------------------------------\\n\\n当源码中使用了 react 依赖。\\n\\n\\nconsole.info(React);\\n\\n\\n--------------------------------------------------------------------------------\\n\\n此时我们会看到这样的产物代码。\\n\\n(function (global, factory) {\\n if (typeof module === 'object' && typeof module.exports === 'object')\\n factory();\\n else if (typeof define === 'function' && define.amd) define([], factory);\\n else if (\\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self)\\n )\\n factory();\\n})(this, function () {\\n // ...\\n // libuild:globals:react\\n var require_react = __commonJS({\\n 'libuild:globals:react'(exports, module1) {\\n module1.exports = Function('return this')()['React'];\\n },\\n });\\n // src/index.ts\\n var import_react = __toESM(require_react());\\n console.info(import_react.default);\\n});\\n\\n\\n</CH.Spotlight>\\n\\n此时项目就可以运行在浏览器中,并使用存在于全局对象上的 React 变量了。\\n\\n\\n更改项目的全局变量名称\\n\\n当我们将下面的代码打包成 umd 产物并运行在浏览器的时候,我们可以通过 window.index 来使用该模块。\\n\\nexport default () => {\\n console.info('hello world');\\n};\\n\\n\\n默认情况下,以源码文件名称作为该模块在浏览器里全局变量的名称。对于上面的例子,其产物内容如下:\\n\\n(function (global, factory) {\\n if (typeof module === 'object' && typeof module.exports === 'object')\\n factory(exports);\\n else if (typeof define === 'function' && define.amd)\\n define(['exports'], factory);\\n else if (\\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self)\\n )\\n factory((global.index = {}));\\n})(this, function (exports) {\\n //...\\n});\\n\\n\\n如果需要修改它,则需要使用 buildConfig.umdModuleName API。\\n\\n当使用该 API 后:\\n\\nexport default defineConfig({\\n buildConfig: {\\n format: 'umd',\\n umdModuleName: 'myLib',\\n },\\n});\\n\\n\\n此时构建产物的内容为:\\n\\n(function (global, factory) {\\n if (typeof module === 'object' && typeof module.exports === 'object')\\n factory(exports);\\n else if (typeof define === 'function' && define.amd)\\n define(['exports'], factory);\\n else if (\\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self)\\n )\\n factory((global.myLib = {}));\\n})(this, function (exports) {\\n //...\\n});\\n\",\"frontmatter\":{\"sidebar_position\":5}},{\"title\":\"使用 Copy 工具\",\"routePath\":\"/guide/advance/copy\",\"toc\":[{\"id\":\"了解-copy-api\",\"text\":\"了解 Copy API\",\"depth\":2},{\"id\":\"api-详解\",\"text\":\"API 详解\",\"depth\":2},{\"id\":\"不同场景使用示例-1\",\"text\":\"不同场景使用示例\",\"depth\":2},{\"id\":\"将文件复制文件-1\",\"text\":\"将文件复制文件\",\"depth\":3},{\"id\":\"将文件复制到目录-1\",\"text\":\"将文件复制到目录\",\"depth\":3},{\"id\":\"从目录复制到目录-1\",\"text\":\"从目录复制到目录\",\"depth\":3},{\"id\":\"从目录到文件-1\",\"text\":\"从目录到文件\",\"depth\":3},{\"id\":\"使用-glob-1\",\"text\":\"使用 Glob\",\"depth\":3}],\"content\":\"使用 COPY 工具\\n\\n模块工程提供了 Copy 工具用于将已经存在的单个文件或整个目录复制到产物目录中。接下来我们学习如何使用它。\\n\\n\\n了解 COPY API\\n\\n我们可以通过 buildConfig.copy API 来使用 Copy 工具,它包含以下两个主要配置:\\n\\n * patterns\\n * options\\n\\n在开始学习之前可以先花一些时间了解它们。\\n\\n\\nAPI 详解\\n\\ncopy.patterns 用于寻找复制的文件以及配置输出的路径。\\n\\n其中 patterns.from 用于指定要复制的文件或者目录。它接收 Glob 形式字符串或具体路径。Glob 形式字符串是指 fast-glob\\npattern-syntax。因此我们可以按照如下两种方式使用它:\\n\\nexport default defineConfig({\\n buildConfig: {\\n copy: {\\n patterns: [\\n { from: './index.html', to: '' },\\n { from: './*.html', to: '' },\\n ],\\n },\\n },\\n});\\n\\n\\npatterns.context 一般和 patterns.from 配合使用,默认情况下它的值与 buildConfig.sourceDir\\n相同,因此我们可以按照如下方式指定 src/data.json 文件为要复制的文件:\\n\\n> 默认情况下,buildConfig.sourceDir 为 src\\n\\nexport default defineConfig({\\n buildConfig: {\\n copy: {\\n patterns: [\\n { from: './data.json' to: ''},\\n ],\\n },\\n },\\n});\\n\\n\\n当指定的文件不在源码目录的时候,可以修改 context 配置。例如指定项目目录下的 temp/index.html 为要复制的文件:\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n copy: {\\n patterns: [\\n {\\n from: './index.html',\\n context: path.join(__dirname, './temp')\\n to: '',\\n }\\n ],\\n },\\n },\\n});\\n\\n\\npatterns.to 用于指定复制文件的输出路径,默认情况下它的值为 buildConfig.outDir对应的值。因此我们按照如下方式将\\nsrc/index.html 复制到 dist 目录下:\\n\\nexport default defineConfig({\\n buildConfig: {\\n copy: {\\n patterns: [{ from: './index.html' }],\\n },\\n },\\n});\\n\\n\\n当我们配置了 patterns.to 的时候:\\n\\n * 如果是相对路径,则该路径会相对于 buildConfig.outDir 计算出复制文件输出的绝对路径。\\n * 如果是绝对路径,则会直接使用该值。\\n\\n最后 patterns.globOptions 用于配置寻找复制文件 globby 对象,其配置可参考:\\n\\n * globby.options\\n\\n\\n不同场景使用示例\\n\\n\\n将文件复制文件\\n\\nexport default defineConfig({\\n buildConfig: [\\n {\\n outDir: 'dist',\\n copy: {\\n patterns: [\\n /**\\n * copy file to file\\n */\\n {\\n from: './temp-1/a.png',\\n context: __dirname,\\n to: './temp-1/b.png',\\n },\\n ],\\n },\\n },\\n ],\\n});\\n\\n\\n\\n将文件复制到目录\\n\\nexport default defineConfig({\\n buildConfig: [\\n {\\n outDir: 'dist',\\n copy: {\\n patterns: [\\n /**\\n * copy file to dir\\n */\\n {\\n from: './temp-2/a.png',\\n context: __dirname,\\n to: './temp-2',\\n },\\n ],\\n },\\n },\\n ],\\n});\\n\\n\\n\\n从目录复制到目录\\n\\nexport default defineConfig({\\n buildConfig: [\\n {\\n outDir: 'dist',\\n copy: {\\n patterns: [\\n /**\\n * copy dir to dir\\n */\\n {\\n from: './temp-3/',\\n to: './temp-3',\\n context: __dirname,\\n },\\n ],\\n options: {\\n enableCopySync: true,\\n },\\n },\\n },\\n ],\\n});\\n\\n\\n\\n从目录到文件\\n\\nexport default defineConfig({\\n buildConfig: [\\n {\\n outDir: 'dist',\\n copy: {\\n patterns: [\\n /**\\n * copy dir to file\\n */\\n {\\n from: './temp-4/',\\n context: __dirname,\\n to: './temp-4/_index.html',\\n },\\n ],\\n options: {\\n enableCopySync: true,\\n },\\n },\\n },\\n ],\\n});\\n\\n\\n\\n使用 GLOB\\n\\nexport default defineConfig({\\n buildConfig: [\\n {\\n outDir: 'dist',\\n copy: {\\n patterns: [\\n /**\\n * copy glob to dir\\n */\\n {\\n from: './*.html',\\n to: './temp-5',\\n },\\n ],\\n options: {\\n enableCopySync: true,\\n },\\n },\\n },\\n {\\n copy: {\\n patterns: [\\n /**\\n * copy glob to file\\n */\\n {\\n from: './*.html',\\n to: './temp-6/index.html',\\n },\\n ],\\n options: {\\n enableCopySync: true,\\n },\\n },\\n },\\n ],\\n});\\n\",\"frontmatter\":{\"sidebar_position\":3}},{\"title\":\"如何处理第三方依赖\",\"routePath\":\"/guide/advance/external-dependency\",\"toc\":[{\"id\":\"第三方依赖的默认处理\",\"text\":\"第三方依赖的默认处理\",\"depth\":2},{\"id\":\"打包第三方依赖\",\"text\":\"打包第三方依赖\",\"depth\":2},{\"id\":\"关闭默认行为\",\"text\":\"关闭默认行为\",\"depth\":3},{\"id\":\"排除指定第三方依赖\",\"text\":\"排除指定第三方依赖\",\"depth\":3}],\"content\":\"如何处理第三方依赖\\n\\n一般来说,项目所需要的第三方依赖可以通过包管理器的 install 命令安装,在安装第三方依赖成功后,这些第三方依赖一般会出现在项目 package.json\\n的 dependencies 和 devDependencies 下。\\n\\n{\\n \\\"dependencies\\\": {},\\n \\\"devDependencies\\\": {}\\n}\\n\\n\\n而 \\\"dependencies\\\" 下的依赖通常来说是和项目代码以及构建相关的,如果这些第三方依赖声明在 \\\"devDependencies\\\"\\n下,那么在生产环境下就会出现缺失依赖的问题。\\n\\n除了 \\\"dependencies\\\" 以外,\\\"peerDependencies\\\" 也可以声明在生产环境下需要的依赖,不过它更强调项目在运行环境下存在\\n\\\"peerDependencies\\\" 声明的这些依赖,这类似于插件这样的机制。\\n\\n\\n第三方依赖的默认处理\\n\\n在模块工程里,默认情况下不会对\\\"dependencies\\\" 以及 \\\"peerDependencies\\\" 下的第三方依赖进行打包处理,因此:\\n\\n<CH.Spotlight>\\n\\n{\\n \\\"dependencies\\\": {\\n \\\"react\\\": \\\"^17\\\"\\n },\\n // or\\n \\\"peerDependencies\\\": {\\n \\\"react\\\": \\\"^17\\\"\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n如果项目依赖了 react。\\n\\n{\\n \\\"dependencies\\\": {\\n \\\"react\\\": \\\"^17\\\"\\n },\\n // or\\n \\\"peerDependencies\\\": {\\n \\\"react\\\": \\\"^17\\\"\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n当源码中使用了 react 依赖。\\n\\n\\nconsole.info(React);\\n\\n\\n--------------------------------------------------------------------------------\\n\\n此时产物中不会将 react 代码打包到产物中。\\n\\n\\nconsole.info(React);\\n\\n\\n</CH.Spotlight>\\n\\n\\n打包第三方依赖\\n\\n不过也有一些情况希望将这些第三方依赖打包到产物。将第三方依赖打包到产物的好处是:减少下载第三方依赖所花费的时间。\\n\\n这种处理第三方依赖的方式一般在开发命令行工具中比较常见,这可以提升命令行工具的加载速度,给使用者带来更好的使用体验。\\n\\n那么如何在模块工程中开启对于第三方依赖的打包处理呢?\\n\\n在构建配置中提供了以下 API 来处理第三方依赖:\\n\\n * buildConfig.autoExternal\\n * buildConfig.externals\\n\\n\\n关闭默认行为\\n\\n当我们希望关闭对于第三方依赖的默认处理行为时候,可以通过以下方式来实现:\\n\\nexport default defineConfig({\\n buildConfig: {\\n autoExternal: false,\\n },\\n});\\n\\n\\n这样对于 \\\"dependencies\\\" 和 \\\"peerDependencies\\\" 下面的依赖都会进行打包处理。如果只想要关闭其中某个下面的依赖处理,则可以使用\\nbuildConfig.autoExternal 的对象形式:\\n\\nexport default defineConfig({\\n buildConfig: {\\n autoExternal: {\\n dependencies: false,\\n peerDependencies: false,\\n },\\n },\\n});\\n\\n\\n\\n排除指定第三方依赖\\n\\n而除了 buildConfig.autoExternal API 以外,buildConfig.externals\\n也可以控制哪些第三方依赖要进行处理。我们可以组合这两个 API 对项目的依赖进行更细微的处理。\\n\\n例如当我们需要仅对某些依赖不进行打包处理的时候,可以按照如下方式进行配置:\\n\\n> 一般这种情况,可能是某些依赖不适合进行打包处理。如果遇到这种情况,则可以按照下面的方式进行处理。\\n\\nepxort default defineConfig({\\n buildConfig: {\\n autoExternal: false,\\n externals: ['pkg-1', /pkg-2/],\\n }\\n});\\n\",\"frontmatter\":{\"sidebar_position\":4}},{\"title\":\"深入理解构建\",\"routePath\":\"/guide/advance/in-depth-about-build\",\"toc\":[{\"id\":\"深入理解-buildconfig-2\",\"text\":\"深入理解 buildConfig\",\"depth\":2},{\"id\":\"bundle-和-bundleless-2\",\"text\":\"Bundle 和 Bundleless\",\"depth\":3},{\"id\":\"input-与-sourcedir-的关系-2\",\"text\":\"input 与 sourceDir 的关系\",\"depth\":3},{\"id\":\"input-的对象模式\",\"text\":\"input 的对象模式\",\"depth\":4},{\"id\":\"sourcedir-3\",\"text\":\"sourceDir\",\"depth\":4},{\"id\":\"类型文件\",\"text\":\"类型文件\",\"depth\":3},{\"id\":\"关闭类型生成\",\"text\":\"关闭类型生成\",\"depth\":4},{\"id\":\"打包类型文件\",\"text\":\"打包类型文件\",\"depth\":4},{\"id\":\"别名转换\",\"text\":\"别名转换\",\"depth\":4},{\"id\":\"一些-dts-的使用示例\",\"text\":\"一些 dts 的使用示例\",\"depth\":4},{\"id\":\"buildconfigdefine-不同场景的使用方式\",\"text\":\"buildConfig.define 不同场景的使用方式\",\"depth\":3},{\"id\":\"环境变量替换\",\"text\":\"环境变量替换\",\"depth\":4},{\"id\":\"全局变量替换\",\"text\":\"全局变量替换\",\"depth\":4},{\"id\":\"构建过程-2\",\"text\":\"构建过程\",\"depth\":2},{\"id\":\"构建报错\",\"text\":\"构建报错\",\"depth\":2}],\"content\":\"深入理解构建\\n\\n在【基础使用】的部分,我们已经知道可以通过 buildConfig 配置对项目的输出产物进行修改。buildConfig\\n不仅描述了产物的一些特性,同时还为构建产物提供了一些功能。\\n\\n如果你还不清楚 buildConfig 是什么,建议花一些时间通过下面的链接了解一下:\\n\\n * 【修改输出产物】\\n\\n而在本章里我们将要深入理解某些构建配置的使用以及了解执行 modern build 命令的时候发生了什么。\\n\\n\\n深入理解 BUILDCONFIG\\n\\n\\nBUNDLE 和 BUNDLELESS\\n\\n那么首先我们来了解一下 Bundle 和 Bundleless。\\n\\n所谓 Bundle 是指对构建产物进行打包,构建产物可能是一个文件,也有可能是基于一定的代码拆分策略得到的多个文件。\\n\\n而 Bundleless 则是指对每个源文件单独进行编译构建,但是并不将它们打包在一起。每一个产物文件都可以找到与之相对应的源码文件。Bundleless\\n构建的过程,也可以理解为仅对源文件进行代码转换的过程。\\n\\n在 buildConfig 中可以通过 buildConfig.buildType 来指定当前构建任务是 Bundle 还是 Bundleless。\\n\\n\\nINPUT 与 SOURCEDIR 的关系\\n\\nbuildConfig.input 用于指定读取源码的文件路径或者目录路径,其默认值在 Bundle 和 Bundleless 构建过程中有所不同:\\n\\n * 当 buildType: 'bundle' 的时候,input 默认值为 ['src/index.ts']\\n * 当 buildType: 'bundleless' 的时候,input 默认值为 ['src']\\n \\n > 实际上,在 buildType: 'bundle' 的时候,构建工具会检测是否存在符合 src/index.(j|t)sx?\\n > 这个名称规则的文件,并将其作为入口文件。\\n\\n建议不要在 Bundleless 构建过程中指定多个源码文件目录,可能出现不符合预期的结果。目前多个源码目录的 Bundleless 构建还处于不稳定阶段。\\n\\n从默认值上我们可以知道:Bundle 构建一般可以指定文件路径作为构建的入口,而 Bundleless 构建则更期望使用目录路径寻找源文件。\\n\\nINPUT 的对象模式\\n\\n在 Bundle 构建过程中,除了将 input\\n设置为一个数组,也可以将它设置为一个对象。通过使用对象的形式,我们可以修改构建产物输出的文件名称。那么对于下面的例子,./src/index.ts\\n对应的构建产物文件路径为 ./dist/main.js。\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n input: {\\n main: ['./src/index.ts'],\\n },\\n outDir: './dist',\\n },\\n});\\n\\n\\n而在 Bundleless 构建过程中,虽然同样支持这样的使用方式,但是并不推荐。\\n\\nSOURCEDIR\\n\\nsourceDir 用于指定源码目录,它主要与以下两个内容有关系:\\n\\n * 类型文件生成\\n * 指定构建过程中的 outbase\\n\\n一般来说:\\n\\n * 在 Bundleless 构建过程中,sourceDir 与 input 的值要保持一致,它们的默认值都是 src。\\n * 在 Bundle 构建过程中,很少需要使用 sourceDir。\\n\\n\\n类型文件\\n\\nbuildConfig.dts 配置主要用于类型文件的生成。\\n\\n关闭类型生成\\n\\n默认情况下类型生成功能是开启的,如果需要关闭的话,可以按照如下配置:\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n dts: false,\\n },\\n});\\n\\n\\n关闭类型文件后,一般来说构建速度会有所提升。\\n\\n打包类型文件\\n\\n在 buildType: 'bundleless' 的时候,类型文件的生成是使用项目的 tsc 命令来完成生产。\\n\\n模块工程解决方案同时还支持对类型文件进行打包,不过使用该功能的时候需要注意:\\n\\n * 一些第三方依赖存在错误的语法会导致打包过程失败。因此对于这种情况,需要手动通过 buildConfig.externals 将这类第三方包排除。\\n * 对于第三方依赖的类型文件指向的是一个 .ts 文件的情况,目前无法处理。比如第三方依赖的 package.json 中存在这样的内容: {\\\"types\\\":\\n \\\"./src/index.ts\\\"}。\\n\\n别名转换\\n\\n在 Bundleless 构建过程中,如果源代码中出现了别名,例如:\\n\\n\\n\\n正常来说,使用 tsc 生成的产物类型文件也会包含这些别名。不过 Module Tools 会对 tsc 生成的类型文件里的别名进行转换处理:\\n\\n * 对于类似 `` 这样形式的代码可以进行别名转换。\\n * 对于类似 export { utils } from '@common/utils' 这样形式的代码可以进行别名转换。\\n\\n然而也存在一些情况,目前还无法处理:\\n\\n * 对于类似 Promise<import('@common/utils')> 这样形式的输出类型目前无法进行转换。\\n\\n一些 DTS 的使用示例\\n\\n一般使用方式:\\n\\n\\n\\nexport default defineConfig({\\n // 此时打包的类型文件输出路径为 `./dist/types`\\n buildConfig: {\\n buildType: 'bundle',\\n dts: {\\n tsconfigPath: './other-tsconfig.json',\\n distPath: './types',\\n },\\n outDir: './dist',\\n },\\n});\\n\\n\\n使用 dts.only 的情况:\\n\\n\\n\\nexport default defineConfig({\\n // 此时类型文件没有进行打包,输出路径为 `./dist/types`\\n buildConfig: [\\n {\\n buildType: 'bundle',\\n dts: false,\\n outDir: './dist',\\n },\\n {\\n buildType: 'bundleless',\\n dts: {\\n only: true,\\n },\\n outDir: './dist/types',\\n },\\n ],\\n});\\n\\n\\n\\nBUILDCONFIG.DEFINE 不同场景的使用方式\\n\\nbuildConfig.define 功能有些类似 webpack.DefinePlugin。这里介绍几个使用场景:\\n\\n环境变量替换\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n define: {\\n 'process.env.VERSION': JSON.stringify(process.env.VERSION || '0.0.0'),\\n },\\n },\\n});\\n\\n\\n通过上面的配置,我们就可以将下面这段代码:\\n\\n// 编译前代码\\nconsole.log(process.env.VERSION);\\n\\n\\n在执行 VERSION=1.0.0 modern build 的时候,转换为:\\n\\n// 编译后代码\\nconsole.log('1.0.0');\\n\\n\\n全局变量替换\\n\\n\\nexport default defineConfig({\\n buildConfig: {\\n define: {\\n VERSION: JSON.stringify(require('./package.json').version || '0.0.0'),\\n },\\n },\\n});\\n\\n\\n通过上面的配置,我们就可以将下面这段代码:\\n\\n// 编译前代码\\nconsole.log(VERSION);\\n\\n\\n转换为:\\n\\n// 编译后代码\\nconsole.log('1.0.0');\\n\\n\\n不过要注意:如果项目是一个 TypeScript 项目,那么你可能需要在项目源代码目录下的 .d.ts 文件里增加以下内容:\\n\\n> 如果不存在 d.ts 文件,则可以手动创建。\\n\\ndeclare const YOUR_ADD_GLOBAL_VAR;\\n\\n\\n\\n构建过程\\n\\n当执行 modern build 命令的时候,会发生\\n\\n * 根据 buildConfig.outDir 清理产物目录。\\n * 编译 js/ts 源代码生成 Bundle/Bundleless 的 JS 构建产物。\\n * 使用 tsc 生成 Bundle/Bundleless 的类型文件。\\n * 处理 Copy 任务。\\n\\n\\n构建报错\\n\\n当发生构建报错的时候,基于以上了解到的信息,可以很容易的明白在终端出现的报错内容:\\n\\njs 或者 ts 构建的报错:\\n\\nerror ModuleBuildError:\\n\\n╭───────────────────────╮\\n│ bundle failed: │\\n│ - format is \\\"cjs\\\" │\\n│ - target is \\\"esnext\\\" │\\n╰───────────────────────╯\\n\\nDetailed Information:\\n\\n\\n类型文件生成过程的报错:\\n\\nerror ModuleBuildError:\\n\\nbundle DTS failed:\\n\\n\\n对于 js/ts 构建错误,我们可以从报错信息中知道:\\n\\n * 通过 'bundle failed:' 来判断报错的是 Bundle 构建还是 Bundleless 构建?\\n * 构建过程的 format 是什么?\\n * 构建过程的 target 是什么?\\n * 具体的报错信息。\",\"frontmatter\":{\"sidebar_position\":1}},{\"title\":\"深入理解 dev 命令\",\"routePath\":\"/guide/advance/in-depth-about-dev-command\",\"toc\":[{\"id\":\"深入理解-buildconfig-1\",\"text\":\"深入理解 buildConfig\",\"depth\":2},{\"id\":\"bundle-和-bundleless-1\",\"text\":\"Bundle 和 Bundleless\",\"depth\":3},{\"id\":\"input-与-sourcedir-的关系-1\",\"text\":\"input 与 sourceDir 的关系\",\"depth\":3},{\"id\":\"构建过程-1\",\"text\":\"构建过程\",\"depth\":2}],\"content\":\"深入理解 DEV 命令\\n\\n在【基础使用】的部分,我们已经知道可以通过 buildConfig 配置对项目的输出产物进行修改。buildConfig\\n不仅描述了产物的一些特性,同时还为构建产物提供了一些功能。\\n\\n如果你还不清楚 buildConfig 是什么,建议花一些时间通过下面的链接了解一下:\\n\\n * 【修改输出产物】\\n\\n而在本章里我们将要深入理解某些构建配置的使用以及了解执行 modern build 命令的时候发生了什么。\\n\\n\\n深入理解 BUILDCONFIG\\n\\n\\nBUNDLE 和 BUNDLELESS\\n\\n那么首先我们来理解一下 Bundle 和 Bundleless。\\n\\n所谓 Bundle 是指对构建产物进行打包,构建产物可能是一个文件,也有可能是基于一定的代码拆分策略得到的多个文件。\\n\\n而 Bundleless 则是指对每个源文件进行编译构建,但是并不将它们打包在一起。每一个产物文件都可以找到与之相对应的源码文件。\\n\\n\\nINPUT 与 SOURCEDIR 的关系\\n\\n\\n构建过程\",\"frontmatter\":{\"sidebar_position\":2}},{\"title\":\"主题配置\",\"routePath\":\"/guide/advance/theme-config\",\"toc\":[{\"id\":\"动机和原理\",\"text\":\"动机和原理\",\"depth\":2},{\"id\":\"使用示例\",\"text\":\"使用示例\",\"depth\":2},{\"id\":\"tailwindcss-3\",\"text\":\"tailwindcss\",\"depth\":3},{\"id\":\"html-类名\",\"text\":\"HTML 类名。\",\"depth\":4},{\"id\":\"apply-指令\",\"text\":\"@apply 指令\",\"depth\":4}],\"content\":\"主题配置\\n\\n模块工程通过 designSystem API,提供了配置主题的能力。\\n\\n\\n动机和原理\\n\\n主题配置有些类似组件库中的定制主题功能,主要用于样式开发中使用。我们可以通过 designSystem 配置在不同的样式开发环境下使用由它生成的\\ndesignToken。\\n\\n所谓 designToken 在不同的样式开发环境下对应不同的东西:\\n\\n * tailwindcss: 以 designSystem 作为 tailwindcss 的 theme 配置。因此可以使用:\\n * tailwindcss 支持的 HTML 类名。\\n * 在 css/less/sass 下通过 @apply 自定义指令使用与 tailwindcss 支持的 HTML 类名同名的字符串。\\n * css/less/scss: 通过 designSystem 生成全局的样式变量。\\n\\ndesignSystem API 的数据结构借鉴了 tailwindcss 配置对象中的 theme API,因此存在默认的一套\\ndesignToken。关于默认值,可以查看 designSystem API。\\n\\n目前暂时还未支持 css/less/sass 全局变量。\\n\\n\\n使用示例\\n\\n\\nTAILWINDCSS\\n\\n在使用 tailwindcss 的时候,可以通过 designSystem 来设置它的 theme 配置。\\n\\n例如在下面的配置中扩展了原有的颜色配置:\\n\\nexport default {\\n designSystem: {\\n extend: {\\n colors: {\\n primary: '#1677ff',\\n },\\n },\\n },\\n};\\n\\n\\n我们可以在代码中有两种使用 tailwindcss 的方式。\\n\\nHTML 类名。\\n\\nimport 'tailwindcss/utilities.css';\\n\\nexport default () => {\\n return <div className=\\\"bg-primary\\\"></div>;\\n};\\n\\n\\n@APPLY 指令\\n\\n关于 @apply。\\n\\n<CH.Code>\\n\\nimport './index.css';\\n\\nexport default () => {\\n return <div className=\\\"btn-primary\\\"></div>;\\n};\\n\\n\\n.btn-primary {\\n @apply bg-primary;\\n}\\n\\n\\n</CH.Code>\",\"frontmatter\":{\"sidebar_position\":6}},{\"title\":\"开始之前\",\"routePath\":\"/guide/basic/before-getting-started\",\"toc\":[{\"id\":\"环境准备\",\"text\":\"环境准备\",\"depth\":2},{\"id\":\"初识-npm\",\"text\":\"初识 npm\",\"depth\":2},{\"id\":\"npm-包类型项目\",\"text\":\"npm 包类型项目\",\"depth\":2},{\"id\":\"使用第三方-npm-包\",\"text\":\"使用第三方 npm 包\",\"depth\":2},{\"id\":\"还需要了解的-npm-零碎知识\",\"text\":\"还需要了解的 npm 零碎知识\",\"depth\":2},{\"id\":\"npm-包的程序入口\",\"text\":\"npm 包的程序入口\",\"depth\":3},{\"id\":\"scripts-1\",\"text\":\"\\\"scripts\\\"\",\"depth\":3},{\"id\":\"npm-install-1\",\"text\":\"npm install\",\"depth\":4},{\"id\":\"npm-publish-1\",\"text\":\"npm publish\",\"depth\":4},{\"id\":\"peerdependencies-3\",\"text\":\"peerDependencies\",\"depth\":3},{\"id\":\"npm-包管理器\",\"text\":\"npm 包管理器\",\"depth\":2},{\"id\":\"module-tools-配置文件\",\"text\":\"Module Tools 配置文件\",\"depth\":2}],\"content\":\"开始之前\\n\\n\\n环境准备\\n\\n为了使用 Modern.js 模块工程解决方案,首先需要 NodeJS,我们推荐最新的长期维护版本,并确保 Node 版本大于等于 14.17.6。因为非稳定的\\nNodeJS 时常有一些 Bug,你可以使用 nvm-windows 和 nvm(Mac/linux)安装,这样你就可以方便地切换到不同的 NodeJS\\n版本,这些版本可能会用于不同的项目。\\n\\n\\n初识 NPM\\n\\n当 NodeJS 被安装后,你不仅可以在命令行中访问 node 可执行程序,同时你也可以执行 npm 命令。\\n\\nnpm 是 NodeJS 的标准软件包管理器。它一开始的用途是用于下载和管理 NodeJS 包的依赖关系,但后来它逐渐变成为一个用于前端 JavaScript\\n的工具。\\n\\n如果你已经对 npm 和 npm 包的使用方式有所了解,那么可以直接跳到【npm 包管理器】部分。\\n\\n\\nNPM 包类型项目\\n\\n那么什么是 npm 包类型的项目呢?当我们在一个空的项目目录下执行 npm init 命令的时候,它会在当前目录下面创建一个文件名为 package.json\\n的 JSON 文件。在创建过程中,我们需要填写包括但不限于 npm 包的名称、版本号、描述等等内容,这些填写的内容都会在生成的 package.json\\n文件中找到:\\n\\n{\\n \\\"name\\\": \\\"npm-demo\\\",\\n \\\"version\\\": \\\"1.0.0\\\",\\n \\\"description\\\": \\\"\\\",\\n \\\"main\\\": \\\"index.js\\\",\\n \\\"scripts\\\": {\\n \\\"test\\\": \\\"echo \\\\\\\"Error: no test specified\\\\\\\" && exit 1\\\"\\n },\\n \\\"author\\\": \\\"\\\",\\n \\\"license\\\": \\\"ISC\\\"\\n}\\n\\n\\n此时这个包含了初始化后的 package.json 文件的项目就是一个 npm 包类型的项目,你可以执行 npm publish 命令将这个项目发布到 npm\\nRegistry。\\n\\nnpm Registry 是一个 npm 包存储的地方,开发者们不仅可以将他们自己的 npm 包发布到 npm Registry,还可以通过 npm\\nRegistry 使用其他开发者发布的 npm 包。\\n\\n优质的 npm 包会有更多的人去使用,因为它不仅节省了很多代码实现的工作,同时也不容易让项目出现问题。\\n\\n\\n使用第三方 NPM 包\\n\\n当要为初始化的项目增加第三方的 npm 包的时候,我们可以把这一过程叫做“为项目安装依赖”或是“为项目增加依赖”。在增加依赖之前,首先我们要特别了解一件事情\\n—— npm 依赖的软件包类型:\\n\\n * \\\"dependencies\\\":一种是你的应用程序在生产环境中需要的软件包。\\n * \\\"devDependencies\\\":另一种是仅在本地开发和测试中需要的软件包。\\n \\n > 软件包可以理解为是第三方的 npm 包。\\n\\n你可以通过执行 npm install npm-package-name 或者 npm add npm-package-name\\n的方式来安装在生产环境中需要的软件包,或者也可以在 package.json 文件中手动的将需要安装的包和对应的语义化版本写在 \\\"dependencies\\\"\\n里,并执行 npm install 命令:\\n\\n{\\n \\\"name\\\": \\\"your-npm-project\\\",\\n \\\"dependencies\\\": {\\n \\\"npm-package-name\\\": \\\"0.1.0\\\"\\n }\\n}\\n\\n\\n同理,你也可以执行 npm install npm-package-name --save-dev 或 npm add npm-package-name\\n--save-dev 的方式来安装仅在本地开发和测试中需要的软件包,或者也可以在 package.json 文件中手动的将需要安装的包和对应的语义化版本写在\\n\\\"devDependencies\\\" 里,并执行 npm install 命令:\\n\\n{\\n \\\"name\\\": \\\"your-npm-project\\\",\\n \\\"devDependencies\\\": {\\n \\\"npm-package-name\\\": \\\"0.1.0\\\"\\n }\\n}\\n\\n\\n在安装或者使用第三方 npm 包的时候一定要确定它们的用途,以及通过区分它们的类型确定好它们应该放在 \\\"dependencies\\\" 还是\\n\\\"devDependencies\\\" 中。\\n\\n一般来说,需要在源代码中使用到的包都属于 dependencies 依赖。除非你通过打包的方式将依赖的代码输出到本地,那么这种情况可以将它作为\\ndevDependencies 依赖。\\n\\n\\n还需要了解的 NPM 零碎知识\\n\\n\\nNPM 包的程序入口\\n\\n在 package.json 中存在一个 \\\"main\\\" 属性,它对应的值是一个模块 ID,或者更直观的说是一个 NodeJS 文件路径,它是你程序的主要入口。\\n\\n例如你的包名为 foo,并且用户安装了它,然后执行 require(\\\"foo\\\") 代码,那么 foo 这个 npm 包的 \\\"main\\\"\\n字段对应的文件将会被导出。\\n\\n推荐在你的 npm 包里一定要设置 \\\"main\\\" 字段。如果没有设置 \\\"main\\\",则默认入口为包的根目录下的 index.js 文件。\\n\\n除了需要设置 \\\"main\\\" 属性以外,一般还会设置 \\\"module\\\" 属性。它与 \\\"main\\\" 属性的用途类似,它主要是用于在 webpack\\n场景下使用。webpack 在大多数情况下,会以 \\\"module\\\" -> \\\"main\\\" 这个顺序读取 npm 包的入口(文件)。\\n\\n> 想要了解关于 webpack 如何做这件事,可以查看这个链接。\\n\\n\\n\\\"SCRIPTS\\\"\\n\\npackage.json 文件的 \\\"scripts\\\" 属性支持一些内置的脚本和 npm 预设的生命周期事件,以及任意的脚本。\\n\\n这些都可以通过运行 npm run-script <stage> 或简称 npm run <stage> 来执行。\\n\\n名称匹配的前置命令和后置命令也会被运行(例如 premyscript、myscript、postmyscript)。\\n\\n{\\n \\\"scripts\\\": {\\n \\\"premyscript\\\": \\\"\\\",\\n \\\"myscript\\\": \\\"\\\",\\n \\\"postmyscript\\\": \\\"\\\"\\n }\\n}\\n\\n\\n当执行 npm run myscripts 的时候,premyscripts 对应的脚本会在它之前执行,postmyscripts 对应的脚本会在它之后执行。\\n\\n来自依赖的脚本命令可以用 npm explore <pkg> -- npm run <stage> 运行。\\n\\n还有一些特殊的生命周期脚本(Life Scripts),只在某些情况下发生。这里介绍几个通常需要了解的情况。\\n\\nNPM INSTALL\\n\\n当你运行 npm install -g <pkg-name> 时,以下脚本会运行。\\n\\n * preinstall\\n * install\\n * postinstall\\n * prepublish\\n * preprepare\\n * prepare\\n * postprepare\\n\\n如果你的软件包根目录有一个 binding.gyp 文件,而你没有定义 install 或 preinstall 脚本,那么 npm 将以 node-gyp\\nrebuild 作为默认的 install 命令,使用 node-gyp 进行编译。\\n\\nNPM PUBLISH\\n\\n当发布项目的时候,执行该命令会触发以下脚本:\\n\\n * prepublishOnly\\n * prepack\\n * prepare\\n * postpack\\n * publish\\n * postpublish\\n\\n当以 --dry-run 模式运行的时候,prepare 对应的脚本将不会执行。\\n\\n\\nPEERDEPENDENCIES\\n\\n在某些情况下,你的 npm 项目与它的宿主工具或者库之间存在某种兼容关系(例如一个 webpack 插件项目和 webpack),同时你的 npm\\n项目不想将宿主作为必要的依赖,这个时候通常说明你的项目可能是这个宿主工具或者库的插件。你的 npm\\n项目会对宿主包的版本有一定的要求,因为只有在特定的版本下才会暴露出 npm 项目所需要的 API。\\n\\n关于更多 peerDependencies 的解释,可以通过下面的链接了解 npm、pnpm、Yarn 对于它的不同处理方式:\\n\\n * npm 对 peerDependencies 的解释\\n * pnpm vs npm VS Yarn\\n\\n\\nNPM 包管理器\\n\\n除了 npm 这种标准的包管理器以外,目前主流的还有 pnpm 和 Yarn,它们都是不错的 npm cli 替代品。\\n\\n推荐使用 pnpm 来管理项目依赖,可以通过下面的方式安装它:\\n\\nnpm install -g pnpm\\n\\n\\n\\nMODULE TOOLS 配置文件\\n\\n初始化的模块工程项目目录下提供了 Module Tools 的配置文件 —— modern.config.(j|t)s。默认情况下,不需要做任何配置,因此\\nmodern.config 配置文件不是必须存在的。\\n\\n初始化的配置文件的内容如下:\\n\\n// modern.config.ts\\n\\n\\nexport default defineConfig({});\\n\\n\\n// modern.config.js\\nconst { defineConfig } = require('@modern-js/module-tools');\\n\\nmodule.exports = defineConfig({});\\n\\n\\n我们推荐使用 defineConfig 函数,不过并不强制使用它。因此你也可以在配置文件中直接返回一个对象:\\n\\n// modern.config.ts\\nexport default {};\\n\\n\\n// modern.config.js\\nmodule.exports = {};\\n\",\"frontmatter\":{\"sidebar_position\":1}},{\"title\":\"命令预览\",\"routePath\":\"/guide/basic/command-preview\",\"toc\":[{\"id\":\"modern-build-1\",\"text\":\"modern build\",\"depth\":2},{\"id\":\"modern-new-1\",\"text\":\"modern new\",\"depth\":2},{\"id\":\"modern-dev-1\",\"text\":\"modern dev\",\"depth\":2},{\"id\":\"modern-test-1\",\"text\":\"modern test\",\"depth\":2},{\"id\":\"modern-lint-1\",\"text\":\"modern lint\",\"depth\":2},{\"id\":\"modern-change\",\"text\":\"modern change\",\"depth\":2},{\"id\":\"modern-pre-1\",\"text\":\"modern pre\",\"depth\":2},{\"id\":\"modern-bump-1\",\"text\":\"modern bump\",\"depth\":2},{\"id\":\"modern-release-1\",\"text\":\"modern release\",\"depth\":2},{\"id\":\"modern-gen-release-note-1\",\"text\":\"modern gen-release-note\",\"depth\":2},{\"id\":\"modern-upgrade-1\",\"text\":\"modern upgrade\",\"depth\":2}],\"content\":\"命令预览\\n\\n模块工程项目可以使用的命令:\\n\\n\\nMODERN BUILD\\n\\nUsage: modern build [options]\\n\\n构建模块命令\\n\\nOptions:\\n -w, --watch 使用监听模式构建代码\\n --tsconfig [tsconfig] 指定 tsconfig.json 文件的路径 (default:\\n \\\"./tsconfig.json\\\")\\n --platform [platform] 构建所有或者指定平台的产物\\n --no-dts 关闭 DTS 类型文件生成和类型检查\\n --no-clear 关闭自动清除产物输出目录的行为\\n -h, --help 展示当前命令的信息\\n\\n\\n当想要启动项目构建的时候,可以执行 modern build 命令。在使用这个命令的时候,我们可以:\\n\\n * 当想要以观察模式启动构建时,使用 --watch 选项。\\n * 当想要指定项目编译读取的 TypeScript 配置文件的路径时,使用 build --tsconfig ./path/config.json\\n 选项。使用该选项后,会覆盖所有 buildConfig 里 dts.tsconfigPath 配置。\\n * 当需要关闭项目的 DTS 类型文件生成和类型检查行为时,可以使用 --no-dts\\n 选项。注意:类型文件的生成依赖类型检查的结果。如果关闭了类型检查,那么类型文件也不会生成。\\n * 当需要关闭自动清除产物输出目录的行为时,可以使用 --no-clear 选项。\\n\\n除了以上,模块工程还支持 platform 构建模式,可以用于执行其他工具的构建任务。例如,目前官方支持在安装了\\n@modern-js/plugin-storybook 插件后,可以通过执行 modern build --platform 或者 modern build\\n--platform storybook 命令启动 Storybook 构建任务生成 Storybook 产物。\\n\\n在执行 Storybook 构建的时候,它需要读取项目的构建产物。因此在执行 modern build --platform 命令启动 Storybook\\n构建的时候,要先执行一次 modern build 确保源码构建产物的存在。\\n\\n\\nMODERN NEW\\n\\nUsage: modern new [options]\\n\\n模块化工程方案中执行生成器\\n\\nOptions:\\n -d, --debug 开启 Debug 模式,打印调试日志信息 (default: false)\\n -c, --config <config> 生成器运行默认配置(JSON 字符串)\\n --dist-tag <tag> 生成器使用特殊的 npm Tag 版本\\n --registry 生成器运行过程中定制 npm Registry\\n -h, --help display help for command\\n\\n\\nmodern new 命令用于启动微生成器功能,它可以为项目启用默认没有提供的功能。\\n\\n目前可以开启的功能有:\\n\\n * Storybook 调试\\n * Tailwind CSS 支持\\n * Modern.js Runtime API\\n\\n关于这些功能,可以通过【使用微生成器】 章节了解更多。\\n\\n\\nMODERN DEV\\n\\nUsage: modern dev [options]\\n\\n本地开发命令\\n\\nOptions:\\n -h, --help display help for command\\n\\nCommands:\\n[dev-tools-subCommand]\\n\\n\\n模块工程解决方案提供了使用调试工具的能力,可以通过 modern dev 命令来启动。不过要注意的是,默认情况下是没有提供调试相关的插件,因此此时执行\\nmodern dev 会提示: \\\"No dev tools found available\\\"。\\n\\n目前官方支持的调试工具有 Storybook,因此在你执行 modern new 命令开启它后,就可以执行 modern dev 或者 modern dev\\nstorybook 执行它。\\n\\n\\nMODERN TEST\\n\\nUsage: modern test [options]\\n\\nOptions:\\n -h, --help display help for command\\n\\n\\nmodern test 命令会自动将 src/tests/*.test.(js|ts|jsx|tsx) 文件当做测试用例运行。\\n\\n\\nMODERN LINT\\n\\nUsage: modern lint [options] [...files]\\n\\nlint and fix source files\\n\\nOptions:\\n --no-fix disable auto fix source file\\n -h, --help display help for command\\n\\n\\n运行 ESLint 检查代码语法情况。通常情况下,我们只需要在 git commit 阶段通过 lint-staged 检查本次提交修改的部分代码。\\n\\n * --no-fix 参数设置后可以关闭自动修复 lint 错误代码的能力。\\n\\n\\nMODERN CHANGE\\n\\nUsage: modern change [options]\\n\\n创建变更集\\n\\nOptions:\\n --empty 创建空变更集 (default: false)\\n --open 使用编辑器中打开创建的变更集 (default: false)\\n -h, --help display help for command\\n\\n\\nmodern change 命令用于生成 changesets 需要的 Markdown 文件。\\n\\n\\nMODERN PRE\\n\\nUsage: modern pre [options] <enter|exit> [tag]\\n\\n进入和退出预发布模式\\n\\nOptions:\\n -h, --help display help for command\\n\\n\\n可以使用 modern pre 命令在正式发布前预发布一个版本。\\n\\n\\nMODERN BUMP\\n\\nUsage: modern bump [options]\\n\\n使用变更集自动更新发布版本和变更日志\\n\\nOptions:\\n --canary 创建一个预发布版本进行测试 (default: false)\\n --preid <tag> 在对预发布版本进行版本控制时指定标识符 (default: \\\"next\\\")\\n --snapshot 创建一个特殊版本进行测试 (default: false)\\n -h, --help display help for command\\n\\n\\n按照 changesets 生成的变更记录的 Markdown 文件修改 package.json 中的版本号, 同时生成 CHANGELOG.md 文件。\\n\\n\\nMODERN RELEASE\\n\\nUsage: modern release [options]\\n\\n发布 npm 包\\n\\nOptions:\\n --tag <tag> 发布 npm 包使用特定的 tag (default: \\\"\\\")\\n --ignore-scripts 发布时忽略 package.json 中的 scripts 命令,仅支持在 pnpm monorepo\\n 中使用 (default: \\\"\\\")\\n -h, --help display help for command\\n\\n\\nmodern release 命令可以将模块发布到 npm Registry 上。\\n\\n * --tag 参数可以指定发布时具体的 dist tags。\\n\\n\\nMODERN GEN-RELEASE-NOTE\\n\\nUsage: modern gen-release-note [options]\\n\\n根据当前仓库 changeset 信息生成 Release Note\\n\\nOptions:\\n --repo <repo> 仓库名称,用于生成 Pull Request 链接, 例如: modern-js-dev/modern.js\\n --custom <cumtom> 自定义 Release Note 生成函数\\n -h, --help display help for command\\n\\n\\n根据当前仓库的 changeset 信息自动生成 Release Note。\\n\\n需要在 bump 命令之前执行。\\n\\n\\nMODERN UPGRADE\\n\\nUsage: modern upgrade [options]\\n\\n升级 Modern.js 到最新版本\\n\\nOptions:\\n --registry <registry> 定制 npm registry (default: \\\"\\\")\\n -d,--debug 开启 Debug 模式,打印调试日志信息 (default: false)\\n --cwd <cwd> 项目路径 (default: \\\"\\\")\\n -h, --help display help for command\\n\\n\\nmodern upgrade 命令,用于升级项目 Modern.js 相关依赖至最新版本。\\n\\n在项目根目录下执行命令 npx modern upgrade,会默认将当前执行命令项目的 package.json 中的 Modern.js\\n相关依赖更新至最新版本。\\n\\n命令在 @modern-js/module-tools 版本 >= 1.17.0 提供,之前版本可使用 npx @modern-js/upgrade 进行升级。\",\"frontmatter\":{\"sidebar_position\":2}},{\"title\":\"修改输出产物\",\"routePath\":\"/guide/basic/modify-output-product\",\"toc\":[{\"id\":\"默认输出产物\",\"text\":\"默认输出产物\",\"depth\":2},{\"id\":\"构建预设\",\"text\":\"构建预设\",\"depth\":2},{\"id\":\"构建预设的字符串形式\",\"text\":\"构建预设的字符串形式\",\"depth\":3},{\"id\":\"构建预设的函数形式\",\"text\":\"构建预设的函数形式\",\"depth\":3},{\"id\":\"构建配置对象\",\"text\":\"构建配置(对象)\",\"depth\":2},{\"id\":\"什么时候使用-buildconfig\",\"text\":\"什么时候使用 buildConfig\",\"depth\":2}],\"content\":\"修改输出产物\\n\\n\\n默认输出产物\\n\\n当在初始化的项目里使用 modern build 命令的时候,会根据 Module Tools 默认支持的配置生成相应的产物。默认支持的配置具体如下:\\n\\n\\n\\nexport default defineConfig({\\n buildPreset: 'base-config',\\n});\\n\\n\\n默认生成产物具有以下特点:\\n\\n * 代码格式为 CommonJS,或者简称为 cjs。\\n * 代码语法支持到 ES6。\\n * 所有的代码经过打包变成了一个文件,即进行了 bundle 处理。\\n * 产物输出根目录为项目下的 dist 目录,类型文件输出的目录为 dist/types。\\n\\n 1. 所谓“代码语法支持到 ES6”的意思是指:产物代码所支持的语法不会超过 ES6。如果源码中使用语法是 ES6 以上的语法(例如\\n ES2017),则会被进行转换。\\n\\n看到这里你可能会有以下疑问:\\n\\n 1. buildPreset 是什么?\\n 2. 产物的这些特点是由什么决定的?\\n\\n那么接下来首先解释一下 buildPreset。\\n\\n\\n构建预设\\n\\nbuildPreset 代表着提前准备好的一组或者多组构建相关的配置,只需要使用 buildPreset\\n对应的预设值,就可以省去麻烦且复杂的配置工作,得到符合预期的产物。\\n\\n\\n构建预设的字符串形式\\n\\n构建预设的值可以是字符串形式,因此这样形式的构建预设叫做预设字符串。\\n\\n模块工程解决方案根据 npm 包使用的通用场景,提供了通用的构建预设字符串以及相应的变体。目前支持的所有预设字符串可以通过 BuildPreset API\\n查看。这里讲解一下关于通用的预设字符串与变体之间的关系。\\n\\n在通用的预设字符串中,\\\"npm-library\\\" 可以用于在开发库类型的 npm 包的场景下使用,它适合大多数普通的模块类型项目。当设置\\n\\\"npm-library\\\" 的时候,项目的输出产物会有以下特点:\\n\\n * 在 dist/lib 目录下会得到代码格式为 cjs、语法支持到 es6 且经过打包处理后的产物。\\n * 在 dist/es 目录下会得到代码格式为 esm、语法支持为 es6 且经过打包处理后的产物。\\n * 在 dist/types 目录下会得到类型文件。如果不是 TypeScript 项目,则没有该目录。\\n\\n而预设字符串 \\\"npm-library\\\" 对应的变体则是在原本产物的基础上修改了代码语法支持这一特点,同时在字符串命名上也变为了\\n\\\"npm-library-[es5 | es2016...es2020 | esnext]\\\" 这样的形式。\\n\\n例如,如果在预设字符串 \\\"npm-library\\\" 对应的输出产物基础上,让产物代码支持的语法变为 es2017 的话,那么只需要将 \\\"npm-library\\\"\\n改变为 \\\"npm-library-es2017\\\" 就可以了。\\n\\n\\n构建预设的函数形式\\n\\n除了字符串形式以外,构建预设的值也可以是函数形式,在函数中可以打印或者修改某个预设值对应的具体配置。\\n\\n例如,如果使用预设函数的形式达到预设字符串 \\\"npm-library-es2017\\\" 同样的效果,可以按照如下的方式:\\n\\n\\n\\nexport default defineConfig({\\n buildPreset({ preset }) {\\n return preset.NPM_LIBRARY.map(config => {\\n return { ...config, target: 'es2017' };\\n });\\n },\\n});\\n\\n\\n在上面的代码实现中,preset.NPM_LIBRARY 与预设字符串 \\\"npm-library\\\" 是相对应的,它代表着 \\\"npm-library\\\"\\n等价的多组构建相关的配置。我们通过 map 方法遍历了 NPM_LIBRARY 这个数组,在这个数组中包含了多个 buildConfig 对象。我们将原本的\\nbuildConfig 对象进行了浅拷贝并修改了浅拷贝后得到 buildConfig.target,将它指定为 es2017。\\n\\n> 关于 preset.NPM_LIBRARY 具体对应的值,可以通过 BuildPreset API 查看。在 preset 对象下不仅包含了\\n> NPM_LIBRARY,还包含了其他类似的常量。\\n\\n那么这里的 buildConfig 对象是什么呢?之前提到的构建产物特点又是根据什么呢?\\n\\n接下来我们解释一下。\\n\\n\\n构建配置(对象)\\n\\nbuildConfig 是一个用来描述如何编译、生成构建产物的配置对象。在最开始提到的关于“构建产物的特点”,其实都是 buildConfig\\n所支持的属性。目前所支持的属性覆盖了大部分模块类型项目在构建产物时的需求,buildConfig\\n不仅包含一些产物所具备的属性,也包含了构建产物所需要的一些特性功能。接下来从分类的角度简单罗列一下:\\n\\n构建产物的基本属性包括:\\n\\n * 产物是否被打包:对应的 API 是 buildConfig.buildType。\\n * 产物对于语法的支持:对应的 API 是 buildConfig.target。\\n * 产物格式:对应的 API 是 buildConfig.format。\\n * 产物类型文件如何处理,对应的 API 是 buildConfig.dts。\\n * 产物的 sourceMap 如何处理:对应的 API 是 buildConfig.sourceMap。\\n * 产物对应的输入(或者是源文件):对应的 API 是 buildConfig.input。\\n * 产物输出的目录:对应的 API 是 buildConfig.outDir。\\n * 构建的源码目录:对应的 API 是 buildConfig.sourceDir。\\n\\n构建产物所需的常用功能包括:\\n\\n * 别名:对应的 API 是 buildConfig.alias。\\n * 静态资源处理:对应的 API 是 buildConfig.asset。\\n * 第三方依赖处理:对应的 API 有:\\n * buildConfig.autoExternal。\\n * buildConfig.externals。\\n * 拷贝:对应的 API 是 buildConfig.copy。\\n * 全局变量替换:对应的 API 是 buildConfig.define。\\n * 指定 JSX 编译方式,对应的 API 是 buildConfig.jsx。\\n\\n一些高级属性或者使用频率不高的功能:\\n\\n * 产物代码压缩:对应的 API 是 buildConfig.minify。\\n * 代码分割:buildConfig.spitting\\n * 指定构建产物用于 NodeJS 环境还是浏览器环境:对应的 API 是 buildConfig.platform。\\n * umd 产物相关:\\n * 指定 umd 产物外部导入的全局变量:对应的 API 是 buildConfig.umdGlobals。\\n * 指定 umd 产物的模块名:对应的 API 是 buildConfig.umdModuleName。\\n\\n除了以上分类以外,关于这些 API 的常见问题和最佳实践可以通过下面的链接来了解,敬请期待。\\n\\n * 什么是 bundle 和 bundleless?\\n * input 与 sourceDir 的关系。\\n * 产物中类型文件的多种生成方式。\\n * buildConfig.define 不同场景的使用方式。\\n * 如何处理第三方依赖?\\n * 如何使用拷贝?\\n * 如何构建 umd 产物?\\n * 静态资源目前所支持的能力。\\n\\n\\n什么时候使用 BUILDCONFIG\\n\\nbuildConfig 是用于修改产物的方式之一,当与 buildPreset 配置同时存在的时候,只有 buildConfig\\n才会生效。因此如果按照如下方式配置:\\n\\n\\n\\nexport default defineConfig({\\n buildConfig: [{}],\\n buildPreset: 'base-config',\\n});\\n\\n\\n那么此时就会看到如下提示:\\n\\n因为同时出现 'buildConfig' 和 'buildPreset' 配置,因此仅 'buildConfig' 配置生效\\n\\n\\nbuildPreset 代表的一组或者多组构建相关的配置都是由 buildConfig 组成,当使用 buildPreset\\n无法满足当前项目需求的时候,就可以使用 buildConfig 来自定义输出产物。\\n\\n在使用 buildConfig 的过程,就是对“获得怎样的构建产物”的思考过程。\",\"frontmatter\":{\"sidebar_position\":3}},{\"title\":\"版本管理与发布\",\"routePath\":\"/guide/basic/publish-your-project\",\"toc\":[{\"id\":\"跟踪变更\",\"text\":\"跟踪变更\",\"depth\":2},{\"id\":\"版本更新\",\"text\":\"版本更新\",\"depth\":2},{\"id\":\"发布\",\"text\":\"发布\",\"depth\":2},{\"id\":\"预发布\",\"text\":\"预发布\",\"depth\":2}],\"content\":\"版本管理与发布\\n\\n一个 npm 类型的模块项目发布流程包含了两个阶段:\\n\\n * 第一阶段是在开发期间,开发者需要提供一个变更文件来记录需要发布的变动;\\n * 第二阶段是在发布期间,Module Tools 可以收集所有的变更文件来更新版本、更新发布日志,并发布新的包到 npm Registry 上。\\n\\n\\n跟踪变更\\n\\n当项目发生变化的时候需要将变化的内容记录下来。项目发生的变化一般是指:\\n\\n * 新功能\\n * 修复问题\\n * 配置文件修改\\n * ...\\n\\n当这些变化一旦完成后,需要通过以下命令来对当前的变化进行记录:\\n\\n * modern change\\n\\n执行 modern change 命令后会向开发者提出几个问题,并根据开发者的回答生成变更记录。变更记录文件包含了版本变化的类型和其描述,该文件会被提交到\\ngit 仓库中。\\n\\n$ npx modern change\\n🦋 What kind of change is this for module-example? (current version is 0.1.0) · patch\\n🦋 Please enter a summary for this change (this will be in the changelogs). Submit empty line to open external editor\\n🦋 Summary · publish test\\n🦋 === Releasing the following packages ===\\n🦋 [Patch]\\n🦋 module\\n🦋 Is this your desired changeset? (Y/n) · true\\n🦋 Changeset added! - you can now commit it\\n🦋\\n🦋 If you want to modify or expand on the changeset summary, you can find it here\\n🦋 info /xxxxxx/module/.changeset/brave-dryers-agree.md\\n\\n\\n当执行成功后,生成的包含变更记录的 Markdown 文件会保存在项目的 .changeset 目录下面。其内容类似下面这样:\\n\\n---\\n'module-example': patch\\n---\\n\\npublish test\\n\\n\\n\\n版本更新\\n\\n当需要更新项目版本的时候,执行以下命令:\\n\\n * modern bump\\n\\n执行 modern bump 将会基于 .changeset/ 目录下记录了变更的 Markdown 文件内容来修改 package.json\\n中的版本号,同时生成 CHANGELOG.md 文件。而当版本更新完成后,这些记录变更的 Markdown 文件也会被删除,也可说这些 Markdown\\n文件被“消耗”掉了。\\n\\n# module\\n\\n## 0.1.1\\n\\n### Patch Changes\\n\\n- publish test\\n\\n\\n\\n发布\\n\\n发布项目可以执行以下命令:\\n\\n * modern publish\\n\\nmodern release 命令可以将项目发布到 npm Registry。\\n\\n此时发布的是 latest 版本,也可以说是正式版本。如果想要修改 dist-tag,可以通过 modern release --tag 命令来指定。例如:\\n\\nmodern release --tag beta\\n\\n\\n但是如果希望将当前项目的版本号也修改为预发布的版本号,则需要使用 modern pre 命令。\\n\\n> 所谓 dist-tag,可以理解:为当前发布的版本打标签。一般来说,默认发布的版本对应的 dist-tag 为 latest,因此可以把 latest\\n> 认为是正式版本的 dist-tag。\\n\\n\\n预发布\\n\\n当需要在正式发布之前进行预发布,则需要执行以下命令:\\n\\n * modern pre\\n\\n首先 modern pre enter <tag> 进入预发布模式,<tag> 可以与发布项目的时候使用 modern release --tag 命令指定的\\ntag 一致。\\n\\n$ npx modern pre enter next\\n🦋 success Entered pre mode with tag next\\n🦋 info Run `changeset version` to version packages with prerelease versions\\n✨ Done in 5.30s.\\n\\n\\n接着可以使用 modern bump 命令更新具体的版本号,此时不会真正的“消耗”记录变更的 Markdown 文件:\\n\\n$ npx modern bump\\n🦋 warn ===============================IMPORTANT!===============================\\n🦋 warn You are in prerelease mode\\n🦋 warn If you meant to do a normal release you should revert these changes and run `changeset pre exit`\\n🦋 warn You can then run `changeset version` again to do a normal release\\n🦋 warn ----------------------------------------------------------------------\\n🦋 All files have been updated. Review them and commit at your leisure\\n\\n\\n然后可以看到 package.json 中更新的版本号会类似这样:0.1.2-next.0。\\n\\n最后,如果不需要再进行预发布,则一定要执行 modern pre exit 命令,这样可以退出预发布状态,并且当再次执行 modern bump\\n命令的时候,就可以发布正式的版本。\",\"frontmatter\":{\"sidebar_position\":7}},{\"title\":\"测试项目\",\"routePath\":\"/guide/basic/test-your-project\",\"toc\":[{\"id\":\"先决条件和约定\",\"text\":\"先决条件和约定\",\"depth\":2},{\"id\":\"运行测试\",\"text\":\"运行测试\",\"depth\":2},{\"id\":\"使用配置\",\"text\":\"使用配置\",\"depth\":2},{\"id\":\"测试示例\",\"text\":\"测试示例\",\"depth\":2},{\"id\":\"普通模块\",\"text\":\"普通模块\",\"depth\":3},{\"id\":\"组件\",\"text\":\"组件\",\"depth\":3}],\"content\":\"测试项目\\n\\n本章将要介绍如何测试可复用模块。\\n\\n\\n先决条件和约定\\n\\n想要使用项目的测试功能,需要确保项目中包含以下依赖:\\n\\n * \\\"@modern-js/plugin-testing\\\"\\n\\n在模块工程方案中,对于测试用例或者说编写测试的文件有如下约定:\\n\\n * 项目目录下的 tests 目录为测试用例和测试文件的目录,不支持更改运行测试用例的目录。\\n * 默认会自动将后缀为 .test.[tj]sx? 的文件识别为测试文件。\\n * 其他的 .[tj]sx? 后缀的文件被识别为普通的文件,可以用于测试的 utils 文件或者其他用途。\\n\\n\\n运行测试\\n\\n当准备好了依赖以及了解了测试用例在哪里编写后,我们可以通过以下命令来执行测试:\\n\\nmodern test\\n\\n// 更新 snapshot\\nmodern test --updateSnapshot\\n\\n\\n执行之后,会看到测试的结果:\\n\\n\\n\\n\\n使用配置\\n\\n/obj/eden-cn/uhbfnupenuhf/test-result.png 模块工程方案对测试提供了以下配置:\\n\\n * testing\\n\\n可以在 modern.config.(j|t)s 中增加它。\\n\\n\\n测试示例\\n\\n\\n普通模块\\n\\n对于普通的模块,我们可以按照如下方式使用测试功能:\\n\\n<CH.Spotlight>\\n\\nexport default function () {\\n return 'hello world';\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n首先是模块的代码。\\n\\nexport default function () {\\n return 'hello world';\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n然后在测试文件中,我们可以这样。\\n\\n其中 @ 指向了源码目录,在初始化项目的 tests/tsconfig.json 中定义了。\\n\\n\\n\\ndescribe('默认值 cases', () => {\\n test('Have returns', () => {\\n const drink = jest.fn(main);\\n drink();\\n expect(drink).toHaveReturned();\\n });\\n});\\n\\n\\n--------------------------------------------------------------------------------\\n\\n最后我们可以执行 modern test。\\n\\npnpm test\\n## or\\nyarn test\\n## or\\nnpm run test\\n\\n\\n</CH.Spotlight>\\n\\n\\n组件\\n\\n{/* 链接待补充 */}\\n\\n对于组件,Modern.js 的 Runtime API 提供了用于测试 UI 组件的功能,其功能由 @modern-js/runtime/testing\\n提供。\\n\\n如果需要使用 Runtime API,那么可以通过 微生成器 开启。\\n\\n<CH.Spotlight>\\n\\nexport const default () {\\n return (\\n <div>This is a UI Component</div>\\n );\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n首先是组件的代码。\\n\\nexport const default () {\\n return (\\n <div>This is a UI Component</div>\\n );\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n然后在测试文件中,我们可以这样。\\n\\n其中 @ 指向了源码目录,在初始化项目的 tests/tsconfig.json 中定义了。\\n\\n\\n\\n\\n\\ndescribe('默认值 cases', () => {\\n test('Rendered', () => {\\n render(<Component />);\\n expect(screen.getByText('This is a UI Component')).toBeInTheDocument();\\n });\\n});\\n\\n\\n--------------------------------------------------------------------------------\\n\\n最后我们可以执行 modern test。\\n\\npnpm test\\n## or\\nyarn test\\n## or\\nnpm run test\\n\\n\\n</CH.Spotlight>\",\"frontmatter\":{\"sidebar_position\":6}},{\"title\":\"使用微生成器\",\"routePath\":\"/guide/basic/use-micro-generator\",\"toc\":[{\"id\":\"storybook-调试\",\"text\":\"Storybook 调试\",\"depth\":2},{\"id\":\"tailwind-css-支持\",\"text\":\"Tailwind CSS 支持\",\"depth\":2},{\"id\":\"启动-modernjs-runtime-api\",\"text\":\"启动 Modern.js Runtime API\",\"depth\":2}],\"content\":\"使用微生成器\\n\\n模块工程解决方案提供了微生成器工具,它可以为当前项目:\\n\\n * 新增目录和文件\\n * 修改 package.json 文件内容\\n * 执行命令\\n\\n因此通过这些能力,微生成器可以为项目开启额外的特性功能。\\n\\n可以通过 modern new 启动微生成器。目前模块工程方案支持的微生成器功能有:\\n\\n\\nSTORYBOOK 调试\\n\\n当我们想要对组件或者普通模块进行调试的时候,可以启用 Storybook 调试功能。启动该功能后,会在项目目录下创建 stories 目录以及相关文件,在\\npackage.json 中新增 \\\"@modern-js/plugin-storybook\\\" 依赖。\\n\\n关于如何启动 Storybook 以及如何使用 Storybook,可以查看下面的链接:\\n\\n * modern dev\\n * 使用 Storybook\\n\\n\\nTAILWIND CSS 支持\\n\\n当我们想要为项目增加 Tailwind CSS 支持的时候,可以启动这个功能。Tailwind CSS 是一个 CSS 库,提供开箱即用的样式。\\n\\n关于如何在模块工程里使用 Tailwind CSS,可以查看:\\n\\n * 使用 Tailwind CSS\\n\\n\\n启动 MODERN.JS RUNTIME API\\n\\nModern.js 提供了 Runtime API 能力,这些 API 只能在 Modern.js 的应用项目环境中使用。如果你需要开发一个 Modern.js\\n应用环境中使用的组件,那么你可以开启该特性,微生成器会增加 \\\"@modern-js/runtime\\\"依赖。\\n\\n另外,Storybook 调试工具也会通过检测项目的依赖确定项目是否需要使用 Runtime API,并且提供与 Modern.js 应用项目一样的\\nRuntime API 运行环境。\",\"frontmatter\":{\"sidebar_position\":4}},{\"title\":\"使用 Storybook\",\"routePath\":\"/guide/basic/using-storybook\",\"toc\":[{\"id\":\"调试代码\",\"text\":\"调试代码\",\"depth\":2},{\"id\":\"引用组件产物\",\"text\":\"引用组件产物\",\"depth\":3},{\"id\":\"引用组件源码\",\"text\":\"引用组件源码\",\"depth\":3},{\"id\":\"配置-storybook\",\"text\":\"配置 Storybook\",\"depth\":2},{\"id\":\"配置文件\",\"text\":\"配置文件\",\"depth\":3},{\"id\":\"devstorybook-1\",\"text\":\"dev.storybook\",\"depth\":3},{\"id\":\"构建-storybook-产物\",\"text\":\"构建 Storybook 产物\",\"depth\":3}],\"content\":\"使用 STORYBOOK\\n\\n首先如果没有看过以下内容的话,可以先花几分钟先了解一下:\\n\\n * 使用微生成器开启 Storybook 调试\\n * modern dev\\n\\nStorybook 是一个专门用于组件调试的工具,围绕着组件开发提供了:\\n\\n * 丰富多样的调试能力\\n * 可与一些测试工具结合使用\\n * 可重复使用的文档内容\\n * 可分享能力\\n * 工作流程自动化\\n\\n因此它是一个复杂且功能强大的工具。\\n\\n模块工程解决方案集成了 Storybook,因此你几乎可以按照 Storybook 官方文档的内容进行使用。不过依然有一些地方需要注意,接下来讲解一下:\\n\\n\\n调试代码\\n\\n在调试代码过程中需要引入组件代码,目前可以通过两种方式引入组件代码:\\n\\n * 引用组件产物\\n * 引用组件源码\\n\\n我们更推荐使用第一种“引用组件产物”的方式。因为它几乎接近真实的使用场景,不仅可以对组件功能进行调试,同时也对构建产物的正确性进行了验证。\\n\\n接下来我们分别讲一下这两种方式具体如何使用。\\n\\n\\n引用组件产物\\n\\n假如存在 TypeScript 项目 foo:\\n\\n<CH.Spotlight>\\n\\n{\\n \\\"name\\\": \\\"foo\\\",\\n \\\"main\\\": \\\"./dist/index.js\\\",\\n \\\"types\\\": \\\"./dist/types/index.d.ts\\\"\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n确保 package.json 的 main 和 types 的值为真实的路径。\\n\\n{\\n \\\"name\\\": \\\"foo\\\",\\n \\\"main\\\": \\\"./dist/index.js\\\",\\n \\\"types\\\": \\\"./dist/types/index.d.ts\\\"\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\nfoo 项目的源码。\\n\\nexport const content = 'hello world';\\n\\n\\n--------------------------------------------------------------------------------\\n\\n确保在 stories/tsconfig.json 中设置了指向项目根目录的 paths 配置。 paths 的 key 与项目名称相同。\\n\\n{\\n \\\"extends\\\": \\\"../tsconfig.json\\\",\\n \\\"include\\\": [\\\"./\\\"],\\n \\\"compilerOptions\\\": {\\n \\\"jsx\\\": \\\"preserve\\\",\\n \\\"baseUrl\\\": \\\".\\\",\\n \\\"paths\\\": {\\n \\\"foo\\\": [\\\"../\\\"]\\n }\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n最后在 Story 代码中直接以项目名称的方式引用。\\n\\n\\n\\nconst Component = () => <div>this is a Story Component {content}</div>;\\n\\nexport const YourStory = () => <Component />;\\n\\nexport default {\\n title: 'Your Stories',\\n};\\n\\n\\n</CH.Spotlight>\\n\\n如果在开发过程中,遇到无法实时获得类型定义的情况,此时:\\n\\n对于 pnpm 的项目,可以按照下面的内容对 package.json 进行修改:\\n\\n{\\n \\\"name\\\": \\\"foo\\\",\\n \\\"main\\\": \\\"./dist/index.js\\\",\\n \\\"types\\\": \\\"./src/index.ts\\\",\\n \\\"publishConfig\\\": {\\n \\\"types\\\": \\\"./dist/index.d.ts\\\",\\n }\\n}\\n\\n\\n> 关于 pnpm 的 publishConfig 的使用,可以阅读下面这个链接。\\n\\n而对于 npm 和 Yarn 的项目,则只能通过手动的方式在开发阶段和发布阶段对 package.json 的 types 的值进行修改。\\n\\n那么为什么可以直接引用产物呢?\\n\\n 1. 在执行 modern dev storybook 命令之前,会自动执行 modern build 命令,保证项目构建产物的存在。\\n 2. 在 Storybook 内部增加了以项目名称作为别名的处理,保证能够根据 package.json 解析出项目的产物路径。\\n\\n\\n引用组件源码\\n\\n引用组件的源码可以通过相对路径的方式:\\n\\n\\n\\nconst Component = () => <div>this is a Story Component {content}</div>;\\n\\nexport const YourStory = () => <Component />;\\n\\nexport default {\\n title: 'Your Stories',\\n};\\n\\n\\n那么为什么不推荐使用源码的方式呢?\\n\\n不仅仅是因为使用组件源码无法验证组件产物是否正确,同时模块工程对于构建产物支持的一些配置无法完全转换为 Storybook\\n内部的配置。如果某些配置无法进行相互转换的话,就会在 Storybook 调试过程中出现不符合预期的结果。\\n\\n\\n配置 STORYBOOK\\n\\n\\n配置文件\\n\\nStorybook 官方通过一个名为 .storybook 的文件夹来进行项目配置,其中包含各种配置文件。在模块工程方案中,可以在项目的\\nconfig/storybook 目录下增加 Storybook 配置文件。\\n\\n关于 Storybook 各种配置文件的使用方式,可以查看下面的链接:\\n\\n * Configure Storybook\\n\\n不过在模块项目里进行 Storybook 存在一些限制:\\n\\n * 目前不能修改 Story 文件存放的位置,即无法在 main.js 文件里修改 stories 配置。\\n * 目前不能修改 Webpack 和 Babel 相关的配置,即无法在 main.js 文件里修改 webpackFinal 和 babel 配置。\\n\\n在未来我们会考虑这些配置是否可以允许修改,不过目前为了减少不可预知的问题暂时限制使用这些配置。\\n\\n\\nDEV.STORYBOOK\\n\\n除了配置文件以外,模块工程方案还在 modern.config.(j|t)s 项目配置文件里提供了 dev.storybook 配置项。\\n\\n目前可以通过该配置对 Storybook 的 webpack 配置进行修改。\\n\\n{/* 链接待补充 */}\\n\\n * dev.storybook.webpack\\n\\n\\n构建 STORYBOOK 产物\\n\\n除了可以对组件或者普通的模块进行 Storybook 调试,还可以通过下面的命令来执行 Storybook 的构建任务。\\n\\nmodern build --platform storybook\\n\\n\\n关于 modern build --platform 命令可以查看:\\n\\n * modern build\\n\\n构建完成后,可以在 dist/storybook-static 目录看到构建产物文件。\",\"frontmatter\":{\"sidebar_position\":5}},{\"title\":\"开发组件\",\"routePath\":\"/guide/best-practices/components\",\"toc\":[{\"id\":\"初始化项目\",\"text\":\"初始化项目\",\"depth\":2},{\"id\":\"使用-storybook-调试代码\",\"text\":\"使用 Storybook 调试代码\",\"depth\":2},{\"id\":\"开发样式\",\"text\":\"开发样式\",\"depth\":2},{\"id\":\"csspostcss-1\",\"text\":\"CSS/PostCSS\",\"depth\":3},{\"id\":\"less-3\",\"text\":\"Less\",\"depth\":3},{\"id\":\"sassscss-1\",\"text\":\"Sass/Scss\",\"depth\":3},{\"id\":\"tailwind-css-1\",\"text\":\"Tailwind CSS\",\"depth\":3},{\"id\":\"html-类名-1\",\"text\":\"HTML 类名\",\"depth\":4},{\"id\":\"apply-1\",\"text\":\"@apply\",\"depth\":4},{\"id\":\"推荐方式\",\"text\":\"推荐方式\",\"depth\":4},{\"id\":\"bundle-和-bundleless-构建产物区别\",\"text\":\"bundle 和 bundleless 构建产物区别\",\"depth\":4},{\"id\":\"css-modules-1\",\"text\":\"CSS Modules\",\"depth\":3},{\"id\":\"配置构建产物\",\"text\":\"配置构建产物\",\"depth\":2},{\"id\":\"测试组件\",\"text\":\"测试组件\",\"depth\":2},{\"id\":\"发布组件\",\"text\":\"发布组件\",\"depth\":2}],\"content\":\"开发组件\\n\\n本章将要介绍如何使用模块工程解决方案开发组件项目。\\n\\n\\n初始化项目\\n\\n<CH.Spotlight>\\n\\nnpx @modern-js/create components-project\\n\\n? 请选择你想创建的工程类型 模块\\n? 请填写项目名称 components-demo\\n? 请选择开发语言 TS\\n? 请选择包管理工具 pnpm\\n\\n\\n--------------------------------------------------------------------------------\\n\\n推荐使用 @modern-js/create 命令来初始化一个 npm 项目。\\n\\nnpx @modern-js/create components-project\\n\\n? 请选择你想创建的工程类型 模块\\n? 请填写项目名称 components-demo\\n? 请选择开发语言 TS\\n? 请选择包管理工具 pnpm\\n\\n\\n--------------------------------------------------------------------------------\\n\\n初始化的目录结构。\\n\\n.\\n├── README.md\\n├── node_modules/\\n├── dist/\\n├── modern.config.ts\\n├── package.json\\n├── pnpm-lock.yaml\\n├── src\\n│ ├── index.ts\\n│ └── modern-app-env.d.ts\\n└── tsconfig.json\\n\\n\\n--------------------------------------------------------------------------------\\n\\n修改 ./src/index.ts 文件后缀和内容。\\n\\n此时就初始化了一个组件项目。\\n\\nexport default () => {\\n return <div>hello world</div>;\\n};\\n\\n\\n</CH.Spotlight>\\n\\n\\n使用 STORYBOOK 调试代码\\n\\n<CH.Spotlight>\\n\\npnpm run new\\n\\n? 请选择你想要的操作 启用可选功能\\n? 启用可选功能 启用「Storybook」\\n\\n\\n--------------------------------------------------------------------------------\\n\\n在项目根目录下执行 new 命令,可以开启 Storybook 功能。\\n\\npnpm run new\\n\\n? 请选择你想要的操作 启用可选功能\\n? 启用可选功能 启用「Storybook」\\n\\n\\n--------------------------------------------------------------------------------\\n\\n成功开启后,会看到 package.json 中新增了依赖。同时创建了 stories 目录和相关的初始化文件。\\n\\n<CH.Code>\\n\\n{\\n \\\"name\\\": \\\"components-demo\\\",\\n \\\"devDependencies\\\": {\\n \\\"@modern-js/plugin-storybook\\\": \\\"x.y.z\\\",\\n \\\"@modern-js/runtime\\\": \\\"x.y.z\\\",\\n \\\"react\\\": \\\"^17\\\",\\n \\\"react-dom\\\": \\\"^17\\\"\\n }\\n}\\n\\n\\n.\\n├── src\\n│ ├── index.ts\\n│ └── modern-app-env.d.ts\\n├── stories\\n│ ├── .eslintrc.js\\n│ ├── index.stories.tsx\\n│ └── tsconfig.json\\n\\n\\n</CH.Code>\\n\\n--------------------------------------------------------------------------------\\n\\n初始化后,在 ./stories 目录下的 tsconfig.json 文件中默认设置了与项目同名的 paths 配置。\\n\\n{\\n \\\"extends\\\": \\\"../tsconfig.json\\\",\\n \\\"compilerOptions\\\": {\\n \\\"baseUrl\\\": \\\"../\\\",\\n \\\"paths\\\": {\\n \\\"components-demo\\\": [\\\"./\\\"],\\n \\\"components-demo/*\\\": [\\\"./*\\\"]\\n }\\n },\\n \\\"include\\\": [\\\"**/*\\\"]\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n这样的配置可以让你在 Story 代码中直接使用项目的名称引入代码。\\n\\n<CH.Code>\\n\\n\\n\\nexport const YourStory = () => <Component />;\\n\\nexport default {\\n title: 'Your Stories',\\n};\\n\\n\\n--------------------------------------------------------------------------------\\n\\nexport default () => {\\n return <div>hello world</div>;\\n};\\n\\n\\n</CH.Code>\\n\\n--------------------------------------------------------------------------------\\n\\n此时 Storybook 会根据项目的 package.json 文件中的 main、exports 这样的字段确认导入代码的入口; 根据 types\\n字段确定类型文件的位置。\\n\\n{\\n \\\"name\\\": \\\"components-demo\\\",\\n \\\"main\\\": \\\"./dist/esm/index.js\\\",\\n \\\"types\\\": \\\"./dist/types/index.d.ts\\\"\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n虽然也支持导入源代码进行调试,不过使用项目产物调试更加可靠。\\n\\n使用源代码调试存在局限性:某些配置无法在 Storybook 和原本构建支持的配置等价使用。\\n\\n因此更推荐使用产物进行调试。\\n\\n\\n\\nexport const YourStory = () => <Component />;\\n\\nexport default {\\n title: 'Your Stories',\\n};\\n\\n\\n</CH.Spotlight>\\n\\n\\n开发样式\\n\\n接下来我们可以给组件添加样式。\\n\\n目前支持开发样式的能力有:\\n\\n * CSS/PostCSS\\n * Less\\n * Scss/Sass\\n * Tailwind CSS\\n * CSS Modules\\n\\n\\nCSS/POSTCSS\\n\\n模块工程支持 PostCSS,并且内置了以下 postcss 插件:\\n\\n * flexbugs-fixes\\n * custom-properties\\n * initial\\n * page-break\\n * font-variant\\n * media-minmax\\n * nesting\\n\\n因此我们可以在项目中创建 .css 文件,并且可以直接在 css 文件中使用这些插件提供的语法支持和能力。\\n\\n<CH.Spotlight>\\n\\na,\\nb {\\n color: red;\\n\\n /* \\\"&\\\" comes first */\\n & c,\\n & d {\\n color: white;\\n }\\n\\n /* \\\"&\\\" comes later, requiring \\\"@nest\\\" */\\n @nest e & {\\n color: yellow;\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n源代码。\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\ncss 产物。\\n\\na,\\nb {\\n color: red;\\n}\\na c,\\nb c,\\na d,\\nb d {\\n color: white;\\n}\\ne a,\\ne b {\\n color: yellow;\\n}\\n\\n\\n</CH.Spotlight>\\n\\n\\nLESS\\n\\n模块工程支持使用 Less 开发样式。\\n\\n> 目前支持的版本为 4.1.3\\n\\n<CH.Spotlight>\\n\\n@bg: black;\\n@bg-light: boolean(luma(@bg) > 50%);\\n\\ndiv {\\n background: @bg;\\n color: if(@bg-light, black, white);\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n源代码。\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\nLess 产物。\\n\\ndiv {\\n background: black;\\n color: white;\\n}\\n\\n\\n</CH.Spotlight>\\n\\n\\nSASS/SCSS\\n\\n模块工程支持使用 Scss/Sass 开发样式。\\n\\n> 目前支持的版本为 1.54.4\\n\\n<CH.Spotlight>\\n\\n$font-stack: Helvetica, sans-serif;\\n$primary-color: #333;\\n\\nbody {\\n font: 100% $font-stack;\\n color: $primary-color;\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n源代码。\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\nLess 产物。\\n\\nbody {\\n font: 100% Helvetica, sans-serif;\\n color: #333;\\n}\\n\\n\\n</CH.Spotlight>\\n\\n\\nTAILWIND CSS\\n\\n模块工程支持使用 Tailwind CSS 开发组件样式。\\n\\n默认情况下,模块工程没有开启该功能,需要按照下面的方式开启它。\\n\\n<CH.Spotlight>\\n\\npnpm run new\\n\\n? 请选择你想要的操作 启用可选功能\\n? 启用可选功能 启用「Storybook」\\n\\n\\n--------------------------------------------------------------------------------\\n\\n在项目根目录下执行 new 命令,可以开启 Tailwind CSS 功能。\\n\\npnpm run new\\n\\n? 请选择你想要的操作 启用可选功能\\n? 启用可选功能 启用 Tailwind CSS 支持\\n\\n\\n--------------------------------------------------------------------------------\\n\\n成功开启后,会看到 package.json 中新增了依赖。\\n\\n{\\n \\\"devDependencies\\\": {\\n \\\"@modern-js/plugin-tailwindcss\\\": \\\"x.y.z\\\"\\n }\\n}\\n\\n\\n</CH.Spotlight>\\n\\nTailwind CSS 提供了两种使用方式:\\n\\nHTML 类名\\n\\n<CH.Spotlight>\\n\\nimport 'tailwindcss/utilities.css';\\n\\nexport default () => {\\n return <div className=\\\"bg-black text-white\\\">hello world</div>;\\n};\\n\\n\\n--------------------------------------------------------------------------------\\n\\nTailwind CSS 支持在 HTML 标签上使用类名的方式增加样式。\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\n当使用 HTML 类名的时候,一定要注意导入 Tailwind CSS 相应的 css 文件。\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\n样式产物。\\n\\n> 此时是 bundle 构建。\\n\\n/* ../../node_modules/.pnpm/tailwindcss@2.2.19/node_modules/tailwindcss/utilities.css */\\n.table {\\n display: table;\\n}\\n@keyframes spin {\\n to {\\n transform: rotate(360deg);\\n }\\n}\\n@keyframes ping {\\n 75%,\\n 100% {\\n transform: scale(2);\\n opacity: 0;\\n }\\n}\\n@keyframes pulse {\\n 50% {\\n opacity: 0.5;\\n }\\n}\\n@keyframes bounce {\\n 0%,\\n 100% {\\n transform: translateY(-25%);\\n animation-timing-function: cubic-bezier(0.8, 0, 1, 1);\\n }\\n 50% {\\n transform: none;\\n animation-timing-function: cubic-bezier(0, 0, 0.2, 1);\\n }\\n}\\n.bg-black {\\n --tw-bg-opacity: 1;\\n background-color: rgba(0, 0, 0, var(--tw-bg-opacity));\\n}\\n.text-white {\\n --tw-text-opacity: 1;\\n color: rgba(255, 255, 255, var(--tw-text-opacity));\\n}\\n*,\\n::before,\\n::after {\\n --tw-shadow: 0 0 #0000;\\n}\\n*,\\n::before,\\n::after {\\n --tw-ring-inset: var(--tw-empty);\\n --tw-ring-offset-width: 0px;\\n --tw-ring-offset-color: #fff;\\n --tw-ring-color: rgba(59, 130, 246, 0.5);\\n --tw-ring-offset-shadow: 0 0 #0000;\\n --tw-ring-shadow: 0 0 #0000;\\n}\\n@media (min-width: 640px) {\\n}\\n@media (min-width: 768px) {\\n}\\n@media (min-width: 1024px) {\\n}\\n@media (min-width: 1280px) {\\n}\\n@media (min-width: 1536px) {\\n}\\n\\n\\n</CH.Spotlight>\\n\\n@APPLY\\n\\nTailwind CSS 提供了 @apply 指令,可以通过它将 Tailwind CSS 提供的样式内联到我们编写的样式中。\\n\\n@apply 可以用于 CSS、Less、Sass 中。\\n\\n.btn {\\n @apply font-bold py-2 px-4 rounded;\\n}\\n\\n\\n但是使用过程中,对于 Less 和 Sass 有些情况需要注意:\\n\\nSASS\\n\\n当将 Tailwind 与 Sass 一起使用时,@apply 后面存在 !important 的时候,需要使用插值来让 Sass 正确编译。\\n\\n<CH.Spotlight>\\n\\n.alert {\\n @apply bg-red-500 !important;\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n不能正常工作。\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\n能够正常工作。\\n\\n.alert {\\n @apply bg-red-500 #{!important};\\n}\\n\\n\\n</CH.Spotlight>\\n\\nLESS\\n\\n在与 Less 一起使用 Tailwind 时,你不能嵌套 Tailwind 的 @screen 指令。\\n\\n<CH.Spotlight>\\n\\n.card {\\n @apply rounded-none;\\n\\n @screen sm {\\n @apply rounded-lg;\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n不能正常工作。\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\n相反,使用常规的媒体查询和 theme() 函数来引用你的屏幕尺寸,或者干脆不要嵌套你的 @screen 指令。\\n\\n<CH.Code>\\n\\n// Use a regular media query and theme()\\n.card {\\n @apply rounded-none;\\n\\n @media (min-width: theme('screens.sm')) {\\n @apply rounded-lg;\\n }\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n// Use the @screen directive at the top-level\\n.card {\\n @apply rounded-none;\\n\\n @media (min-width: theme('screens.sm')) {\\n @apply rounded-lg;\\n }\\n}\\n\\n\\n</CH.Code>\\n\\n</CH.Spotlight>\\n\\n推荐方式\\n\\n推荐使用 @apply 指定的方式开发样式,这样在样式产物中仅包含通过指令内联的样式。\\n\\n当使用 HTML 类名的方式添加样式的时候,默认情况下 Tailwind\\n不仅会将本身类名对应的样式加入产物中,同时还会有额外的样式代码存在,虽然这些代码可能不会对本身的样式产生影响。\\n\\nBUNDLE 和 BUNDLELESS 构建产物区别\\n\\n对于以下代码,在 bundle 和 bundleless 两种模式下,构建产物会有很大区别。\\n\\n> 所谓 bundle 和 bundleless 可以查看 【Bundle 和 Bundleless】\\n\\nimport 'tailwindcss/utilities.css';\\n\\nexport default () => {\\n return <div className=\\\"bg-black text-white\\\">hello world11</div>;\\n};\\n\\n\\nBundle 模式下,会将第三方依赖打包进来。\\n\\n对于样式则会生成一份单独的产物文件,并且在 Js 产物文件中并不会存在导入样式的相关代码。\\n\\n如果需要将样式注入 Js 产物中,可以开启 style.inject API。\\n\\n<CH.Code>\\n\\n/* ../../node_modules/.pnpm/tailwindcss@2.2.19/node_modules/tailwindcss/utilities.css */\\n.table {\\n display: table;\\n}\\n@keyframes spin {\\n to {\\n transform: rotate(360deg);\\n }\\n}\\n@keyframes ping {\\n 75%, 100% {\\n transform: scale(2);\\n opacity: 0;\\n }\\n}\\n@keyframes pulse {\\n 50% {\\n opacity: .5;\\n }\\n}\\n@keyframes bounce {\\n 0%, 100% {\\n transform: translateY(-25%);\\n animation-timing-function: cubic-bezier(0.8, 0, 1, 1);\\n }\\n 50% {\\n transform: none;\\n animation-timing-function: cubic-bezier(0, 0, 0.2, 1);\\n }\\n}\\n.bg-black {\\n --tw-bg-opacity: 1;\\n background-color: rgba(0, 0, 0, var(--tw-bg-opacity));\\n}\\n.text-white {\\n --tw-text-opacity: 1;\\n color: rgba(255, 255, 255, var(--tw-text-opacity));\\n}\\n*,\\n::before,\\n::after {\\n --tw-shadow: 0 0 #0000 ;\\n}\\n*,\\n::before,\\n::after {\\n --tw-ring-inset: var(--tw-empty, );\\n --tw-ring-offset-width: 0px;\\n --tw-ring-offset-color: #fff;\\n --tw-ring-color: rgba(59, 130, 246, 0.5);\\n --tw-ring-offset-shadow: 0 0 #0000;\\n --tw-ring-shadow: 0 0 #0000 ;\\n}\\n@media (min-width: 640px) {\\n}\\n@media (min-width: 768px) {\\n}\\n@media (min-width: 1024px) {\\n}\\n@media (min-width: 1280px) {\\n}\\n@media (min-width: 1536px) {\\n}\\n\\n\\n--------------------------------------------------------------------------------\\n\\n// src/index.tsx\\n\\nvar src_default = () => {\\n return /* @__PURE__ */ jsx(\\\"div\\\", {\\n className: \\\"bg-black text-white\\\",\\n children: \\\"hello world11\\\"\\n });\\n};\\nexport {\\n src_default as default\\n};\\n\\n\\n</CH.Code>\\n\\nBundleless 模式下,并不会将第三方依赖打包进来,此时不会有样式产物生成。\\n\\n\\nimport 'tailwindcss/utilities.css';\\nvar src_default = () => {\\n return /* @__PURE__ */ jsx('div', {\\n className: 'bg-black text-white',\\n children: 'hello world11',\\n });\\n};\\nexport { src_default as default };\\n\\n\\n\\nCSS MODULES\\n\\n模块工程支持使用 CSS Module 开发样式。默认情况下会将以下文件识别为 CSS Module 文件:\\n\\n * .module.css\\n * .module.less\\n * .module.scss\\n * .module.sass\\n\\n如果需要对 CSS Modules 进行配置,可以查看一下 API:\\n\\n * autoModules\\n * modules\\n\\n下面是一个代码示例:\\n\\n<CH.Code>\\n\\n\\n\\nexport default () => {\\n return <div className={style.btn}>hello world</div>;\\n};\\n\\n\\n.btn {\\n color: blue;\\n}\\n\\n\\n</CH.Code>\\n\\n\\n配置构建产物\\n\\n根据组件项目使用的多数场景,推荐使用 npm-component 构建预设。该预设得到的产物目录结构为:\\n\\n.\\n├── dist\\n│ ├── es\\n│ ├── lib\\n│ └── types\\n\\n\\n * ./dist/es: 包含了支持 es6 语法的 ES modules 格式的 bundleless 产物。\\n * ./dist/lib: 包含了支持 es6 语法的 CommonJS 格式的 bundleless 产物。\\n * ./dist/types: 包含了类型文件。\\n\\n如果对使用语法支持有要求,可以手动配置 buildPreset,并且支持在 npm-component 基础上增加后缀的方式修改支持的语法:\\n\\nexport default defineConfig({\\n buildPreset: 'npm-component-es2019',\\n});\\n\\n\\n如果对构建产物目录结构有特殊需求,则可以使用 buildConfig API,可以通过以下文档来了解使用方式:\\n\\n * 修改输出产物\\n * 深入理解构建\\n\\n\\n测试组件\\n\\n关于如何对组件进行测试,可以参考 【测试项目】。\\n\\n\\n发布组件\\n\\n推荐使用模块工程提供版本发布功能,可以参考 【版本管理与发布】。\",\"frontmatter\":{\"sidebar_position\":1}},{\"title\":\"快速开始\",\"routePath\":\"/guide/intro/getting-started\",\"toc\":[{\"id\":\"三分钟快速上手\",\"text\":\"三分钟快速上手\",\"depth\":2},{\"id\":\"让我们开始吧\",\"text\":\"让我们开始吧\",\"depth\":2}],\"content\":\"快速开始\\n\\n\\n三分钟快速上手\\n\\n想要实际体验 Module Tools?首先需要安装 Node.js LTS,并确保 Node 版本大于等于 14.17.6。\\n\\n然后在你的项目里安装以下依赖:\\n\\n * @modern-js/module-tools\\n * @modern-js/plugin-testing\\n\\n> 如果是一个 TypeScript 项目,则需要增加 \\\"typescript\\\" 依赖。\\n\\nnpm install -D @modern-js/module-tools @modern-js/plugin-testing\\n\\n\\n> 对于使用 pnpm 或者 Yarn 包管理器的项目,只需要替换 npm 就可以了。推荐使用 pnpm。\\n\\n接着在项目的 package.json 文件里增加命令 \\\"build\\\": \\\"modern build\\\":\\n\\n{\\n \\\"scripts\\\": {\\n \\\"build\\\": \\\"modern build\\\"\\n }\\n}\\n\\n\\n如果你的项目存在 src/index.(js|jsx) 文件或者同时存在 src/index.(ts|tsx) 和 tsconfig.json\\n文件,那么恭喜你可以运行直接运行 npm run build 来使用 Module Tools 构建你的项目了。\\n\\n如果你想要看看使用了模块工程方案的真实项目,可以执行以下命令:\\n\\ngit clone https://github.com/modern-js-dev/module-tools-examples\\ncd module-tools-example\\n\\n## 执行构建:\\npnpm build\\n\\n## 监听模式执行构建:\\npnpm build --watch\\n\\n## 启动 Storybook\\npnpm dev storybook\\n\\n## 测试\\npnpm test\\n\\n\\n> 上面的链接对应的内容待补充\\n\\n如果你想要创建一个完整的模块工程项目,可以执行以下命令:\\n\\nnpx @modern-js/create your-project-dir-name\\n\\n\\n接着在问题交互中,按照如下选择:\\n\\n? 请选择你想创建的工程类型 模块\\n? 请填写项目名称 library\\n? 请选择开发语言 TS\\n? 请选择包管理工具 pnpm\\n\\n\\n> 项目名称为 package.json 中的 \\\"name\\\" 字段值。\\n\\n接着就会开始初始化项目的流程。在项目目录和文件生成以及依赖安装完毕后,此时就创建了一个完整的模块工程项目。\\n\\n我们可以直接执行 pnpm build 命令启动项目的构建,执行 pnpm build --watch 命令开启构建的观察模式。\\n\\n\\n让我们开始吧\\n\\n选择适合你的教程:\\n\\n * 我是初学者,需要学习 Module Tools 的基础使用。\\n * 我已经初步掌握了 Module Tools 的使用,可以学习 Module Tools 的高级使用。\\n * 我是项目的维护者,需要学习如何开发 Module Tools 的插件以及了解更多关于 Module Tools 进阶的内容。\",\"frontmatter\":{\"sidebar_position\":3}},{\"title\":\"欢迎使用\",\"routePath\":\"/guide/intro/welcome\",\"toc\":[],\"content\":\"欢迎使用\\n\\nModule Tools 是 Modern.js\\n的模块工程解决方案,同时也是核心依赖。它可以让开发者更轻松地构建、调试、发布模块类型的项目。模块类型的项目大多数情况可以认为是 npm\\n包类型的项目,它可能是一个组件、组件库或者工具库项目。\\n\\n如果你正打算开发一个 npm 包类型的项目,那么你就来对地方了!Modern.js 提供了专业的模块工程解决方案。它带来了:\\n\\n * 简单的项目初始化:仅需执行 npx @modern-js/create project-dir\\n 命令,然后进行几个交互问题,就可以创建一个完整的模块类型项目。创建的项目还支持选择 pnpm、Yarn 两种包管理器。\\n * 代码格式化:在模块工程项目中,你可以执行 modern lint 来对代码进行格式化。同时初始化的模块工程项目里包含了 Modern.js 的\\n ESLint 规则集,可以满足大部分场景下的需求。\\n * 全面的构建能力和更快的构建速度:Module Tools 基于 esbuild 和 SWC\\n 提供了高性能的构建能力,并且为不同构建模块的场景提供了丰富的配置。\\n * Storybook 调试工具:Module Tools 为调试模块项目提供了 Storybook 调试工具。在安装了 Module Tools 的\\n Storybook 插件后,你可以使用 modern dev storybook 命令来启动它。你不仅可以使用 Storybook\\n 对组件进行调试,也可以使用在其他类型的模块上。\\n * 集成 Jest 的测试能力:在需要对模块测试的时候,可以使用 Module Tools 的 modern test 命令。Module Tools\\n 不仅集成了 Jest,同时也提供了配置 Jest 的 API。\\n * 基于 Changesets 实现的版本管理:当需要对项目记录变更内容的时候,可以使用 modern change 命令生成包含变更内容的 Markdown\\n 文件;当需要对项目进行版本升级的时候,可以使用 modern bump 命令通过 Markdown 文件分析并升级版本;当需要发布项目的时候,可以使用\\n modern release 命令对项目进行发布。Module Tools 基于 Changesets 实现了这些命令。\\n * 可扩展性的插件机制:想要为项目集成其他的调试工具?又或者是想要在构建过程中做一些额外处理?Module Tools\\n 提供了插件机制和插件钩子,插件钩子覆盖了 dev 命令和 build 命令两个流程。你可以通过它们为项目进行能力的扩展。\\n * 还有更多:Module Tools\\n 在未来还会不断的在构建、调试功能上进行优化。如果在模块项目构建上存在需要解决的重要问题,又或者是某个主流的模块项目调试工具、模式出现的时候,那么它们很可能\\n 成为 Module Tools 将要支持功能。\",\"frontmatter\":{\"sidebar_position\":1}},{\"title\":\"为什么需要模块工程解决方案\",\"routePath\":\"/guide/intro/why-module-engineering-solution\",\"toc\":[],\"content\":\"为什么需要模块工程解决方案\\n\\n大家可能都经历过:从零开始开发一个组件库或者工具库的过程中,我们不仅要考虑项目本身的代码逻辑如何编写,还要考虑项目的构建、调试、测试、代码格式化等等和代码逻辑无\\n关的事情。\\n\\n比如说,当我们考虑构建模块项目的代码是使用什么构建工具的时候,在之前我们可能会考虑使用 webpack 还是 Rollup,然而现在的话,也许还会考虑是使用\\nesbuild 还是 SWC。\\n\\n无论选择哪个构建工具,这对于没有熟练掌握这些构建工具使用方式的开发者来说,是需要一定的成本去学习的。即使想要快速使用,也会需要花费大量的时间和精力。\\n\\n而除了构建这件事情以外,像为项目提供调试工具、支持测试能力、增加代码格式校验等等,对于一个新手来说都有可能需要花费很长的时间和精力了解或者掌握它们,并且真正的服\\n务于当前的项目中。\\n\\n而为了保证代码质量以及项目的完整性,我们往往是需要做这些与代码逻辑实现无关的事情。然而这些事情很有可能会影响整体的项目开发进度,降低开发者的开发体验,会让开发者\\n感觉模块项目的开发门槛很高。\\n\\n如果说每次开发一个模块类型的项目都需要经历一遍这些工作准备的话,那么基本上刚开始开发的时间会大部分花费在这些与代码实现无关的事情上。如果能够提供一个模块工程解决\\n方案,它能够帮助开发者解决项目工程上的事情,让开发者可以更专注于代码的实现上,那么这将会大大提升模块类型项目的开发体验。\\n\\n\\n\\nModern.js 为了让开发模块类型的项目更简单,为了解决上述提到的问题提供了模块工程解决方案,并且使用 Module Tools\\n提供了主要的功能。Module-tools 可以理解为是一个专门用于模块类型项目开发的工具。\",\"frontmatter\":{\"sidebar_position\":2}},{\"title\":\"index\",\"routePath\":\"/\",\"toc\":[],\"content\":\"INDEX\",\"frontmatter\":{\"pageType\":\"home\",\"hero\":{\"name\":\"Module tools\",\"text\":\"模块工程解决方案\",\"tagline\":\"简单、强大、高性能的现代化npm包开发方案\",\"actions\":[{\"theme\":\"brand\",\"text\":\"欢迎使用\",\"link\":\"/guide/intro/welcome\"}]},\"features\":[{\"title\":\"Esbuild: 高性能的JS Bundler\",\"details\":\"基于 Esbuild 构建,构建速度极快,带给你极致的开发体验。\",\"icon\":\"🚀\"},{\"title\":\"Storybook: 社区流行的UI开发工具\",\"details\":\"集成了Storybook,你可以使用它调试UI。\",\"icon\":\"📦\"},{\"title\":\"transform + bundle\",\"details\":\"支持bundle和bundleless两种构建模式。\",\"icon\":\"✨\"},{\"title\":\"零配置\",\"details\":\"无需任何配置即可开发你的npm包,内置预设覆盖多种场景。\",\"icon\":\"🛠️\"},{\"title\":\"扩展性强: 提供强大的插件机制\",\"details\":\"通过其插件扩展机制,你可以轻松的扩展Module tools的各项能力。\",\"icon\":\"🎨\"}]}},{\"title\":\"快速开始\",\"routePath\":\"/plugins/guide/getting-started\",\"toc\":[],\"content\":\"快速开始\\n\\n模块工程解决方案不仅提供了丰富的功能,同时也支持通过插件的方式为当前项目扩展能力。\\n\\n我们可以通过下面的例子来快速了解如果编写一个 module-tools 插件:\\n\\n<CH.Spotlight>\\n\\n./\\n├── plugins\\n│ └── example.ts\\n├── src/\\n└── modern.config.ts\\n\\n\\n--------------------------------------------------------------------------------\\n\\n首先我们在初始化的项目下创建 ./plugins/example.ts 文件。\\n\\n\\n\\n--------------------------------------------------------------------------------\\n\\n接着在 example.ts 文件中增加插件的代码。\\n\\n\\n\\nexport const ExamplePlugin = (): CliPlugin<ModuleTools> => {\\n return {\\n name: 'example',\\n setup() {\\n console.info('this is example plugin');\\n return {\\n // use hooks\\n afterBuild() {\\n console.info('build over');\\n }\\n };\\n };\\n };\\n};\\n\\n\\n--------------------------------------------------------------------------------\\n\\n然后我们通过 plugins API,将刚刚写好的插件进行注册。\\n\\n\\nexport default defineConfig({\\n plugins: [ExamplePlugin()],\\n});\\n\\n\\n--------------------------------------------------------------------------------\\n\\n最后运行 modern build,就可以看到。\\n\\nthis is example plugin\\nBuild succeed: 510.684ms\\nbuild over\\n\\n\\n</CH.Spotlight>\\n\\n通过上面这个例子,我们了解到了下面几件事:\\n\\n * 推荐的插件目录结构\\n * 插件的初始化代码\\n * 插件的注册\\n\\n除了以上内容以外,我们还需要了解:\\n\\n * 插件对象、类型定义与推荐配置项\\n * setup 函数、api 对象参数、生命周期钩子\",\"frontmatter\":{\"sidebar_position\":1}},{\"title\":\"插件对象\",\"routePath\":\"/plugins/guide/plugin-object\",\"toc\":[{\"id\":\"插件类型定义\",\"text\":\"插件类型定义\",\"depth\":2},{\"id\":\"插件配置项\",\"text\":\"插件配置项\",\"depth\":2}],\"content\":\"插件对象\\n\\nModule-tools 插件是一个对象,对象包含以下属性:\\n\\n * name:插件的名称,唯一标识符。\\n * setup:插件初始化函数,只会执行一次。setup 函数可以返回一个 Hooks 对象,module-tools 会在特定的时机执行 Hooks\\n 对象上定义的 Hook 对应的函数。\\n\\n例如在下面的插件代码示例中,在项目开始执行构建任务之前会触发 beforeBuild 函数的执行,并打印 build start 的 log 内容。\\n\\n<CH.Code>\\n\\n\\n\\nconst MyPlugin: CliPlugin<ModuleTools> = {\\n name: 'my-plugin',\\n\\n setup() {\\n return {\\n // this is hook\\n beforeBuild: () => {\\n console.info('build start');\\n },\\n };\\n },\\n};\\n\\n\\n--------------------------------------------------------------------------------\\n\\n\\nexport default {\\n plugins: [MyPlugin()],\\n};\\n\\n\\n</CH.Code>\\n\\n\\n插件类型定义\\n\\n使用 TypeScript 时,可以引入内置的 CliPlugin 和 ModuleTools 类型,为插件提供正确的类型推导:\\n\\n\\n\\nconst MyPlugin: CliPlugin<ModuleTools> = {\\n name: 'my-plugin',\\n\\n setup() {\\n const foo = '1';\\n\\n return {\\n // this is hook\\n afterBuild: () => {\\n //...\\n },\\n };\\n },\\n};\\n\\n\\n\\n插件配置项\\n\\n建议将插件写成函数的形式,使插件能通过函数入参来接收配置项:\\n\\n\\n\\ntype MyPluginOptions = {\\n foo: string;\\n};\\n\\nconst MyPlugin = (options: MyPluginOptions): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup() {\\n console.log(options.foo);\\n },\\n});\\n\",\"frontmatter\":{\"sidebar_position\":2}},{\"title\":\"Setup 函数\",\"routePath\":\"/plugins/guide/setup-function\",\"toc\":[{\"id\":\"插件-api-对象\",\"text\":\"插件 API 对象\",\"depth\":2},{\"id\":\"apiuseappcontext-1\",\"text\":\"api.useAppContext\",\"depth\":3},{\"id\":\"apiuseresolvedconfigcontext-1\",\"text\":\"api.useResolvedConfigContext\",\"depth\":3},{\"id\":\"apiusehookrunners-1\",\"text\":\"api.useHookRunners\",\"depth\":3},{\"id\":\"异步-setup\",\"text\":\"异步 setup\",\"depth\":2},{\"id\":\"生命周期钩子\",\"text\":\"生命周期钩子\",\"depth\":2}],\"content\":\"SETUP 函数\\n\\n在【插件对象】 部分我们知道插件对象包含了一个 setup 函数,该函数不仅包含了一个 api 对象参数,同时还可以返回一个 Hooks 对象。\\n\\n\\n插件 API 对象\\n\\n插件的 setup 函数会提供一个 api 对象参数,你可以调用该对象上提供的一些方法来获取到配置、项目上下文等信息。\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n setup(api) {\\n // 获取应用原始配置\\n const config = api.useConfigContext();\\n // 获取应用运行上下文\\n const appContext = api.useAppContext();\\n // 获取解析之后的最终配置\\n const resolvedConfig = api.useResolvedConfigContext();\\n },\\n});\\n\\n\\n\\nAPI.USEAPPCONTEXT\\n\\n用于获取项目上下文信息。\\n\\nconst useAppContext: () => IAppContext;\\n\\ninterface IAppContext {\\n appDirectory: string;\\n configFile: string | false;\\n packageName: string;\\n nodeModulesDirectory: string;\\n internalDirectory: string;\\n plugins: {\\n cli?: any;\\n server?: any;\\n }[];\\n}\\n\\n\\n通过实际的类型文件我们可以看到还存在着其他的字段,不过目前对于模块工程有意义的字段只有以上内容。api 对象其他的方法也是如此。\\n\\n\\nAPI.USERESOLVEDCONFIGCONTEXT\\n\\n用于获取解析之后的最终配置。\\n\\n如果需要获取构建相关的最终配置,需要使用 beforeBuild Hook。\\n\\nconst useResolvedConfigContext: () => NormalizedConfig;\\n\\ninterface NormalizedConfig {\\n buildConfig: PartialBuildConfig;\\n buildPreset: BuildPreset;\\n designSystem?: Record<string, any>;\\n dev: Dev;\\n plugins: PluginConfig;\\n runtime: RuntimeConfig;\\n runtimeByEntries?: RuntimeByEntriesConfig;\\n _raw: UserConfig;\\n}\\n\\n\\n\\nAPI.USEHOOKRUNNERS\\n\\n用于获取 Hooks 的执行器,并触发特定的 Hook 执行。\\n\\n\\n\\nexport default (): CliPlugin => ({\\n name: 'my-plugin',\\n\\n async setup(api) {\\n const hookRunners = api.useHookRunners();\\n // 触发 afterBuild Hook\\n await hookRunners.afterBuild();\\n },\\n});\\n\\n\\n\\n异步 SETUP\\n\\nCLI 插件的 setup 可以是一个异步函数,在初始化过程中执行异步逻辑。\\n\\nexport default (): CliPlugin<ModuleTools> => ({\\n name: 'my-plugin',\\n\\n async setup(api) {\\n await doSomething();\\n },\\n});\\n\\n\\n\\n生命周期钩子\\n\\n我们知道 setup 函数会返回一个 Hooks 对象,所谓 Hooks 对象也可以理解是具有 module-tools 生命周期钩子的对象。\\n\\n目前主要包含两类钩子:\\n\\n * 构建钩子:仅在执行 build 命令构建源码产物时触发。\\n * buildPlatform 钩子:仅在执行 build --platform 命令生成其他构建产物时触发。\\n * 调试钩子:运行 dev 命令时会触发的钩子。\\n\\n关于生命周期钩子的完整列表参考 API 文档。\",\"frontmatter\":{\"sidebar_position\":3}},{\"title\":\"总览\",\"routePath\":\"/plugins/official-list/overview\",\"toc\":[{\"id\":\"官方插件\",\"text\":\"官方插件\",\"depth\":2}],\"content\":\"总览\\n\\n\\n官方插件\\n\\n(建设中)\",\"frontmatter\":{}}]}","\nimport React from 'react';\nimport { lazyWithPreload } from \"react-lazy-with-preload\";\nconst Route0 = lazyWithPreload(() => import(/* webpackChunkName: \"en_api_config_build-config\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/api/config/build-config.md'))\nconst Route1 = lazyWithPreload(() => import(/* webpackChunkName: \"en_api_config_build-preset\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/api/config/build-preset.md'))\nconst Route2 = lazyWithPreload(() => import(/* webpackChunkName: \"en_api_config_design-system\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/api/config/design-system.md'))\nconst Route3 = lazyWithPreload(() => import(/* webpackChunkName: \"en_api_config_plugins\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/api/config/plugins.md'))\nconst Route4 = lazyWithPreload(() => import(/* webpackChunkName: \"en_api_config_testing\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/api/config/testing.md'))\nconst Route5 = lazyWithPreload(() => import(/* webpackChunkName: \"en_api_\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/api/index.md'))\nconst Route6 = lazyWithPreload(() => import(/* webpackChunkName: \"en_api_plugin-api_plugin-hooks\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/api/plugin-api/plugin-hooks.md'))\nconst Route7 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_advance_asset\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/asset.mdx'))\nconst Route8 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_advance_build-umd\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/build-umd.mdx'))\nconst Route9 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_advance_copy\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/copy.md'))\nconst Route10 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_advance_external-dependency\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/external-dependency.mdx'))\nconst Route11 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_advance_in-depth-about-build\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/in-depth-about-build.md'))\nconst Route12 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_advance_in-depth-about-dev-command\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/in-depth-about-dev-command.md'))\nconst Route13 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_advance_theme-config\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/theme-config.mdx'))\nconst Route14 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_basic_before-getting-started\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/before-getting-started.md'))\nconst Route15 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_basic_command-preview\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/command-preview.md'))\nconst Route16 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_basic_modify-output-product\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/modify-output-product.md'))\nconst Route17 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_basic_publish-your-project\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/publish-your-project.md'))\nconst Route18 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_basic_test-your-project\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/test-your-project.mdx'))\nconst Route19 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_basic_use-micro-generator\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/use-micro-generator.md'))\nconst Route20 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_basic_using-storybook\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/using-storybook.mdx'))\nconst Route21 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_best-practices_components\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/best-practices/components.mdx'))\nconst Route22 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_intro_getting-started\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/intro/getting-started.md'))\nconst Route23 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_intro_welcome\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/intro/welcome.md'))\nconst Route24 = lazyWithPreload(() => import(/* webpackChunkName: \"en_guide_intro_why-module-engineering-solution\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/guide/intro/why-module-engineering-solution.md'))\nconst Route25 = lazyWithPreload(() => import(/* webpackChunkName: \"en_\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/index.md'))\nconst Route26 = lazyWithPreload(() => import(/* webpackChunkName: \"en_plugins_guide_getting-started\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/plugins/guide/getting-started.mdx'))\nconst Route27 = lazyWithPreload(() => import(/* webpackChunkName: \"en_plugins_guide_plugin-object\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/plugins/guide/plugin-object.mdx'))\nconst Route28 = lazyWithPreload(() => import(/* webpackChunkName: \"en_plugins_guide_setup-function\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/plugins/guide/setup-function.mdx'))\nconst Route29 = lazyWithPreload(() => import(/* webpackChunkName: \"en_plugins_official-list_overview\" */'/Users/bytedance/modern.js/website/module-tools/docs/en/plugins/official-list/overview.md'))\nconst Route30 = lazyWithPreload(() => import(/* webpackChunkName: \"api_config_build-config\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/api/config/build-config.md'))\nconst Route31 = lazyWithPreload(() => import(/* webpackChunkName: \"api_config_build-preset\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/api/config/build-preset.md'))\nconst Route32 = lazyWithPreload(() => import(/* webpackChunkName: \"api_config_design-system\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/api/config/design-system.md'))\nconst Route33 = lazyWithPreload(() => import(/* webpackChunkName: \"api_config_plugins\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/api/config/plugins.md'))\nconst Route34 = lazyWithPreload(() => import(/* webpackChunkName: \"api_config_testing\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/api/config/testing.md'))\nconst Route35 = lazyWithPreload(() => import(/* webpackChunkName: \"api_\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/api/index.md'))\nconst Route36 = lazyWithPreload(() => import(/* webpackChunkName: \"api_plugin-api_plugin-hooks\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/api/plugin-api/plugin-hooks.md'))\nconst Route37 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_advance_asset\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/asset.mdx'))\nconst Route38 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_advance_build-umd\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/build-umd.mdx'))\nconst Route39 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_advance_copy\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/copy.md'))\nconst Route40 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_advance_external-dependency\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/external-dependency.mdx'))\nconst Route41 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_advance_in-depth-about-build\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/in-depth-about-build.md'))\nconst Route42 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_advance_in-depth-about-dev-command\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/in-depth-about-dev-command.md'))\nconst Route43 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_advance_theme-config\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/theme-config.mdx'))\nconst Route44 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_basic_before-getting-started\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/before-getting-started.md'))\nconst Route45 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_basic_command-preview\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/command-preview.md'))\nconst Route46 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_basic_modify-output-product\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/modify-output-product.md'))\nconst Route47 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_basic_publish-your-project\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/publish-your-project.md'))\nconst Route48 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_basic_test-your-project\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/test-your-project.mdx'))\nconst Route49 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_basic_use-micro-generator\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/use-micro-generator.md'))\nconst Route50 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_basic_using-storybook\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/using-storybook.mdx'))\nconst Route51 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_best-practices_components\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/best-practices/components.mdx'))\nconst Route52 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_intro_getting-started\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/intro/getting-started.md'))\nconst Route53 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_intro_welcome\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/intro/welcome.md'))\nconst Route54 = lazyWithPreload(() => import(/* webpackChunkName: \"guide_intro_why-module-engineering-solution\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/intro/why-module-engineering-solution.md'))\nconst Route55 = lazyWithPreload(() => import(/* webpackChunkName: \"index\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/index.md'))\nconst Route56 = lazyWithPreload(() => import(/* webpackChunkName: \"plugins_guide_getting-started\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/plugins/guide/getting-started.mdx'))\nconst Route57 = lazyWithPreload(() => import(/* webpackChunkName: \"plugins_guide_plugin-object\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/plugins/guide/plugin-object.mdx'))\nconst Route58 = lazyWithPreload(() => import(/* webpackChunkName: \"plugins_guide_setup-function\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/plugins/guide/setup-function.mdx'))\nconst Route59 = lazyWithPreload(() => import(/* webpackChunkName: \"plugins_official-list_overview\" */'/Users/bytedance/modern.js/website/module-tools/docs/zh/plugins/official-list/overview.md'))\nexport const routes = [\n{ path: '/en/api/config/build-config', element: React.createElement(Route0), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/api/config/build-config.md', preload: async () => { \n await Route0.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/api/config/build-config.md\");\n } },\n{ path: '/en/api/config/build-preset', element: React.createElement(Route1), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/api/config/build-preset.md', preload: async () => { \n await Route1.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/api/config/build-preset.md\");\n } },\n{ path: '/en/api/config/design-system', element: React.createElement(Route2), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/api/config/design-system.md', preload: async () => { \n await Route2.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/api/config/design-system.md\");\n } },\n{ path: '/en/api/config/plugins', element: React.createElement(Route3), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/api/config/plugins.md', preload: async () => { \n await Route3.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/api/config/plugins.md\");\n } },\n{ path: '/en/api/config/testing', element: React.createElement(Route4), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/api/config/testing.md', preload: async () => { \n await Route4.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/api/config/testing.md\");\n } },\n{ path: '/en/api/', element: React.createElement(Route5), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/api/index.md', preload: async () => { \n await Route5.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/api/index.md\");\n } },\n{ path: '/en/api/plugin-api/plugin-hooks', element: React.createElement(Route6), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/api/plugin-api/plugin-hooks.md', preload: async () => { \n await Route6.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/api/plugin-api/plugin-hooks.md\");\n } },\n{ path: '/en/guide/advance/asset', element: React.createElement(Route7), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/asset.mdx', preload: async () => { \n await Route7.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/asset.mdx\");\n } },\n{ path: '/en/guide/advance/build-umd', element: React.createElement(Route8), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/build-umd.mdx', preload: async () => { \n await Route8.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/build-umd.mdx\");\n } },\n{ path: '/en/guide/advance/copy', element: React.createElement(Route9), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/copy.md', preload: async () => { \n await Route9.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/copy.md\");\n } },\n{ path: '/en/guide/advance/external-dependency', element: React.createElement(Route10), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/external-dependency.mdx', preload: async () => { \n await Route10.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/external-dependency.mdx\");\n } },\n{ path: '/en/guide/advance/in-depth-about-build', element: React.createElement(Route11), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/in-depth-about-build.md', preload: async () => { \n await Route11.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/in-depth-about-build.md\");\n } },\n{ path: '/en/guide/advance/in-depth-about-dev-command', element: React.createElement(Route12), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/in-depth-about-dev-command.md', preload: async () => { \n await Route12.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/in-depth-about-dev-command.md\");\n } },\n{ path: '/en/guide/advance/theme-config', element: React.createElement(Route13), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/theme-config.mdx', preload: async () => { \n await Route13.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/advance/theme-config.mdx\");\n } },\n{ path: '/en/guide/basic/before-getting-started', element: React.createElement(Route14), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/before-getting-started.md', preload: async () => { \n await Route14.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/before-getting-started.md\");\n } },\n{ path: '/en/guide/basic/command-preview', element: React.createElement(Route15), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/command-preview.md', preload: async () => { \n await Route15.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/command-preview.md\");\n } },\n{ path: '/en/guide/basic/modify-output-product', element: React.createElement(Route16), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/modify-output-product.md', preload: async () => { \n await Route16.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/modify-output-product.md\");\n } },\n{ path: '/en/guide/basic/publish-your-project', element: React.createElement(Route17), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/publish-your-project.md', preload: async () => { \n await Route17.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/publish-your-project.md\");\n } },\n{ path: '/en/guide/basic/test-your-project', element: React.createElement(Route18), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/test-your-project.mdx', preload: async () => { \n await Route18.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/test-your-project.mdx\");\n } },\n{ path: '/en/guide/basic/use-micro-generator', element: React.createElement(Route19), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/use-micro-generator.md', preload: async () => { \n await Route19.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/use-micro-generator.md\");\n } },\n{ path: '/en/guide/basic/using-storybook', element: React.createElement(Route20), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/using-storybook.mdx', preload: async () => { \n await Route20.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/basic/using-storybook.mdx\");\n } },\n{ path: '/en/guide/best-practices/components', element: React.createElement(Route21), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/best-practices/components.mdx', preload: async () => { \n await Route21.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/best-practices/components.mdx\");\n } },\n{ path: '/en/guide/intro/getting-started', element: React.createElement(Route22), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/intro/getting-started.md', preload: async () => { \n await Route22.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/intro/getting-started.md\");\n } },\n{ path: '/en/guide/intro/welcome', element: React.createElement(Route23), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/intro/welcome.md', preload: async () => { \n await Route23.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/intro/welcome.md\");\n } },\n{ path: '/en/guide/intro/why-module-engineering-solution', element: React.createElement(Route24), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/guide/intro/why-module-engineering-solution.md', preload: async () => { \n await Route24.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/guide/intro/why-module-engineering-solution.md\");\n } },\n{ path: '/en/', element: React.createElement(Route25), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/index.md', preload: async () => { \n await Route25.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/index.md\");\n } },\n{ path: '/en/plugins/guide/getting-started', element: React.createElement(Route26), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/plugins/guide/getting-started.mdx', preload: async () => { \n await Route26.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/plugins/guide/getting-started.mdx\");\n } },\n{ path: '/en/plugins/guide/plugin-object', element: React.createElement(Route27), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/plugins/guide/plugin-object.mdx', preload: async () => { \n await Route27.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/plugins/guide/plugin-object.mdx\");\n } },\n{ path: '/en/plugins/guide/setup-function', element: React.createElement(Route28), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/plugins/guide/setup-function.mdx', preload: async () => { \n await Route28.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/plugins/guide/setup-function.mdx\");\n } },\n{ path: '/en/plugins/official-list/overview', element: React.createElement(Route29), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/en/plugins/official-list/overview.md', preload: async () => { \n await Route29.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/en/plugins/official-list/overview.md\");\n } },\n{ path: '/api/config/build-config', element: React.createElement(Route30), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/api/config/build-config.md', preload: async () => { \n await Route30.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/api/config/build-config.md\");\n } },\n{ path: '/api/config/build-preset', element: React.createElement(Route31), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/api/config/build-preset.md', preload: async () => { \n await Route31.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/api/config/build-preset.md\");\n } },\n{ path: '/api/config/design-system', element: React.createElement(Route32), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/api/config/design-system.md', preload: async () => { \n await Route32.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/api/config/design-system.md\");\n } },\n{ path: '/api/config/plugins', element: React.createElement(Route33), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/api/config/plugins.md', preload: async () => { \n await Route33.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/api/config/plugins.md\");\n } },\n{ path: '/api/config/testing', element: React.createElement(Route34), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/api/config/testing.md', preload: async () => { \n await Route34.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/api/config/testing.md\");\n } },\n{ path: '/api/', element: React.createElement(Route35), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/api/index.md', preload: async () => { \n await Route35.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/api/index.md\");\n } },\n{ path: '/api/plugin-api/plugin-hooks', element: React.createElement(Route36), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/api/plugin-api/plugin-hooks.md', preload: async () => { \n await Route36.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/api/plugin-api/plugin-hooks.md\");\n } },\n{ path: '/guide/advance/asset', element: React.createElement(Route37), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/asset.mdx', preload: async () => { \n await Route37.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/asset.mdx\");\n } },\n{ path: '/guide/advance/build-umd', element: React.createElement(Route38), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/build-umd.mdx', preload: async () => { \n await Route38.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/build-umd.mdx\");\n } },\n{ path: '/guide/advance/copy', element: React.createElement(Route39), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/copy.md', preload: async () => { \n await Route39.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/copy.md\");\n } },\n{ path: '/guide/advance/external-dependency', element: React.createElement(Route40), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/external-dependency.mdx', preload: async () => { \n await Route40.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/external-dependency.mdx\");\n } },\n{ path: '/guide/advance/in-depth-about-build', element: React.createElement(Route41), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/in-depth-about-build.md', preload: async () => { \n await Route41.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/in-depth-about-build.md\");\n } },\n{ path: '/guide/advance/in-depth-about-dev-command', element: React.createElement(Route42), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/in-depth-about-dev-command.md', preload: async () => { \n await Route42.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/in-depth-about-dev-command.md\");\n } },\n{ path: '/guide/advance/theme-config', element: React.createElement(Route43), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/theme-config.mdx', preload: async () => { \n await Route43.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/advance/theme-config.mdx\");\n } },\n{ path: '/guide/basic/before-getting-started', element: React.createElement(Route44), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/before-getting-started.md', preload: async () => { \n await Route44.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/before-getting-started.md\");\n } },\n{ path: '/guide/basic/command-preview', element: React.createElement(Route45), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/command-preview.md', preload: async () => { \n await Route45.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/command-preview.md\");\n } },\n{ path: '/guide/basic/modify-output-product', element: React.createElement(Route46), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/modify-output-product.md', preload: async () => { \n await Route46.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/modify-output-product.md\");\n } },\n{ path: '/guide/basic/publish-your-project', element: React.createElement(Route47), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/publish-your-project.md', preload: async () => { \n await Route47.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/publish-your-project.md\");\n } },\n{ path: '/guide/basic/test-your-project', element: React.createElement(Route48), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/test-your-project.mdx', preload: async () => { \n await Route48.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/test-your-project.mdx\");\n } },\n{ path: '/guide/basic/use-micro-generator', element: React.createElement(Route49), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/use-micro-generator.md', preload: async () => { \n await Route49.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/use-micro-generator.md\");\n } },\n{ path: '/guide/basic/using-storybook', element: React.createElement(Route50), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/using-storybook.mdx', preload: async () => { \n await Route50.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/basic/using-storybook.mdx\");\n } },\n{ path: '/guide/best-practices/components', element: React.createElement(Route51), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/best-practices/components.mdx', preload: async () => { \n await Route51.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/best-practices/components.mdx\");\n } },\n{ path: '/guide/intro/getting-started', element: React.createElement(Route52), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/intro/getting-started.md', preload: async () => { \n await Route52.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/intro/getting-started.md\");\n } },\n{ path: '/guide/intro/welcome', element: React.createElement(Route53), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/intro/welcome.md', preload: async () => { \n await Route53.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/intro/welcome.md\");\n } },\n{ path: '/guide/intro/why-module-engineering-solution', element: React.createElement(Route54), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/intro/why-module-engineering-solution.md', preload: async () => { \n await Route54.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/guide/intro/why-module-engineering-solution.md\");\n } },\n{ path: '/', element: React.createElement(Route55), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/index.md', preload: async () => { \n await Route55.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/index.md\");\n } },\n{ path: '/plugins/guide/getting-started', element: React.createElement(Route56), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/plugins/guide/getting-started.mdx', preload: async () => { \n await Route56.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/plugins/guide/getting-started.mdx\");\n } },\n{ path: '/plugins/guide/plugin-object', element: React.createElement(Route57), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/plugins/guide/plugin-object.mdx', preload: async () => { \n await Route57.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/plugins/guide/plugin-object.mdx\");\n } },\n{ path: '/plugins/guide/setup-function', element: React.createElement(Route58), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/plugins/guide/setup-function.mdx', preload: async () => { \n await Route58.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/plugins/guide/setup-function.mdx\");\n } },\n{ path: '/plugins/official-list/overview', element: React.createElement(Route59), filePath: '/Users/bytedance/modern.js/website/module-tools/docs/zh/plugins/official-list/overview.md', preload: async () => { \n await Route59.preload();\n return import(\"/Users/bytedance/modern.js/website/module-tools/docs/zh/plugins/official-list/overview.md\");\n } }\n];\n"],"names":[],"sourceRoot":""}
|