diff --git a/package.json b/package.json index 93b5202..2057578 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ }, "devDependencies": { "@babel/core": "^7.22.9", + "@highlightjs/vue-plugin": "^2.1.0", "@rollup/plugin-node-resolve": "^15.1.0", "@rollup/plugin-replace": "^5.0.2", "@rollup/plugin-terser": "^0.4.3", @@ -41,6 +42,7 @@ "@vue/composition-api": "^1.7.1", "@vue/eslint-config-prettier": "^6.0.0", "@vue/eslint-config-typescript": "^10.0.0", + "@vueuse/core": "^10.4.1", "comment-mark": "^1.1.1", "core-js": "^3.32.0", "echarts": "^5.4.3", @@ -49,12 +51,12 @@ "eslint": "^7.32.0", "eslint-plugin-prettier": "^3.4.1", "eslint-plugin-vue": "^8.7.1", + "highlight.js": "^11.8.0", "pinia": "^2.1.6", "postcss": "^8.4.27", "postcss-loader": "^5.3.0", "postcss-nested": "^5.0.6", "prettier": "^2.8.8", - "qs": "^6.11.2", "raw-loader": "^4.0.2", "resize-detector": "^0.3.0", "rimraf": "^3.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 01dad38..1ea4c74 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,6 +16,9 @@ devDependencies: '@babel/core': specifier: ^7.22.9 version: 7.22.9 + '@highlightjs/vue-plugin': + specifier: ^2.1.0 + version: 2.1.0(highlight.js@11.8.0)(vue@3.3.4) '@rollup/plugin-node-resolve': specifier: ^15.1.0 version: 15.1.0(rollup@2.79.1) @@ -58,6 +61,9 @@ devDependencies: '@vue/eslint-config-typescript': specifier: ^10.0.0 version: 10.0.0(eslint-plugin-vue@8.7.1)(eslint@7.32.0)(typescript@4.6.4) + '@vueuse/core': + specifier: ^10.4.1 + version: 10.4.1(@vue/composition-api@1.7.1)(vue@3.3.4) comment-mark: specifier: ^1.1.1 version: 1.1.1 @@ -82,6 +88,9 @@ devDependencies: eslint-plugin-vue: specifier: ^8.7.1 version: 8.7.1(eslint@7.32.0) + highlight.js: + specifier: ^11.8.0 + version: 11.8.0 pinia: specifier: ^2.1.6 version: 2.1.6(@vue/composition-api@1.7.1)(typescript@4.6.4)(vue@3.3.4) @@ -97,9 +106,6 @@ devDependencies: prettier: specifier: ^2.8.8 version: 2.8.8 - qs: - specifier: ^6.11.2 - version: 6.11.2 raw-loader: specifier: ^4.0.2 version: 4.0.2(webpack@5.88.2) @@ -1440,6 +1446,16 @@ packages: '@hapi/hoek': 9.3.0 dev: true + /@highlightjs/vue-plugin@2.1.0(highlight.js@11.8.0)(vue@3.3.4): + resolution: {integrity: sha512-E+bmk4ncca+hBEYRV2a+1aIzIV0VSY/e5ArjpuSN9IO7wBJrzUE2u4ESCwrbQD7sAy+jWQjkV5qCCWgc+pu7CQ==} + peerDependencies: + highlight.js: ^11.0.1 + vue: ^3 + dependencies: + highlight.js: 11.8.0 + vue: 3.3.4 + dev: true + /@humanwhocodes/config-array@0.5.0: resolution: {integrity: sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==} engines: {node: '>=10.10.0'} @@ -1813,6 +1829,10 @@ packages: resolution: {integrity: sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==} dev: true + /@types/web-bluetooth@0.0.17: + resolution: {integrity: sha512-4p9vcSmxAayx72yn70joFoL44c9MO/0+iVEBIQXe3v2h2SiAsEIo/G5v6ObFWvNKRFjbrVadNf9LqEEZeQPzdA==} + dev: true + /@types/webpack-env@1.18.1: resolution: {integrity: sha512-D0HJET2/UY6k9L6y3f5BL+IDxZmPkYmPT4+qBrRdmRLYRuV0qNKizMgTvYxXZYn+36zjPeoDZAEYBCM6XB+gww==} dev: true @@ -2697,6 +2717,31 @@ packages: resolution: {integrity: sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==} dev: true + /@vueuse/core@10.4.1(@vue/composition-api@1.7.1)(vue@3.3.4): + resolution: {integrity: sha512-DkHIfMIoSIBjMgRRvdIvxsyboRZQmImofLyOHADqiVbQVilP8VVHDhBX2ZqoItOgu7dWa8oXiNnScOdPLhdEXg==} + dependencies: + '@types/web-bluetooth': 0.0.17 + '@vueuse/metadata': 10.4.1 + '@vueuse/shared': 10.4.1(@vue/composition-api@1.7.1)(vue@3.3.4) + vue-demi: 0.14.5(@vue/composition-api@1.7.1)(vue@3.3.4) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: true + + /@vueuse/metadata@10.4.1: + resolution: {integrity: sha512-2Sc8X+iVzeuMGHr6O2j4gv/zxvQGGOYETYXEc41h0iZXIRnRbJZGmY/QP8dvzqUelf8vg0p/yEA5VpCEu+WpZg==} + dev: true + + /@vueuse/shared@10.4.1(@vue/composition-api@1.7.1)(vue@3.3.4): + resolution: {integrity: sha512-vz5hbAM4qA0lDKmcr2y3pPdU+2EVw/yzfRsBdu+6+USGa4PxqSQRYIUC9/NcT06y+ZgaTsyURw2I9qOFaaXHAg==} + dependencies: + vue-demi: 0.14.5(@vue/composition-api@1.7.1)(vue@3.3.4) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: true + /@webassemblyjs/ast@1.11.6: resolution: {integrity: sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==} dependencies: @@ -4899,6 +4944,11 @@ packages: resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} dev: true + /highlight.js@11.8.0: + resolution: {integrity: sha512-MedQhoqVdr0U6SSnWPzfiadUcDHfN/Wzq25AkXiQv9oiOO/sG0S7XkvpFIqWBl9Yq1UYyYOOVORs5UW2XlPyzg==} + engines: {node: '>=12.0.0'} + dev: true + /hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} dev: true @@ -6508,13 +6558,6 @@ packages: side-channel: 1.0.4 dev: true - /qs@6.11.2: - resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==} - engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.4 - dev: true - /query-string@7.1.3: resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} engines: {node: '>=6'} diff --git a/src/demo/CodeGen.vue b/src/demo/CodeGen.vue new file mode 100644 index 0000000..cf6201c --- /dev/null +++ b/src/demo/CodeGen.vue @@ -0,0 +1,316 @@ + + + + + diff --git a/src/demo/Demo.vue b/src/demo/Demo.vue index c133ee6..1fc9c6b 100644 --- a/src/demo/Demo.vue +++ b/src/demo/Demo.vue @@ -1,3 +1,42 @@ + + - - - diff --git a/src/demo/examples/Example.vue b/src/demo/examples/Example.vue index 21b6df8..266b4e4 100644 --- a/src/demo/examples/Example.vue +++ b/src/demo/examples/Example.vue @@ -6,17 +6,17 @@
-
+
- +
@@ -37,3 +37,64 @@ defineProps({ split: Boolean }); + + diff --git a/src/demo/utils/LICENSE b/src/demo/utils/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/src/demo/utils/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/src/demo/utils/codegen.js b/src/demo/utils/codegen.js new file mode 100644 index 0000000..3f5a325 --- /dev/null +++ b/src/demo/utils/codegen.js @@ -0,0 +1,470 @@ +// Modified from https://github.com/apache/echarts-examples/blob/b644ced5325ea2522cb11606df54eae69bba3a3a/common/buildCode.js +// See license at `./LICENSE`. + +const COMPONENTS_MAP = { + grid: "GridComponent", + polar: "PolarComponent", + geo: "GeoComponent", + singleAxis: "SingleAxisComponent", + parallel: "ParallelComponent", + calendar: "CalendarComponent", + graphic: "GraphicComponent", + toolbox: "ToolboxComponent", + tooltip: "TooltipComponent", + axisPointer: "AxisPointerComponent", + brush: "BrushComponent", + title: "TitleComponent", + timeline: "TimelineComponent", + markPoint: "MarkPointComponent", + markLine: "MarkLineComponent", + markArea: "MarkAreaComponent", + legend: "LegendComponent", + dataZoom: "DataZoomComponent", + visualMap: "VisualMapComponent", + aria: "AriaComponent", + dataset: "DatasetComponent", + + // Dependencies + xAxis: "GridComponent", + yAxis: "GridComponent", + angleAxis: "PolarComponent", + radiusAxis: "PolarComponent" +}; + +const CHARTS_MAP = { + line: "LineChart", + bar: "BarChart", + pie: "PieChart", + scatter: "ScatterChart", + radar: "RadarChart", + map: "MapChart", + tree: "TreeChart", + treemap: "TreemapChart", + graph: "GraphChart", + gauge: "GaugeChart", + funnel: "FunnelChart", + parallel: "ParallelChart", + sankey: "SankeyChart", + boxplot: "BoxplotChart", + candlestick: "CandlestickChart", + effectScatter: "EffectScatterChart", + lines: "LinesChart", + heatmap: "HeatmapChart", + pictorialBar: "PictorialBarChart", + themeRiver: "ThemeRiverChart", + sunburst: "SunburstChart", + custom: "CustomChart" +}; + +const COMPONENTS_GL_MAP = { + grid3D: "Grid3DComponent", + geo3D: "Geo3DComponent", + globe: "GlobeComponent", + mapbox3D: "Mapbox3DComponent", + maptalks3D: "Maptalks3DComponent", + + // Dependencies + xAxis3D: "Grid3DComponent", + yAxis3D: "Grid3DComponent", + zAxis3D: "Grid3DComponent" +}; + +const CHARTS_GL_MAP = { + bar3D: "Bar3DChart", + line3D: "Line3DChart", + scatter3D: "Scatter3DChart", + lines3D: "Lines3DChart", + polygons3D: "Polygons3DChart", + surface: "SurfaceChart", + map3D: "Map3DChart", + + scatterGL: "ScatterGLChart", + graphGL: "GraphGLChart", + flowGL: "FlowGLChart", + linesGL: "LinesGLChart" +}; + +const FEATURES = ["UniversalTransition", "LabelLayout"]; +const RENDERERS_MAP = { + canvas: "CanvasRenderer", + svg: "SVGRenderer" +}; + +const EXTENSIONS_MAP = { + bmap: "bmap/bmap" + // PENDING: There seem no examples that use dataTool + // dataTool: 'dataTool' +}; + +// Component that will be injected automatically in preprocessor +// These should be excluded util find they were used explicitly. +const MARKERS = ["markLine", "markArea", "markPoint"]; +const INJECTED_COMPONENTS = [ + ...MARKERS, + "grid", + "axisPointer", + "aria" // TODO aria +]; + +// Component that was dependent. +const DEPENDENT_COMPONENTS = [ + "xAxis", + "yAxis", + "angleAxis", + "radiusAxis", + "xAxis3D", + "yAxis3D", + "zAxis3D" +]; + +function createReverseMap(map) { + const reverseMap = {}; + Object.keys(map).forEach(key => { + // Exclude dependencies. + if (DEPENDENT_COMPONENTS.includes(key)) { + return; + } + reverseMap[map[key]] = key; + }); + + return reverseMap; +} + +const COMPONENTS_MAP_REVERSE = createReverseMap(COMPONENTS_MAP); +const CHARTS_MAP_REVERSE = createReverseMap(CHARTS_MAP); +const COMPONENTS_GL_MAP_REVERSE = createReverseMap(COMPONENTS_GL_MAP); +const CHARTS_GL_MAP_REVERSE = createReverseMap(CHARTS_GL_MAP); + +function collectDeps(option) { + let deps = []; + if (option.options) { + // TODO getOption() doesn't have baseOption and options. + option.options.forEach(opt => { + deps = deps.concat(collectDeps(opt)); + }); + + if (option.baseOption) { + deps = deps.concat(collectDeps(option.baseOption)); + } + + // Remove duplicates + return Array.from(new Set(deps)); + } + + Object.keys(option).forEach(key => { + if (INJECTED_COMPONENTS.includes(key)) { + return; + } + const val = option[key]; + + if (Array.isArray(val) && !val.length) { + return; + } + + if (COMPONENTS_MAP[key]) { + deps.push(COMPONENTS_MAP[key]); + } + if (COMPONENTS_GL_MAP[key]) { + deps.push(COMPONENTS_GL_MAP[key]); + } + if (EXTENSIONS_MAP[key]) { + deps.push(key); + } + }); + + let series = option.series; + if (!Array.isArray(series)) { + series = [series]; + } + + series.forEach(seriesOpt => { + if (CHARTS_MAP[seriesOpt.type]) { + deps.push(CHARTS_MAP[seriesOpt.type]); + } + if (CHARTS_GL_MAP[seriesOpt.type]) { + deps.push(CHARTS_GL_MAP[seriesOpt.type]); + } + if (seriesOpt.type === "map") { + // Needs geo component when using map + deps.push(COMPONENTS_MAP.geo); + } + if (seriesOpt.coordinateSystem === "bmap") { + deps.push("bmap"); + } + MARKERS.forEach(markerType => { + if (seriesOpt[markerType]) { + deps.push(COMPONENTS_MAP[markerType]); + } + }); + // Features + if (seriesOpt.labelLayout) { + deps.push("LabelLayout"); + } + if (seriesOpt.universalTransition) { + deps.push("UniversalTransition"); + } + }); + // Dataset transform + if (option.dataset && Array.isArray(option.dataset)) { + option.dataset.forEach(dataset => { + if (dataset.transform) { + deps.push("TransformComponent"); + } + }); + } + + // Remove duplicates + return Array.from(new Set(deps)); +} + +function buildMinimalBundleCode( + deps, + { + includeType, + semi = false, + quote = "'", + multiline = false, + indent = " ", + maxLen = 80 + } +) { + const options = { + semi, + quote, + multiline, + indent, + maxLen + }; + + const chartsImports = []; + const componentsImports = []; + const chartsGLImports = []; + const componentsGLImports = []; + const featuresImports = []; + const renderersImports = []; + const extensionImports = []; + + deps.forEach(dep => { + if (dep.endsWith("Renderer")) { + renderersImports.push(dep); + } else if (CHARTS_MAP_REVERSE[dep]) { + chartsImports.push(dep); + if (includeType) { + chartsImports.push(dep.replace(/Chart$/, "SeriesOption")); + } + } else if (COMPONENTS_MAP_REVERSE[dep]) { + componentsImports.push(dep); + if (includeType) { + componentsImports.push(dep.replace(/Component$/, "ComponentOption")); + } + } else if (dep === "TransformComponent") { + // TransformComponent don't have individual option type. + // TODO will put in to an config if there are other similar components + componentsImports.push(dep); + } else if (CHARTS_GL_MAP_REVERSE[dep]) { + chartsGLImports.push(dep); + } else if (COMPONENTS_GL_MAP_REVERSE[dep]) { + componentsGLImports.push(dep); + } else if (FEATURES.includes(dep)) { + featuresImports.push(dep); + } else if (EXTENSIONS_MAP[dep]) { + extensionImports.push(dep); + } + }); + + const allImports = [ + ...componentsImports, + ...chartsImports, + ...componentsGLImports, + ...chartsGLImports, + ...renderersImports, + ...featuresImports + ]; + + const ECOptionTypeCode = typeItems( + allImports.filter(a => a.endsWith("Option")), + options + ); + + const importSources = [ + [chartsImports, "echarts/charts"], + [componentsImports, "echarts/components"], + [featuresImports, "echarts/features"], + [renderersImports, "echarts/renderers"], + [chartsGLImports, "echarts-gl/charts"], + [componentsGLImports, "echarts-gl/components"] + ].filter(a => a[0].length > 0); + const importStatements = importSources.map(([imports, mod]) => + importItems( + imports.filter(a => !a.endsWith("Option")), + mod, + options + ) + ); + + const semiStr = semi ? ";" : ""; + + getExtensionDeps(extensionImports, includeType).forEach(ext => { + importStatements.push(`import ${quote}${ext}${quote}${semiStr}`); + }); + + if (includeType) { + importStatements.push( + `import type { ComposeOption } from ${quote}echarts/core${quote}${semiStr}` + ); + const importTypeStatements = importSources.map(([imports, mod]) => + importItems( + imports.filter(a => a.endsWith("Option")), + mod, + { ...options, type: true } + ) + ); + importStatements.push(...importTypeStatements); + } + + return `import { use } from ${quote}echarts/core${quote}${semiStr} +${importStatements.join("\n")} + +${useItems( + allImports.filter(a => !a.endsWith("Option")), + options +)} +${includeType ? `\n${ECOptionTypeCode}` : ""} +`; +} +function getExtensionDeps(deps, ts) { + return deps + .filter(dep => EXTENSIONS_MAP[dep]) + .map(dep => `echarts/extension${ts ? "-src" : ""}/${EXTENSIONS_MAP[dep]}`); +} + +/** import */ +function importItems(items, module, options) { + if (items.length === 0) { + return ""; + } + + const { multiline, maxLen } = options; + + if (multiline) { + return importMultiLine(items, module, options); + } + + const singleLine = importSingleLine(items, module, options); + if (singleLine.length <= maxLen) { + return singleLine; + } + + return importMultiLine(items, module, options); +} + +// import { foo, bar } from 'module' +function importSingleLine(items, module, { type, semi, quote }) { + const typeStr = type ? "type " : ""; + const semiStr = semi ? ";" : ""; + + return `import ${typeStr}{ ${items.join( + ", " + )} } from ${quote}${module}${quote}${semiStr}`; +} + +// import { +// foo, +// bar +// } from 'module' +function importMultiLine(items, module, { type, indent, semi, quote }) { + const typeStr = type ? "type " : ""; + const semiStr = semi ? ";" : ""; + + return `import ${typeStr}{ +${items.map(item => `${indent}${item}`).join(",\n")} +} from ${quote}${module}${quote}${semiStr}`; +} + +/** use */ +function useItems(items, options) { + if (items.length === 0) { + return ""; + } + + const { multiline, maxLen } = options; + + if (multiline) { + return useMultiLine(items, options); + } + + const singleLine = useSingleLine(items, options); + if (singleLine.length <= maxLen) { + return singleLine; + } + + return useMultiLine(items, options); +} + +// use([foo, bar]) +function useSingleLine(items, { semi }) { + const semiStr = semi ? ";" : ""; + + return `use([${items.join(`, `)}])${semiStr}`; +} + +// use([ +// foo, +// bar +// ]) +function useMultiLine(items, { indent, semi }) { + const semiStr = semi ? ";" : ""; + + return `use([ +${items.map(item => `${indent}${item}`).join(`,\n`)} +])${semiStr}`; +} + +/** type */ +function typeItems(items, options) { + const { multiline, maxLen } = options; + + if (items.length === 0) { + return ""; + } + + if (multiline) { + return typeMultiLine(items, options); + } + + const singleLine = typeSingleLine(items, options); + if (singleLine.length <= maxLen) { + return singleLine; + } + + return typeMultiLine(items, options); +} + +// type EChartsOption = ComposeOption +function typeSingleLine(items, { semi }) { + const semiStr = semi ? ";" : ""; + + return `type EChartsOption = ComposeOption<${items.join(` | `)}>${semiStr}`; +} + +// type EChartsOption = ComposeOption< +// | FooOption +// | BarOption +// > +function typeMultiLine(items, { indent, semi }) { + const semiStr = semi ? ";" : ""; + + return `type EChartsOption = ComposeOption< +${items.map(item => `${indent}| ${item}`).join("\n")} +>${semiStr}`; +} + +export function getImportsFromOption( + option, + { renderer = "canvas", ...options } +) { + return buildMinimalBundleCode( + [...collectDeps(option), RENDERERS_MAP[renderer]], + options + ); +}