├── .editorconfig
├── .eslintignore
├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ ├── config.yml
│ ├── feaure_request.yml
│ └── others.md
├── PULL_REQUEST_TEMPLATE.md
├── PULL_REQUEST_TEMPLATE
│ └── pr_cn.md
├── labeler.yml
└── workflows
│ ├── labeler.yml
│ ├── pr-check.yml
│ ├── pre-release.yml
│ ├── release-changelog.yml
│ ├── release.yml
│ ├── stale.yml
│ ├── sync-main-to-develop.yml
│ └── unit-test.yml
├── .gitignore
├── .lintstagedrc
├── .prettierignore
├── .prettierrc.js
├── .vscode
└── settings.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── CONTRIBUTING.zh-CN.md
├── LICENSE
├── README-ja.md
├── README.md
├── common
├── autoinstallers
│ ├── create
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── pnpm-lock.yaml
│ │ ├── src
│ │ │ ├── cli.ts
│ │ │ ├── create.ts
│ │ │ ├── global.d.ts
│ │ │ ├── logger.ts
│ │ │ └── template.ts
│ │ ├── templates
│ │ │ └── library
│ │ │ │ ├── .eslintrc.js
│ │ │ │ ├── README.md
│ │ │ │ ├── bundler.config.js
│ │ │ │ ├── package.json
│ │ │ │ ├── src
│ │ │ │ ├── global.d.ts
│ │ │ │ └── index.ts
│ │ │ │ ├── tsconfig.json
│ │ │ │ └── vite
│ │ │ │ ├── index.html
│ │ │ │ ├── public
│ │ │ │ └── vite.svg
│ │ │ │ ├── src
│ │ │ │ ├── App.css
│ │ │ │ ├── App.tsx
│ │ │ │ ├── assets
│ │ │ │ │ └── react.svg
│ │ │ │ ├── index.css
│ │ │ │ ├── main.tsx
│ │ │ │ └── vite-env.d.ts
│ │ │ │ ├── tsconfig.json
│ │ │ │ ├── tsconfig.node.json
│ │ │ │ └── vite.config.ts
│ │ └── tsconfig.json
│ ├── lint
│ │ ├── change-all.ts
│ │ ├── commit-lint.js
│ │ ├── commitlint.config.js
│ │ ├── package.json
│ │ ├── pnpm-lock.yaml
│ │ ├── prettier.ts
│ │ └── tsconfig.json
│ └── run-script
│ │ ├── package.json
│ │ ├── pnpm-lock.yaml
│ │ ├── run.ts
│ │ └── tsconfig.json
├── config
│ └── rush
│ │ ├── .npmrc
│ │ ├── .npmrc-publish
│ │ ├── .pnpmfile.cjs
│ │ ├── artifactory.json
│ │ ├── build-cache.json
│ │ ├── command-line.json
│ │ ├── common-versions.json
│ │ ├── experiments.json
│ │ ├── pnpm-config.json
│ │ ├── pnpm-lock.yaml
│ │ ├── repo-state.json
│ │ ├── rush-plugins.json
│ │ └── version-policies.json
├── git-hooks
│ ├── commit-msg
│ ├── pre-commit
│ └── pre-push
├── scripts
│ ├── apply-prerelease-version.js
│ ├── apply-release-version.js
│ ├── get-package-json.js
│ ├── hotfix-release.js
│ ├── install-run-rush-pnpm.js
│ ├── install-run-rush.js
│ ├── install-run-rushx.js
│ ├── install-run.js
│ ├── parse-version.js
│ ├── pre-release.js
│ ├── release.js
│ ├── set-json-file.js
│ ├── set-prerelease-version.js
│ ├── sort_deps.js
│ └── version-policies.js
└── template
│ ├── chart.d.ts
│ ├── chart.js
│ ├── component.d.ts
│ ├── component.js
│ ├── core.d.ts
│ ├── core.js
│ ├── layout.d.ts
│ ├── layout.js
│ ├── mark.d.ts
│ ├── mark.js
│ ├── series.d.ts
│ └── series.js
├── docs
├── assets
│ ├── api
│ │ ├── en
│ │ │ ├── VMind_Instance.md
│ │ │ ├── dataQuery.md
│ │ │ ├── fillSpecWithData.md
│ │ │ ├── generateChart.md
│ │ │ ├── getFieldInfo.md
│ │ │ ├── getInsights.md
│ │ │ ├── parseCSVData.md
│ │ │ └── text2Chart.md
│ │ ├── menu.json
│ │ └── zh
│ │ │ ├── VMind_Instance.md
│ │ │ ├── dataQuery.md
│ │ │ ├── fillSpecWithData.md
│ │ │ ├── generateChart.md
│ │ │ ├── getFieldInfo.md
│ │ │ ├── getInsights.md
│ │ │ ├── parseCSVData.md
│ │ │ └── text2Chart.md
│ ├── changelog
│ │ ├── en
│ │ │ └── release.md
│ │ └── zh
│ │ │ └── release.md
│ ├── guide
│ │ ├── en
│ │ │ ├── Basic_Tutorial
│ │ │ │ ├── Chart_Advisor.md
│ │ │ │ ├── Chart_Generation.md
│ │ │ │ ├── Chart_Insight.md
│ │ │ │ ├── Create_VMind_Instance.md
│ │ │ │ ├── Data_Aggregation.md
│ │ │ │ ├── Data_Extraction.md
│ │ │ │ ├── Data_Process.md
│ │ │ │ ├── How_to_Get_VMind.md
│ │ │ │ └── How_to_Import_VMind.md
│ │ │ ├── Contribution_Guide.md
│ │ │ ├── Getting_Started
│ │ │ │ ├── Getting_Started.md
│ │ │ │ └── Quickly_Get_Started_with_VisActor_Using_Trae_Context_Doc.md
│ │ │ ├── Intro_to_VMind.md
│ │ │ └── VMind_Website_Guide.md
│ │ ├── menu.json
│ │ └── zh
│ │ │ ├── Basic_Tutorial
│ │ │ ├── Chart_Advisor.md
│ │ │ ├── Chart_Generation.md
│ │ │ ├── Chart_Insight.md
│ │ │ ├── Create_VMind_Instance.md
│ │ │ ├── Data_Aggregation.md
│ │ │ ├── Data_Extraction.md
│ │ │ ├── Data_Process.md
│ │ │ ├── How_to_Get_VMind.md
│ │ │ └── How_to_Import_VMind.md
│ │ │ ├── Contribution_Guide.md
│ │ │ ├── Getting_Started
│ │ │ ├── Getting_Started.md
│ │ │ └── Quickly_Get_Started_with_VisActor_Using_Trae_Context_Doc.md
│ │ │ ├── Intro_to_VMind.md
│ │ │ └── VMind_Website_Guide.md
│ ├── openManus
│ │ ├── Amazon_Fashion_Sales_Analysis_Report.md
│ │ ├── Readme.md
│ │ ├── amazon_sales_jan2025.csv
│ │ ├── aov_trend.png
│ │ ├── correlation_heatmap.png
│ │ ├── daily_sales_trend.png
│ │ ├── home
│ │ │ └── ubuntu
│ │ │ │ ├── analysis
│ │ │ │ ├── data_exploration.txt
│ │ │ │ ├── preprocessing_results.txt
│ │ │ │ └── sales_analysis_results.txt
│ │ │ │ └── todo.md
│ │ ├── key_insights.md
│ │ ├── orders_by_day.png
│ │ ├── outlier_comparison.png
│ │ ├── profit_margin_by_discount.png
│ │ ├── sales_by_day.png
│ │ ├── sales_growth_strategies.md
│ │ ├── weekend_comparison.png
│ │ └── weekly_sales.png
│ └── scenario
│ │ ├── en
│ │ ├── Chart_Assistant.md
│ │ ├── Data_Development.md
│ │ ├── Data_Video.md
│ │ ├── Document_Assistant.md
│ │ ├── OpenManus_VMind.md
│ │ ├── Open_API.md
│ │ └── Wordcloud_Cube.md
│ │ ├── menu.json
│ │ └── zh
│ │ ├── Chart_Assistant.md
│ │ ├── Data_Development.md
│ │ ├── Data_Video.md
│ │ ├── Document_Assistant.md
│ │ ├── OpenManus_VMind.md
│ │ ├── Open_API.md
│ │ └── Wordcloud_Cube.md
├── index.html
├── index.js
├── libs
│ └── template-parse
│ │ ├── build.js
│ │ ├── etpl.js
│ │ ├── md2json.js
│ │ └── schemaHelper.js
├── menu.json
├── package.json
├── src
│ ├── app.tsx
│ ├── header.tsx
│ ├── i18n.tsx
│ ├── main.tsx
│ ├── markdown.tsx
│ ├── option.tsx
│ └── option
│ │ ├── description.tsx
│ │ ├── index.css
│ │ ├── index.tsx
│ │ └── outline.tsx
├── style.css
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.js
├── option
├── packages
├── calculator
│ ├── LICENSE
│ ├── README.md
│ ├── jest.config.js
│ ├── package.json
│ ├── src
│ │ ├── astParser
│ │ │ ├── astPipes.ts
│ │ │ ├── index.ts
│ │ │ ├── parseSqlAST.ts
│ │ │ ├── type.ts
│ │ │ └── utils.ts
│ │ ├── index.ts
│ │ ├── join.test.ts
│ │ ├── join.ts
│ │ ├── mocks
│ │ │ ├── index.ts
│ │ │ └── table.ts
│ │ ├── pipe.ts
│ │ ├── pipes
│ │ │ ├── aggregate
│ │ │ │ ├── aggregate.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── methods.ts
│ │ │ ├── distinct.test.ts
│ │ │ ├── distinct.ts
│ │ │ ├── filter
│ │ │ │ ├── filter.ts
│ │ │ │ ├── having.test.ts
│ │ │ │ ├── having.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── where.test.ts
│ │ │ │ └── where.ts
│ │ │ ├── group.test.ts
│ │ │ ├── group.ts
│ │ │ ├── index.ts
│ │ │ ├── limit.ts
│ │ │ ├── order.test.ts
│ │ │ ├── order.ts
│ │ │ ├── select.test.ts
│ │ │ └── select.ts
│ │ ├── query.test.ts
│ │ ├── query.ts
│ │ ├── types
│ │ │ ├── aggregate.ts
│ │ │ ├── data.ts
│ │ │ ├── filter.ts
│ │ │ ├── group.ts
│ │ │ ├── index.ts
│ │ │ ├── join.ts
│ │ │ ├── query.ts
│ │ │ └── select.ts
│ │ └── utils
│ │ │ ├── includes.ts
│ │ │ ├── index.ts
│ │ │ ├── ordered.ts
│ │ │ └── typeCheck.ts
│ ├── tsconfig.cjs.json
│ ├── tsconfig.esm.json
│ ├── tsconfig.json
│ └── tsconfig.test.json
├── chart-advisor
│ ├── .eslintrc.cjs
│ ├── LICENSE
│ ├── README.md
│ ├── __tests__
│ │ ├── Q1.test.ts
│ │ ├── base.test.ts
│ │ ├── score.test.ts
│ │ └── tsconfig.json
│ ├── exampleChart.png
│ ├── jest.config.js
│ ├── package.json
│ ├── src
│ │ ├── constant.ts
│ │ ├── dataUtil.ts
│ │ ├── fieldAssign.ts
│ │ ├── fieldUtils.ts
│ │ ├── index.ts
│ │ ├── pivot.ts
│ │ ├── score.ts
│ │ └── type.ts
│ ├── tsconfig.cjs.json
│ ├── tsconfig.eslint.json
│ ├── tsconfig.esm.json
│ ├── tsconfig.json
│ └── tsconfig.test.json
└── vmind
│ ├── .eslintrc.cjs
│ ├── CHANGELOG.json
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── __tests__
│ ├── browser
│ │ ├── index.html
│ │ ├── src
│ │ │ ├── App.tsx
│ │ │ ├── Layout.tsx
│ │ │ ├── constants
│ │ │ │ ├── capcutData.ts
│ │ │ │ ├── chartGeneratorData.ts
│ │ │ │ ├── mockData.ts
│ │ │ │ └── mockResponse.ts
│ │ │ ├── index.scss
│ │ │ ├── index.tsx
│ │ │ └── pages
│ │ │ │ ├── ChartGeneration
│ │ │ │ ├── ChartGeneration.tsx
│ │ │ │ ├── ChartPreview.tsx
│ │ │ │ └── DataInput.tsx
│ │ │ │ ├── DataExtraction
│ │ │ │ ├── DataExtractionPage.tsx
│ │ │ │ ├── DataInput.tsx
│ │ │ │ └── DataTable.tsx
│ │ │ │ ├── Home.tsx
│ │ │ │ ├── Insight
│ │ │ │ ├── ChartPreview.tsx
│ │ │ │ ├── DataInput.tsx
│ │ │ │ ├── Insight.tsx
│ │ │ │ └── data
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── insightData.ts
│ │ │ │ ├── NewChartGeneration
│ │ │ │ ├── ChartGeneration.tsx
│ │ │ │ ├── ChartPreview.tsx
│ │ │ │ └── DataInput.tsx
│ │ │ │ ├── NewDataExtraction
│ │ │ │ ├── DataInput.tsx
│ │ │ │ ├── DataTable.tsx
│ │ │ │ └── index.tsx
│ │ │ │ ├── Text2Chart
│ │ │ │ ├── ChartPreview.tsx
│ │ │ │ ├── DataInput.tsx
│ │ │ │ └── TextToChart.tsx
│ │ │ │ ├── constants.tsx
│ │ │ │ └── index.scss
│ │ ├── tsconfig.json
│ │ ├── tsconfig.node.json
│ │ └── vite.config.ts
│ ├── experiment
│ │ ├── index.html
│ │ ├── src
│ │ │ ├── App.tsx
│ │ │ ├── Layout.tsx
│ │ │ ├── data
│ │ │ │ ├── capcutDataCn.ts
│ │ │ │ ├── capcutDataEn.ts
│ │ │ │ ├── capcutV2Data.ts
│ │ │ │ ├── dataExtractionData.ts
│ │ │ │ ├── editorData.ts
│ │ │ │ ├── qaData.ts
│ │ │ │ └── topKeyQA.ts
│ │ │ ├── index.scss
│ │ │ ├── index.tsx
│ │ │ ├── pages
│ │ │ │ ├── ChartDialogueQA
│ │ │ │ │ ├── color.scss
│ │ │ │ │ ├── const.ts
│ │ │ │ │ ├── logo.tsx
│ │ │ │ │ ├── qaPairRag.tsx
│ │ │ │ │ ├── rag.scss
│ │ │ │ │ ├── specEditor.tsx
│ │ │ │ │ └── test.tsx
│ │ │ │ ├── ChartGenerator
│ │ │ │ │ ├── caseStudy.tsx
│ │ │ │ │ ├── test.tsx
│ │ │ │ │ └── type.tsx
│ │ │ │ ├── DataExtraction
│ │ │ │ │ ├── caseStudy.tsx
│ │ │ │ │ ├── test.tsx
│ │ │ │ │ ├── type.tsx
│ │ │ │ │ └── verify.tsx
│ │ │ │ ├── Home.tsx
│ │ │ │ ├── constants.tsx
│ │ │ │ └── page.scss
│ │ │ └── utils.ts
│ │ ├── tsconfig.json
│ │ ├── tsconfig.node.json
│ │ └── vite.config.ts
│ ├── image-to-spec
│ │ ├── spec
│ │ │ ├── area-basis.ts
│ │ │ ├── area-percent.ts
│ │ │ ├── bar-basic.ts
│ │ │ ├── bar-bi-direction.ts
│ │ │ ├── bar-colorful.ts
│ │ │ ├── bar-gradient.ts
│ │ │ ├── bar-group.ts
│ │ │ ├── bar-h-group.ts
│ │ │ ├── bar-h-stack.ts
│ │ │ ├── bar-horizontal.ts
│ │ │ ├── bar-percent.ts
│ │ │ ├── bar-stack.ts
│ │ │ ├── bar-tgi.ts
│ │ │ ├── bar-two-directions.ts
│ │ │ ├── circle-packing-bubble.ts
│ │ │ ├── circle-packing-simple.ts
│ │ │ ├── circular-progress.ts
│ │ │ ├── dual-axis.ts
│ │ │ ├── funnel-basic.ts
│ │ │ ├── funnel-comparative.ts
│ │ │ ├── funnel-rect.ts
│ │ │ ├── funnel-transform.ts
│ │ │ ├── gauge-basic.ts
│ │ │ ├── gauge-segment.ts
│ │ │ ├── heatmap-basic.ts
│ │ │ ├── histogram-basic.ts
│ │ │ ├── histogram-different-bin.ts
│ │ │ ├── index.ts
│ │ │ ├── line-bar.ts
│ │ │ ├── line-basic.ts
│ │ │ ├── line-mark-area.ts
│ │ │ ├── line-markline.ts
│ │ │ ├── line-multi-markline.ts
│ │ │ ├── line-stack.ts
│ │ │ ├── linear-grogress-segment.ts
│ │ │ ├── linear-progress.ts
│ │ │ ├── liquid-basic.ts
│ │ │ ├── liquid-star.ts
│ │ │ ├── pie-basic.ts
│ │ │ ├── pie-donut.ts
│ │ │ ├── pie-nested.ts
│ │ │ ├── radar-basic.ts
│ │ │ ├── radar-group.ts
│ │ │ ├── radar-innerradius.ts
│ │ │ ├── radar-stack.ts
│ │ │ ├── range-bar.ts
│ │ │ ├── range-column.ts
│ │ │ ├── rose-basis.ts
│ │ │ ├── rose-group-stack.ts
│ │ │ ├── rose-group.ts
│ │ │ ├── rose-stack.ts
│ │ │ ├── sankey-simple.ts
│ │ │ ├── scatter-basic.ts
│ │ │ ├── scatter-bubble.ts
│ │ │ ├── scatter-markline.ts
│ │ │ ├── sunburst-basic.ts
│ │ │ ├── treemap.ts
│ │ │ ├── venn-hollow.ts
│ │ │ ├── venn-three.ts
│ │ │ ├── waterfall-collect.ts
│ │ │ ├── waterfall-h.ts
│ │ │ ├── waterfall-stack.ts
│ │ │ ├── waterfall.ts
│ │ │ └── wordcloud-basic.ts
│ │ └── testImage.ts
│ ├── performance
│ │ ├── output.json
│ │ └── performance.test.ts
│ ├── tsconfig.json
│ └── unit
│ │ ├── chartGenerator
│ │ ├── chartTypeUtils.test.ts
│ │ ├── checkChartTypeAndCell.test.ts
│ │ └── simpleSpec.test.ts
│ │ ├── index.test.ts
│ │ ├── specInsights
│ │ ├── dual-axis.test.ts
│ │ ├── growth-markline.test.ts
│ │ └── stacked-bar.test.ts
│ │ ├── utils
│ │ ├── date.test.ts
│ │ ├── delete.test.ts
│ │ └── set.test.ts
│ │ └── vchartSpec
│ │ ├── bar.test.ts
│ │ ├── commonChart.test.ts
│ │ ├── components
│ │ └── markLine.test.ts
│ │ ├── stack-bar.test.ts
│ │ └── util.test.ts
│ ├── bundler.config.js
│ ├── jest.config.js
│ ├── jest.performance.config.js
│ ├── package.json
│ ├── readme-zh.md
│ ├── src
│ ├── applications
│ │ ├── chartGeneration
│ │ │ └── index.ts
│ │ ├── dataAggregation
│ │ │ └── index.ts
│ │ ├── dataExtraction
│ │ │ └── index.ts
│ │ ├── dataInsight
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ └── utils.ts
│ ├── atom
│ │ ├── VChartSpec
│ │ │ ├── index.ts
│ │ │ └── utils.ts
│ │ ├── base.ts
│ │ ├── chartCommand
│ │ │ ├── index.ts
│ │ │ ├── multiple.ts
│ │ │ └── prompt.ts
│ │ ├── chartGenerator
│ │ │ ├── advisor
│ │ │ │ └── index.ts
│ │ │ ├── const.ts
│ │ │ ├── index.ts
│ │ │ ├── llmResultRevise.ts
│ │ │ ├── prompt
│ │ │ │ ├── examples.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── knowledges.ts
│ │ │ ├── rule
│ │ │ │ └── index.ts
│ │ │ ├── spec
│ │ │ │ ├── chartTypeUtils.ts
│ │ │ │ ├── constants.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── transformers
│ │ │ │ │ ├── bar.ts
│ │ │ │ │ ├── boxplot.ts
│ │ │ │ │ ├── cartesian.ts
│ │ │ │ │ ├── circlePacking.ts
│ │ │ │ │ ├── circularProgress.ts
│ │ │ │ │ ├── common.ts
│ │ │ │ │ ├── dualAxis.ts
│ │ │ │ │ ├── funnel.ts
│ │ │ │ │ ├── gauge.ts
│ │ │ │ │ ├── heatmap.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── line.ts
│ │ │ │ │ ├── linearProgress.ts
│ │ │ │ │ ├── liquid.ts
│ │ │ │ │ ├── map.ts
│ │ │ │ │ ├── pie.ts
│ │ │ │ │ ├── polar.ts
│ │ │ │ │ ├── radar.ts
│ │ │ │ │ ├── rangeColumn.ts
│ │ │ │ │ ├── rankingBar.ts
│ │ │ │ │ ├── rose.ts
│ │ │ │ │ ├── sankey.ts
│ │ │ │ │ ├── scatter.ts
│ │ │ │ │ ├── simpleSpec.ts
│ │ │ │ │ ├── sunburst.ts
│ │ │ │ │ ├── treemap.ts
│ │ │ │ │ ├── venn.ts
│ │ │ │ │ ├── waterfall.ts
│ │ │ │ │ └── wordcloud.ts
│ │ │ ├── type.ts
│ │ │ └── utils.ts
│ │ ├── chartQAExtraction
│ │ │ ├── index.ts
│ │ │ └── prompt.ts
│ │ ├── customAtom
│ │ │ └── index.ts
│ │ ├── dataClean
│ │ │ ├── dataClean.ts
│ │ │ ├── index.ts
│ │ │ ├── multiple.ts
│ │ │ └── utils.ts
│ │ ├── dataExtraction
│ │ │ ├── index.ts
│ │ │ └── prompt
│ │ │ │ ├── capcutPrompt.ts
│ │ │ │ ├── doubaoPrompt.ts
│ │ │ │ ├── gptPrompt.ts
│ │ │ │ └── prompt.ts
│ │ ├── dataInsight
│ │ │ ├── algorithms
│ │ │ │ ├── abnormalTrend
│ │ │ │ │ └── index.ts
│ │ │ │ ├── base
│ │ │ │ │ └── baseStatistics.ts
│ │ │ │ ├── correlation
│ │ │ │ │ ├── pearson.ts
│ │ │ │ │ └── spearman.ts
│ │ │ │ ├── drift
│ │ │ │ │ ├── adwin.ts
│ │ │ │ │ ├── bucket.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── pageHinkley.ts
│ │ │ │ ├── extremeValue
│ │ │ │ │ └── index.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── majorityValue
│ │ │ │ │ └── index.ts
│ │ │ │ ├── outlier
│ │ │ │ │ ├── dbscan.ts
│ │ │ │ │ ├── difference.ts
│ │ │ │ │ ├── lof.ts
│ │ │ │ │ └── statistics.ts
│ │ │ │ ├── overallTrending
│ │ │ │ │ └── index.ts
│ │ │ │ ├── revised.ts
│ │ │ │ ├── statistics.ts
│ │ │ │ ├── template.ts
│ │ │ │ ├── turningPoint
│ │ │ │ │ └── index.ts
│ │ │ │ └── volatility
│ │ │ │ │ └── index.ts
│ │ │ ├── const.ts
│ │ │ ├── dataProcess.ts
│ │ │ ├── index.ts
│ │ │ ├── prompt.ts
│ │ │ ├── type.ts
│ │ │ └── utils.ts
│ │ ├── dataQuery
│ │ │ ├── const.ts
│ │ │ ├── executeQuery.ts
│ │ │ ├── index.ts
│ │ │ ├── prompt.ts
│ │ │ └── utils.ts
│ │ ├── imageReader
│ │ │ ├── index.ts
│ │ │ ├── interface.ts
│ │ │ └── prompt.ts
│ │ ├── index.ts
│ │ └── specInsight
│ │ │ └── index.ts
│ ├── core
│ │ ├── VMind.ts
│ │ ├── factory.ts
│ │ ├── llm.ts
│ │ ├── memory.ts
│ │ └── rag.ts
│ ├── index.ts
│ ├── schedule
│ │ └── index.ts
│ ├── types
│ │ ├── atom.ts
│ │ ├── base.ts
│ │ ├── chart.ts
│ │ ├── index.ts
│ │ ├── llm.ts
│ │ ├── rag.ts
│ │ ├── schedule.ts
│ │ └── utils.ts
│ └── utils
│ │ ├── cluster.ts
│ │ ├── common.ts
│ │ ├── dataTable.ts
│ │ ├── field.ts
│ │ ├── json.ts
│ │ ├── llm.ts
│ │ ├── set.ts
│ │ ├── spec.ts
│ │ ├── text.ts
│ │ ├── unfold.ts
│ │ └── video.ts
│ ├── test-setup.js
│ ├── tsconfig.eslint.json
│ ├── tsconfig.json
│ ├── tsconfig.test.json
│ └── types
│ └── jstat.d.ts
├── readme-zh.md
├── rush.json
├── share
├── eslint-config
│ ├── package.json
│ └── profile
│ │ ├── common.js
│ │ ├── lib.js
│ │ └── react.js
├── jest-config
│ ├── jest.base.js
│ └── package.json
└── ts-config
│ ├── package.json
│ └── tsconfig.base.json
└── tools
├── bundler
├── .eslintrc.js
├── README.md
├── bin
│ └── index.js
├── fixtures
│ └── config
│ │ ├── .gitignore
│ │ ├── bundler.config.js
│ │ ├── package.json
│ │ ├── source
│ │ ├── custom.css
│ │ ├── foo
│ │ │ ├── bar
│ │ │ │ ├── index.ts
│ │ │ │ └── web.png
│ │ │ └── index.ts
│ │ ├── global.d.ts
│ │ ├── index.ts
│ │ └── utils
│ │ │ └── index.ts
│ │ └── tsconfig.json
├── package.json
├── src
│ ├── bootstrap.ts
│ ├── global.d.ts
│ ├── index.ts
│ ├── logic
│ │ ├── alias.ts
│ │ ├── babel.config.ts
│ │ ├── config.test.ts
│ │ ├── config.ts
│ │ ├── debug.ts
│ │ ├── package.ts
│ │ └── rollup.config.ts
│ └── tasks
│ │ ├── clean.ts
│ │ ├── copy.ts
│ │ ├── modules.ts
│ │ ├── style.ts
│ │ └── umd.ts
├── tsconfig.json
└── vitest.config.ts
└── typescript-json-schema
├── README.md
├── bin
└── typescript-json-schema
├── package.json
├── tsconfig.json
├── typescript-json-schema-cli.ts
├── typescript-json-schema.ts
└── vchart.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | tools/typescript-json-schema
2 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Don't allow people to merge changes to these generated files, because the result
2 | # may be invalid. You need to run "rush update" again.
3 | pnpm-lock.yaml merge=text
4 | shrinkwrap.yaml merge=binary
5 | npm-shrinkwrap.json merge=binary
6 | yarn.lock merge=binary
7 |
8 | # Rush's JSON config files use JavaScript-style code comments. The rule below prevents pedantic
9 | # syntax highlighters such as GitHub's from highlighting these comments as errors. Your text editor
10 | # may also require a special configuration to allow comments in JSON.
11 | #
12 | # For more information, see this issue: https://github.com/microsoft/rushstack/issues/1088
13 | #
14 | *.json linguist-language=JSON-with-Comments
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | # contact_links:
3 | # - name: @VisaActor/VChart
4 | # url: https://www.visactor.io/
5 | # about: Please search question here before opening a new issue
6 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/others.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Others
3 | about: Describe this issue's purpose here.
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 | ---
8 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE/pr_cn.md:
--------------------------------------------------------------------------------
1 |
8 |
9 | ### 🤔 这个分支是...
10 |
11 | - [ ] 新功能
12 | - [ ] Bug fix
13 | - [ ] Ts 类型更新
14 | - [ ] 打包优化
15 | - [ ] 性能优化
16 | - [ ] 功能增强
17 | - [ ] 重构
18 | - [ ] 依赖版本更新
19 | - [ ] 代码优化
20 | - [ ] 测试 case 更新
21 | - [ ] 分支合并
22 | - [ ] 发布
23 | - [ ] 网站/文档更新
24 | - [ ] demo 更新
25 | - [ ] Workflow
26 | - [ ] 其他 (具体是什么,请补充?)
27 |
28 | ### 🔗 相关 issue 链接
29 |
30 |
34 |
35 | ### 🔗 相关的 PR 链接
36 |
37 |
38 |
39 | ### 🐞 Bugserver 用例 id
40 |
41 |
42 |
43 | ### 💡 问题的背景&解决方案
44 |
45 |
50 |
51 | ### 📝 Changelog
52 |
53 |
56 |
57 | | Language | Changelog |
58 | | ---------- | --------- |
59 | | 🇺🇸 English | |
60 | | 🇨🇳 Chinese | |
61 |
62 | ### ☑️ 自测
63 |
64 | ⚠️ 在提交 PR 之前,请检查一下内容. ⚠️
65 |
66 | - [ ] 文档提供了,或者更新,或者不需要
67 | - [ ] Demo 提供了,或者更新,或者不需要
68 | - [ ] Ts 类型定义提供了,或者更新,或者不需要
69 | - [ ] Changelog 提供了,或者不需要
70 |
71 | ---
72 |
73 |
77 |
78 | ### 🚀 Summary
79 |
80 | copilot:summary
81 |
82 | ### 🔍 Walkthrough
83 |
84 | copilot:walkthrough
85 |
--------------------------------------------------------------------------------
/.github/labeler.yml:
--------------------------------------------------------------------------------
1 | # Add 'vmind' label to any change within the 'vmind' package
2 | vmind:
3 | - packages/vmind/**
4 |
5 |
6 | # Add 'calculator' label to any change within the 'calculator' package
7 | calculator:
8 | - packages/calculator/**
9 |
10 |
11 | # Add 'chart-advisor' label to any change within the 'calculator' package
12 | chart-advisor:
13 | - packages/chart-advisor/**
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.github/workflows/labeler.yml:
--------------------------------------------------------------------------------
1 | # This workflow will triage pull requests and apply a label based on the
2 | # paths that are modified in the pull request.
3 | #
4 | # To use this workflow, you will need to set up a .github/labeler.yml
5 | # file with configuration. For more information, see:
6 | # https://github.com/actions/labeler
7 |
8 | name: Labeler
9 | on: [pull_request_target]
10 |
11 | jobs:
12 | label:
13 | runs-on: ubuntu-latest
14 | permissions:
15 | contents: read
16 | pull-requests: write
17 |
18 | steps:
19 | - uses: actions/labeler@v4
20 | with:
21 | repo-token: '${{ secrets.GITHUB_TOKEN }}'
22 |
--------------------------------------------------------------------------------
/.github/workflows/pr-check.yml:
--------------------------------------------------------------------------------
1 | name: Check of pull request
2 |
3 | # 这里业务方根据需求设置
4 | on:
5 | pull_request:
6 | branches: ['develop', 'dev/**']
7 | jobs:
8 | build:
9 | runs-on: ubuntu-latest
10 |
11 | strategy:
12 | matrix:
13 | node-version: [20.x]
14 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
15 |
16 | steps:
17 | - uses: actions/checkout@v3
18 | - name: Use Node.js ${{ matrix.node-version }}
19 | uses: actions/setup-node@v3
20 | with:
21 | node-version: ${{ matrix.node-version }}
22 | cache: 'npm'
23 | cache-dependency-path: './common/config/rush/pnpm-lock.yaml'
24 |
25 | - uses: xile611/pr-type-check@main
26 | with:
27 | pull_request_body: |
28 | ${{ github.event.pull_request.body }}
29 | pull_request_head: ${{ github.event.pull_request.head.ref }}
30 |
--------------------------------------------------------------------------------
/.github/workflows/unit-test.yml:
--------------------------------------------------------------------------------
1 | # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
3 |
4 | name: TEST CI
5 |
6 | on:
7 | push:
8 | branches: ['main', 'develop']
9 | pull_request:
10 | branches: ['main', 'develop', 'dev/**']
11 |
12 | jobs:
13 | build:
14 | runs-on: macOS-13
15 |
16 | strategy:
17 | matrix:
18 | node-version: [18.x]
19 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
20 |
21 | steps:
22 | - uses: actions/checkout@v3
23 | - name: Use Node.js ${{ matrix.node-version }}
24 | uses: actions/setup-node@v3
25 | with:
26 | node-version: ${{ matrix.node-version }}
27 | cache: 'npm'
28 | cache-dependency-path: './common/config/rush/pnpm-lock.yaml'
29 |
30 | # Install rush
31 | - name: Install rush
32 | run: node common/scripts/install-run-rush.js install --bypass-policy
33 |
34 | - name: Test
35 | run: node common/scripts/install-run-rush.js test --only tag:package
36 |
--------------------------------------------------------------------------------
/.lintstagedrc:
--------------------------------------------------------------------------------
1 | {
2 | "{packages,tools}/**/*.{ts,tsx}": ["eslint --color --fix --quiet", "prettier --write --ignore-unknown"]
3 | }
4 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | # https://prettier.io/docs/en/ignore.html
2 | #-------------------------------------------------------------------------------------------------------------------
3 | # Keep this section in sync with .gitignore
4 | #-------------------------------------------------------------------------------------------------------------------
5 |
6 | 👋 (copy + paste your .gitignore file contents here) 👋
7 |
8 | #-------------------------------------------------------------------------------------------------------------------
9 | # Prettier-specific overrides
10 | #-------------------------------------------------------------------------------------------------------------------
11 |
12 | # Rush files
13 | common/changes/
14 | common/scripts/
15 | common/config/
16 | CHANGELOG.*
17 |
18 | # Package manager files
19 | pnpm-lock.yaml
20 | yarn.lock
21 | package-lock.json
22 | shrinkwrap.json
23 |
24 | # Build outputs
25 | dist
26 | lib
27 | **/*.min.js
28 | tools/typescript-json-schema
29 |
30 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | // Documentation for this file: https://prettier.io/en/configuration.html
2 | module.exports = {
3 | "printWidth": 120,
4 | "tabWidth": 2,
5 | "useTabs": false,
6 | "semi": true,
7 | "singleQuote": true,
8 | "quoteProps": "as-needed",
9 | "trailingComma": "none",
10 | "bracketSpacing": true,
11 | "arrowParens": "avoid",
12 | "proseWrap": "preserve",
13 | "htmlWhitespaceSensitivity": "css",
14 | "endOfLine": "lf",
15 | "printWidth": 120
16 | };
17 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | }
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Bytedance, Inc. and its affiliates.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/README.md:
--------------------------------------------------------------------------------
1 | # Create project
2 |
3 | ## Description
4 |
5 | Create a project
6 |
7 | ## Usage
8 |
9 | ```bash
10 | rush create [--name | -n] [packageName]
11 | ```
12 |
13 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "create",
3 | "version": "1.0.0",
4 | "private": true,
5 | "dependencies": {
6 | "@microsoft/rush-lib": "5.94.1",
7 | "chalk": "4.1.2",
8 | "fast-glob": "3.2.11",
9 | "minimist": "1.2.6",
10 | "prettier": "2.7.1",
11 | "prompts": "2.4.2",
12 | "string.prototype.replaceall": "1.0.6",
13 | "ts-node": "^10.9.2",
14 | "zx": "4.2.0"
15 | },
16 | "devDependencies": {
17 | "@types/minimist": "1.2.2",
18 | "@types/node": "*",
19 | "@types/prompts": "2.0.14",
20 | "typescript": "4.9.5"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/src/global.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'string.prototype.replaceall' {
2 | type ReplaceAll = (source: string, sbuStr: RegExp | string, newSubStr: string) => string;
3 |
4 | const replaceAll: ReplaceAll = () => {}
5 |
6 | export default replaceAll
7 | }
8 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/src/logger.ts:
--------------------------------------------------------------------------------
1 | import chalk from 'chalk'
2 |
3 | export const logger = {
4 | info: (...messages: any[]) => console.info(
5 | chalk.greenBright.bold('[rush create]'),
6 | ...messages,
7 | ),
8 |
9 | error: (...messages: any[]) => {
10 | console.error(
11 | chalk.redBright.bold('[rush create][error]'),
12 | ...messages,
13 | )
14 | },
15 | }
16 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/.eslintrc.js:
--------------------------------------------------------------------------------
1 | require('@rushstack/eslint-patch/modern-module-resolution');
2 |
3 | module.exports = {
4 | extends: ['@internal/eslint-config/profile/lib'],
5 | parserOptions: { tsconfigRootDir: __dirname },
6 | // ignorePatterns: [],
7 | };
8 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/README.md:
--------------------------------------------------------------------------------
1 | # @{{scope}}/{{projectName}}
2 |
3 | ## Description
4 |
5 | {{description}}
6 |
7 | ## Usage
8 |
9 | ```typescript
10 | import { xxx } from '@{{scope}}/{{projectName}}';
11 | ```
12 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/bundler.config.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | formats: ["cjs", "es", "umd"],
4 | };
5 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@{{scope}}/{{projectName}}",
3 | "version": "0.0.1",
4 | "description": "{{description}}",
5 | "sideEffects": false,
6 | "main": "cjs/index.js",
7 | "module": "es/index.js",
8 | "types": "es/index.d.ts",
9 | "files": [
10 | "cjs",
11 | "es",
12 | "dist"
13 | ],
14 | "scripts": {
15 | "compile": "tsc --noEmit",
16 | "eslint": "eslint --debug --fix src/",
17 | "build": "bundle",
18 | "dev": "bundle --clean -f es -w",
19 | "start": "vite ./vite",
20 | "prepublishOnly": "npm run build"
21 | },
22 | "dependencies": {},
23 | "devDependencies": {
24 | "@internal/bundler": "workspace:*",
25 | "@internal/eslint-config": "workspace:*",
26 | "@internal/ts-config": "workspace:*",
27 | "@rushstack/eslint-patch": "~1.1.4",
28 | "react": "^18.0.0",
29 | "react-dom": "^18.0.0",
30 | "@types/react": "^18.0.0",
31 | "@types/react-dom": "^18.0.0",
32 | "@vitejs/plugin-react": "3.1.0",
33 | "eslint": "~8.18.0",
34 | "vite": "3.2.6",
35 | "typescript": "4.9.5"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/src/global.d.ts:
--------------------------------------------------------------------------------
1 | declare const __VERSION__: string;
2 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/src/index.ts:
--------------------------------------------------------------------------------
1 | export const version = __VERSION__;
2 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@internal/ts-config/tsconfig.base.json",
3 | "compilerOptions": {
4 | "baseUrl": ".",
5 | "outDir": "output"
6 | },
7 | "include": [
8 | "src"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/vite/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React + TS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/vite/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/vite/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | transition: filter 300ms;
13 | }
14 | .logo:hover {
15 | filter: drop-shadow(0 0 2em #646cffaa);
16 | }
17 | .logo.react:hover {
18 | filter: drop-shadow(0 0 2em #61dafbaa);
19 | }
20 |
21 | @keyframes logo-spin {
22 | from {
23 | transform: rotate(0deg);
24 | }
25 | to {
26 | transform: rotate(360deg);
27 | }
28 | }
29 |
30 | @media (prefers-reduced-motion: no-preference) {
31 | a:nth-of-type(2) .logo {
32 | animation: logo-spin infinite 20s linear;
33 | }
34 | }
35 |
36 | .card {
37 | padding: 2em;
38 | }
39 |
40 | .read-the-docs {
41 | color: #888;
42 | }
43 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/vite/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import reactLogo from './assets/react.svg';
3 | import viteLogo from '/vite.svg';
4 | import './App.css';
5 |
6 | function App() {
7 | const [count, setCount] = useState(0);
8 |
9 | return (
10 | <>
11 |
19 | Vite + React
20 |
21 |
22 |
23 | Edit src/App.tsx
and save to test HMR
24 |
25 |
26 | Click on the Vite and React logos to learn more
27 | >
28 | );
29 | }
30 |
31 | export default App;
32 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/vite/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | -webkit-text-size-adjust: 100%;
15 | }
16 |
17 | a {
18 | font-weight: 500;
19 | color: #646cff;
20 | text-decoration: inherit;
21 | }
22 | a:hover {
23 | color: #535bf2;
24 | }
25 |
26 | body {
27 | margin: 0;
28 | display: flex;
29 | place-items: center;
30 | min-width: 320px;
31 | min-height: 100vh;
32 | }
33 |
34 | h1 {
35 | font-size: 3.2em;
36 | line-height: 1.1;
37 | }
38 |
39 | button {
40 | border-radius: 8px;
41 | border: 1px solid transparent;
42 | padding: 0.6em 1.2em;
43 | font-size: 1em;
44 | font-weight: 500;
45 | font-family: inherit;
46 | background-color: #1a1a1a;
47 | cursor: pointer;
48 | transition: border-color 0.25s;
49 | }
50 | button:hover {
51 | border-color: #646cff;
52 | }
53 | button:focus,
54 | button:focus-visible {
55 | outline: 4px auto -webkit-focus-ring-color;
56 | }
57 |
58 | @media (prefers-color-scheme: light) {
59 | :root {
60 | color: #213547;
61 | background-color: #ffffff;
62 | }
63 | a:hover {
64 | color: #747bff;
65 | }
66 | button {
67 | background-color: #f9f9f9;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/vite/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App.tsx';
4 | import './index.css';
5 |
6 | ReactDOM.render(
7 |
8 |
9 | ,
10 | document.getElementById('root') as HTMLElement
11 | );
12 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/vite/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/vite/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": [
5 | "DOM",
6 | "DOM.Iterable",
7 | "ESNext"
8 | ],
9 | "module": "ESNext",
10 | "skipLibCheck": true,
11 | /* Bundler mode */
12 | "moduleResolution": "bundler",
13 | "allowImportingTsExtensions": true,
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react",
18 | /* Linting */
19 | "strict": true,
20 | "noUnusedLocals": true,
21 | "noUnusedParameters": true,
22 | "noFallthroughCasesInSwitch": true
23 | },
24 | "include": [
25 | "src"
26 | ],
27 | "references": [
28 | {
29 | "path": "./tsconfig.node.json"
30 | }
31 | ]
32 | }
33 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/vite/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true
8 | },
9 | "include": ["vite.config.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/common/autoinstallers/create/templates/library/vite/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react({ jsxRuntime: 'classic' })]
7 | });
8 |
--------------------------------------------------------------------------------
/common/autoinstallers/lint/commit-lint.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const fs = require("fs");
3 | const child_process = require("child_process");
4 |
5 | const gitPath = path.resolve(__dirname, "../../../.git");
6 | const configPath = path.resolve(__dirname, "./commitlint.config.js");
7 | const commitlintBinPath = path.resolve(__dirname, "./node_modules/.bin/commitlint");
8 |
9 | if (!fs.existsSync(gitPath)) {
10 | console.error("no valid .git path");
11 | process.exit(1);
12 | }
13 |
14 | const result = child_process.spawnSync(
15 | "sh",
16 | ["-c", `${commitlintBinPath} --config ${configPath} --cwd ${path.dirname(gitPath)} --edit`],
17 | {
18 | stdio: "inherit",
19 | },
20 | );
21 |
22 | if (result.status !== 0) {
23 | process.exit(1);
24 | }
25 |
--------------------------------------------------------------------------------
/common/autoinstallers/lint/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['@commitlint/config-conventional'],
3 | rules: {
4 | 'not-allowed-chars': [2, 'always'],
5 | 'header-max-length': [0, 'always', 200],
6 | 'header-min-length': [2, 'always', 16],
7 | 'type-enum': [
8 | 2,
9 | 'always',
10 | [
11 | 'build',
12 | 'chore',
13 | 'ci',
14 | 'docs',
15 | 'feat',
16 | 'fix',
17 | 'perf',
18 | 'refactor',
19 | 'revert',
20 | 'style',
21 | 'test',
22 | 'wip',
23 | 'release',
24 | 'demo'
25 | ]
26 | ]
27 | },
28 | plugins: [
29 | {
30 | rules: {
31 | 'not-allowed-chars': params => {
32 | const { raw } = params;
33 | const reg =
34 | /^[a-zA-Z0-9\s`~!@#$%^&*()_\-+=<>?:"{}|,.\/;'\\[\]·~!@#¥%……&*()——\-+={}|《》?:“”【】、;‘',。、]+$/im;
35 |
36 | return [
37 | reg.exec(raw),
38 | 'Your commit message should only contain english characters, numbers, empty space, and special characters.'
39 | ];
40 | }
41 | }
42 | }
43 | ]
44 | };
45 |
--------------------------------------------------------------------------------
/common/autoinstallers/lint/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "lint",
3 | "version": "0.0.1",
4 | "private": true,
5 | "dependencies": {
6 | "@commitlint/cli": "17.0.3",
7 | "@commitlint/config-conventional": "17.0.3",
8 | "@microsoft/rush-lib": "5.94.1",
9 | "commitizen": "4.2.5",
10 | "eslint": "~8.18.0",
11 | "lint-staged": "13.0.3",
12 | "minimist": "1.2.6",
13 | "prettier": "2.7.1",
14 | "ts-node": "^10.9.2",
15 | "chalk": "4.1.2"
16 | },
17 | "devDependencies": {
18 | "@types/minimist": "1.2.2",
19 | "@types/node": "*",
20 | "typescript": "5.0.2"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/common/autoinstallers/lint/prettier.ts:
--------------------------------------------------------------------------------
1 | import minimist, { ParsedArgs } from "minimist";
2 | import { spawnSync } from "child_process";
3 | import { RushConfiguration } from "@microsoft/rush-lib";
4 |
5 | interface PrettierScriptArgv extends ParsedArgs {
6 | dir?: string;
7 | ext?: string;
8 | }
9 |
10 | function run() {
11 | const cwd = process.cwd();
12 | const rushConfiguration = RushConfiguration.loadFromDefaultLocation({ startingFolder: cwd });
13 |
14 | const argv: PrettierScriptArgv = minimist(process.argv.slice(2));
15 | const configFilePath = rushConfiguration.rushJsonFolder + "/.prettierrc.js";
16 | const ignoreFilePath = rushConfiguration.rushJsonFolder + "/.prettierignore";
17 |
18 | let ext = "{ts,tsx,less}";
19 | if (argv.ext) {
20 | const length = argv.ext.split(",").length;
21 | ext = length === 1 ? `${argv.ext}` : `{${argv.ext}}`;
22 | }
23 |
24 | let patterns = `{apps,libs}/**/src/**/**/*.${ext}`;
25 | if (argv.dir) {
26 | patterns = `${argv.dir}/src/**/**/*.${ext}`;
27 | }
28 |
29 | console.log(patterns);
30 |
31 | spawnSync(
32 | "sh",
33 | [
34 | "-c",
35 | `prettier --config ${configFilePath} --ignore-path ${ignoreFilePath} --write ${patterns}`,
36 | ],
37 | {
38 | shell: false,
39 | stdio: [0, 1, 2],
40 | },
41 | );
42 | }
43 |
44 | run();
45 |
--------------------------------------------------------------------------------
/common/autoinstallers/run-script/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "run-script",
3 | "version": "0.0.1",
4 | "private": true,
5 | "dependencies": {
6 | "@microsoft/rush-lib": "5.94.1",
7 | "minimist": "1.2.6",
8 | "ts-node": "^10.9.2"
9 | },
10 | "devDependencies": {
11 | "@types/node": "*",
12 | "@types/minimist": "1.2.2",
13 | "typescript": "5.0.2"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/common/autoinstallers/run-script/run.ts:
--------------------------------------------------------------------------------
1 | import minimist, { ParsedArgs } from "minimist";
2 | import { RushConfiguration } from "@microsoft/rush-lib";
3 | import { spawnSync } from "child_process";
4 |
5 | interface RunScriptArgv extends ParsedArgs {
6 | project?: string;
7 | script?: string;
8 | }
9 |
10 | function run() {
11 | const argv: RunScriptArgv = minimist(process.argv.slice(2));
12 | const projects = RushConfiguration.loadFromDefaultLocation({
13 | startingFolder: process.cwd(),
14 | });
15 |
16 | const targetProject = projects.findProjectByShorthandName(argv.project!);
17 |
18 | if (targetProject) {
19 | const result = spawnSync("sh", ["-c", `rushx ${argv.script}`], {
20 | cwd: targetProject?.projectFolder,
21 | shell: false,
22 | stdio: [0, 1, 2],
23 | });
24 | if (result.status !== 0) {
25 | process.exit(result.status);
26 | }
27 | }
28 | }
29 |
30 | run();
31 |
--------------------------------------------------------------------------------
/common/config/rush/.npmrc:
--------------------------------------------------------------------------------
1 | # Rush uses this file to configure the NPM package registry during installation. It is applicable
2 | # to PNPM, NPM, and Yarn package managers. It is used by operations such as "rush install",
3 | # "rush update", and the "install-run.js" scripts.
4 | #
5 | # NOTE: The "rush publish" command uses .npmrc-publish instead.
6 | #
7 | # Before invoking the package manager, Rush will copy this file to the folder where installation
8 | # is performed. The copied file will omit any config lines that reference environment variables
9 | # that are undefined in that session; this avoids problems that would otherwise result due to
10 | # a missing variable being replaced by an empty string.
11 | #
12 | # * * * SECURITY WARNING * * *
13 | #
14 | # It is NOT recommended to store authentication tokens in a text file on a lab machine, because
15 | # other unrelated processes may be able to read the file. Also, the file may persist indefinitely,
16 | # for example if the machine loses power. A safer practice is to pass the token via an
17 | # environment variable, which can be referenced from .npmrc using ${} expansion. For example:
18 | #
19 | # //registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}
20 | #
21 | registry=https://registry.npmjs.org/
22 | always-auth=false
23 |
24 |
--------------------------------------------------------------------------------
/common/config/rush/.npmrc-publish:
--------------------------------------------------------------------------------
1 | # This config file is very similar to common/config/rush/.npmrc, except that .npmrc-publish
2 | # is used by the "rush publish" command, as publishing often involves different credentials
3 | # and registries than other operations.
4 | #
5 | # Before invoking the package manager, Rush will copy this file to "common/temp/publish-home/.npmrc"
6 | # and then temporarily map that folder as the "home directory" for the current user account.
7 | # This enables the same settings to apply for each project folder that gets published. The copied file
8 | # will omit any config lines that reference environment variables that are undefined in that session;
9 | # this avoids problems that would otherwise result due to a missing variable being replaced by
10 | # an empty string.
11 | #
12 | # * * * SECURITY WARNING * * *
13 | #
14 | # It is NOT recommended to store authentication tokens in a text file on a lab machine, because
15 | # other unrelated processes may be able to read the file. Also, the file may persist indefinitely,
16 | # for example if the machine loses power. A safer practice is to pass the token via an
17 | # environment variable, which can be referenced from .npmrc using ${} expansion. For example:
18 | #
19 | //registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}
20 | #
21 |
--------------------------------------------------------------------------------
/common/config/rush/.pnpmfile.cjs:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * When using the PNPM package manager, you can use pnpmfile.js to workaround
5 | * dependencies that have mistakes in their package.json file. (This feature is
6 | * functionally similar to Yarn's "resolutions".)
7 | *
8 | * For details, see the PNPM documentation:
9 | * https://pnpm.js.org/docs/en/hooks.html
10 | *
11 | * IMPORTANT: SINCE THIS FILE CONTAINS EXECUTABLE CODE, MODIFYING IT IS LIKELY TO INVALIDATE
12 | * ANY CACHED DEPENDENCY ANALYSIS. After any modification to pnpmfile.js, it's recommended to run
13 | * "rush update --full" so that PNPM will recalculate all version selections.
14 | */
15 | module.exports = {
16 | hooks: {
17 | readPackage
18 | }
19 | };
20 |
21 | /**
22 | * This hook is invoked during installation before a package's dependencies
23 | * are selected.
24 | * The `packageJson` parameter is the deserialized package.json
25 | * contents for the package that is about to be installed.
26 | * The `context` parameter provides a log() function.
27 | * The return value is the updated object.
28 | */
29 | function readPackage(packageJson, context) {
30 |
31 | // // The karma types have a missing dependency on typings from the log4js package.
32 | // if (packageJson.name === '@types/karma') {
33 | // context.log('Fixed up dependencies for @types/karma');
34 | // packageJson.dependencies['log4js'] = '0.6.38';
35 | // }
36 |
37 | return packageJson;
38 | }
39 |
--------------------------------------------------------------------------------
/common/config/rush/repo-state.json:
--------------------------------------------------------------------------------
1 | // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush.
2 | {
3 | "preferredVersionsHash": "bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f"
4 | }
5 |
--------------------------------------------------------------------------------
/common/config/rush/rush-plugins.json:
--------------------------------------------------------------------------------
1 | /**
2 | * This configuration file manages Rush's plugin feature.
3 | */
4 | {
5 | "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugins.schema.json",
6 | "plugins": [
7 | /**
8 | * Each item configures a plugin to be loaded by Rush.
9 | */
10 | // {
11 | // /**
12 | // * The name of the NPM package that provides the plugin.
13 | // */
14 | // "packageName": "@scope/my-rush-plugin",
15 | // /**
16 | // * The name of the plugin. This can be found in the "pluginName"
17 | // * field of the "rush-plugin-manifest.json" file in the NPM package folder.
18 | // */
19 | // "pluginName": "my-plugin-name",
20 | // /**
21 | // * The name of a Rush autoinstaller that will be used for installation, which
22 | // * can be created using "rush init-autoinstaller". Add the plugin's NPM package
23 | // * to the package.json "dependencies" of your autoinstaller, then run
24 | // * "rush update-autoinstaller".
25 | // */
26 | // "autoinstallerName": "rush-plugins"
27 | // }
28 | ]
29 | }
--------------------------------------------------------------------------------
/common/config/rush/version-policies.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "definitionName": "lockStepVersion",
4 | "policyName": "vmindMin",
5 | "version": "2.0.6",
6 | "mainProject": "@visactor/vmind",
7 | "nextBump": "patch"
8 | }
9 | ]
10 |
--------------------------------------------------------------------------------
/common/git-hooks/commit-msg:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | node common/scripts/install-run-rush.js commitlint || exit $? #++
--------------------------------------------------------------------------------
/common/git-hooks/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # log rush change to stdout
4 | STAGE_FILES=$(git diff --cached --name-only)
5 |
6 | if [[ $STAGE_FILES != "" ]] ; then
7 | changedFiles=''
8 | # 红色文本的 ANSI 转义序列
9 | RED='\033[0;31m'
10 | # 大字体的 ANSI 转义序列
11 | BIG_FONT='\033[1m'
12 |
13 | # 重置颜色的 ANSI 转义序列
14 | RESET='\033[0m'
15 |
16 | for fileName in $STAGE_FILES;do
17 | if [[ $fileName =~ ^packages/.*\/src/.* ]]; then
18 | changedFiles="${changedFiles}
19 | ${RED}${fileName}${RESET}"
20 | fi
21 | done;
22 |
23 | if [[ $changedFiles != "" ]] ; then
24 |
25 | echo "
26 | [Notice]: please check, do you need to run ${RED}${BIG_FONT}rush change-all${RESET} to generate changelog,
27 | you has modified some src files, include:
28 | ${changedFiles}
29 | "
30 | fi
31 | fi
32 |
33 | # lint-staged
34 | node common/scripts/install-run-rush.js lint-staged || exit $? #++
35 |
36 | # local pre-commit
37 | if [ -f "common/scripts/pre-commit" ]; then
38 | common/scripts/pre-commit
39 | fi
40 |
--------------------------------------------------------------------------------
/common/git-hooks/pre-push:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | while read local_ref local_sha remote_ref remote_sha
4 | do
5 | # 检查是否是hotfix发布分支
6 | if [[ $local_ref = refs/heads/hotfix/* && $local_ref =~ ^refs/heads/hotfix/[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
7 | echo "Hotfix branch, skipping local test"
8 | exit 0
9 | fi
10 |
11 | # 检查是否是release发布分支
12 | if [[ $local_ref = refs/heads/release/* && $local_ref =~ ^refs/heads/release/[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
13 | echo "Release branch, skipping local test"
14 | exit 0
15 | fi
16 |
17 | # 检查是否是同步代码发布分支
18 | if [[ $local_ref = refs/heads/sync/main-* && $local_ref =~ ^refs/heads/sync/main-[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
19 | echo "Auto sync code branch, skipping local test"
20 | exit 0
21 | fi
22 |
23 | # 检查是否是changelog分支
24 | if [[ $local_ref = refs/heads/sync/docs/generate-changelog-* && $local_ref =~ ^refs/heads/docs/generate-changelog-[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
25 | echo "Auto changelog branch, skipping local test"
26 | exit 0
27 | fi
28 |
29 | # 检查是否是删除操作
30 | if [ "$local_sha" = "0000000000000000000000000000000000000000" ]; then
31 | echo "Ignoring push deletion. Skipping local test."
32 | exit 0
33 | fi
34 |
35 | # 其他推送逻辑...
36 | #node common/scripts/install-run-rush.js test --only tag:package
37 | done
38 |
39 |
--------------------------------------------------------------------------------
/common/scripts/apply-prerelease-version.js:
--------------------------------------------------------------------------------
1 | const writePrereleaseVersion = require('./set-prerelease-version');
2 | const checkAndUpdateNextBump = require('./version-policies');
3 | const parseVersion = require('./parse-version');
4 |
5 |
6 | function run() {
7 | const preReleaseName = process.argv.slice(2)[0];
8 | const nextVersionOrNextBump = process.argv.slice(2)[1];
9 | const buildName = process.argv.slice(2)[2];
10 | const nextBump = checkAndUpdateNextBump(nextVersionOrNextBump);
11 | const parsedNextVersion = nextVersionOrNextBump ? parseVersion(nextVersionOrNextBump) : null;
12 | const nextVersion = parsedNextVersion ? `${parsedNextVersion.major}.${parsedNextVersion.minor}.${parsedNextVersion.patch}`: null;
13 |
14 | console.log('[apply prerelease version]: ', preReleaseName, nextBump, nextVersion);
15 |
16 | writePrereleaseVersion(nextBump, preReleaseName, nextVersion, buildName);
17 | }
18 |
19 | run()
20 |
--------------------------------------------------------------------------------
/common/scripts/apply-release-version.js:
--------------------------------------------------------------------------------
1 | const writePrereleaseVersion = require('./set-prerelease-version');
2 | const checkAndUpdateNextBump = require('./version-policies');
3 | const parseVersion = require('./parse-version');
4 |
5 |
6 | function run() {
7 | const preReleaseName = process.argv.slice(2)[0];
8 | const nextVersionOrNextBump = process.argv.slice(2)[1];
9 | const buildName = process.argv.slice(2)[2];
10 | const nextBump = checkAndUpdateNextBump(nextVersionOrNextBump);
11 | const parsedNextVersion = nextVersionOrNextBump ? parseVersion(nextVersionOrNextBump) : null;
12 | const nextVersion = parsedNextVersion ? `${parsedNextVersion.major}.${parsedNextVersion.minor}.${parsedNextVersion.patch}`: null;
13 |
14 | console.log('[apply prerelease version]: ', preReleaseName, nextBump, nextVersion);
15 |
16 | writePrereleaseVersion(nextBump, preReleaseName, nextVersion, buildName);
17 | }
18 |
19 | run()
20 |
--------------------------------------------------------------------------------
/common/scripts/get-package-json.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 |
3 | function getPackageJson(pkgJsonPath) {
4 | const pkgJson = fs.readFileSync(pkgJsonPath, { encoding: 'utf-8' })
5 | return JSON.parse(pkgJson);
6 | }
7 |
8 | module.exports = getPackageJson;
--------------------------------------------------------------------------------
/common/scripts/install-run-rush-pnpm.js:
--------------------------------------------------------------------------------
1 | // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED.
2 | //
3 | // This script is intended for usage in an automated build environment where the Rush command may not have
4 | // been preinstalled, or may have an unpredictable version. This script will automatically install the version of Rush
5 | // specified in the rush.json configuration file (if not already installed), and then pass a command-line to the
6 | // rush-pnpm command.
7 | //
8 | // An example usage would be:
9 | //
10 | // node common/scripts/install-run-rush-pnpm.js pnpm-command
11 | //
12 | // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/
13 |
14 | /******/ (() => { // webpackBootstrap
15 | /******/ "use strict";
16 | var __webpack_exports__ = {};
17 | /*!*****************************************************!*\
18 | !*** ./lib-esnext/scripts/install-run-rush-pnpm.js ***!
19 | \*****************************************************/
20 |
21 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
22 | // See the @microsoft/rush package's LICENSE file for license information.
23 | require('./install-run-rush');
24 | //# sourceMappingURL=install-run-rush-pnpm.js.map
25 | module.exports = __webpack_exports__;
26 | /******/ })()
27 | ;
28 | //# sourceMappingURL=install-run-rush-pnpm.js.map
--------------------------------------------------------------------------------
/common/scripts/install-run-rushx.js:
--------------------------------------------------------------------------------
1 | // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED.
2 | //
3 | // This script is intended for usage in an automated build environment where the Rush command may not have
4 | // been preinstalled, or may have an unpredictable version. This script will automatically install the version of Rush
5 | // specified in the rush.json configuration file (if not already installed), and then pass a command-line to the
6 | // rushx command.
7 | //
8 | // An example usage would be:
9 | //
10 | // node common/scripts/install-run-rushx.js custom-command
11 | //
12 | // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/
13 |
14 | /******/ (() => { // webpackBootstrap
15 | /******/ "use strict";
16 | var __webpack_exports__ = {};
17 | /*!*************************************************!*\
18 | !*** ./lib-esnext/scripts/install-run-rushx.js ***!
19 | \*************************************************/
20 |
21 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
22 | // See the @microsoft/rush package's LICENSE file for license information.
23 | require('./install-run-rush');
24 | //# sourceMappingURL=install-run-rushx.js.map
25 | module.exports = __webpack_exports__;
26 | /******/ })()
27 | ;
28 | //# sourceMappingURL=install-run-rushx.js.map
--------------------------------------------------------------------------------
/common/scripts/parse-version.js:
--------------------------------------------------------------------------------
1 | // see more about the regex here: https://semver.org/lang/zh-CN/
2 | // reg test: https://regex101.com/r/vkijKf/1/
3 |
4 | function parseVersion(version) {
5 | const res = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/gm.exec(version);
6 |
7 | if (res) {
8 | return {
9 | major: +res[1],
10 | minor: +res[2],
11 | patch: +res[3],
12 | preReleaseName: res[4],
13 | preReleaseType: res[4] && res[4].includes('.') ? res[4].split('.')[0] : res[4],
14 | buildName: res[5],
15 | buildType: res[5] && res[5].includes('.') ? res[5].split('.')[0] : res[5],
16 |
17 | };
18 | }
19 |
20 | return null;
21 | }
22 |
23 | module.exports = parseVersion
--------------------------------------------------------------------------------
/common/scripts/set-json-file.js:
--------------------------------------------------------------------------------
1 | function setJsonFileByKey(file, json, keys, newValue) {
2 | const prevValue = keys.reduce((res, k) => {
3 | return res[k];
4 | }, json);
5 |
6 | if (prevValue !== newValue) {
7 | let startIndex = 0;
8 |
9 | keys.forEach(k => {
10 | const keyStr = `"${k}"`;
11 | const index = file.indexOf(keyStr, startIndex);
12 |
13 | if (index >= 0) {
14 | startIndex = index + keyStr.length + 1;
15 | }
16 | })
17 |
18 | const leftIndex = file.indexOf('"', startIndex);
19 | const rightIndex = leftIndex >= 0 ? file.indexOf('"', leftIndex +1) : -1;
20 |
21 | if (leftIndex >= 0 && rightIndex >= 0) {
22 | return `${file.slice(0, leftIndex)}"${newValue}"${file.slice(rightIndex + 1)}`
23 | }
24 | }
25 |
26 | return file;
27 | }
28 |
29 | module.exports = setJsonFileByKey;
30 |
31 |
--------------------------------------------------------------------------------
/common/template/chart.d.ts:
--------------------------------------------------------------------------------
1 | export * from './esm/chart/index.d.ts';
2 |
--------------------------------------------------------------------------------
/common/template/chart.js:
--------------------------------------------------------------------------------
1 | export * from './esm/chart/index.js';
2 |
--------------------------------------------------------------------------------
/common/template/component.d.ts:
--------------------------------------------------------------------------------
1 | export * from './esm/component/index.d.ts';
2 |
--------------------------------------------------------------------------------
/common/template/component.js:
--------------------------------------------------------------------------------
1 | export * from './esm/component/index.js';
2 |
--------------------------------------------------------------------------------
/common/template/core.d.ts:
--------------------------------------------------------------------------------
1 | export * from './esm/core/index.d.ts';
2 |
--------------------------------------------------------------------------------
/common/template/core.js:
--------------------------------------------------------------------------------
1 | export * from './esm/core/index.js';
2 |
--------------------------------------------------------------------------------
/common/template/layout.d.ts:
--------------------------------------------------------------------------------
1 | export * from './esm/layout/index.d.ts';
2 |
--------------------------------------------------------------------------------
/common/template/layout.js:
--------------------------------------------------------------------------------
1 | export * from './esm/layout/index.js';
2 |
--------------------------------------------------------------------------------
/common/template/mark.d.ts:
--------------------------------------------------------------------------------
1 | export * from './esm/mark/index.d.ts';
2 |
--------------------------------------------------------------------------------
/common/template/mark.js:
--------------------------------------------------------------------------------
1 | export * from './esm/mark/index.js';
2 |
--------------------------------------------------------------------------------
/common/template/series.d.ts:
--------------------------------------------------------------------------------
1 | export * from './esm/series/index.d.ts';
2 |
--------------------------------------------------------------------------------
/common/template/series.js:
--------------------------------------------------------------------------------
1 | export * from './esm/series/index.js';
2 |
--------------------------------------------------------------------------------
/docs/assets/api/menu.json:
--------------------------------------------------------------------------------
1 | {
2 | "menu": "scripts",
3 | "children": [
4 | {
5 | "path": "VMind_Instance",
6 | "title": {
7 | "zh": "VMind实例",
8 | "en": "VMind Instance"
9 | }
10 | },
11 | {
12 | "path": "parseCSVData",
13 | "title": {
14 | "zh": "parseCSVData",
15 | "en": "parseCSVData"
16 | }
17 | },
18 | {
19 | "path": "getFieldInfo",
20 | "title": {
21 | "zh": "getFieldInfo",
22 | "en": "getFieldInfo"
23 | }
24 | },
25 | {
26 | "path": "fillSpecWithData",
27 | "title": {
28 | "zh": "fillSpecWithData",
29 | "en": "fillSpecWithData"
30 | }
31 | },
32 | {
33 | "path": "dataQuery",
34 | "title": {
35 | "zh": "dataQuery",
36 | "en": "dataQuery"
37 | }
38 | },
39 | {
40 | "path": "generateChart",
41 | "title": {
42 | "zh": "generateChart",
43 | "en": "generateChart"
44 | }
45 | },
46 | {
47 | "path": "text2Chart",
48 | "title": {
49 | "zh": "text2Chart",
50 | "en": "text2Chart"
51 | }
52 | },
53 | {
54 | "path": "getInsights",
55 | "title": {
56 | "zh": "getInsights",
57 | "en": "getInsights"
58 | }
59 | }
60 | ]
61 | }
--------------------------------------------------------------------------------
/docs/assets/api/zh/parseCSVData.md:
--------------------------------------------------------------------------------
1 | # parseCSVData
2 |
3 | ## 接口描述
4 |
5 | parseCSVData接口用于将CSV字符串转换为VMind所需的数据集(dataset)和字段信息(fieldInfo)。
6 |
7 | ## 接口参数
8 |
9 | ```typescript
10 | parseCSVData(csv: string): { fieldInfo: FieldInfo[], dataset: any[] }
11 | ```
12 |
13 | - csv: string类型,表示需要解析的CSV字符串。
14 |
15 | ## 返回值类型
16 |
17 | 返回一个对象,包含两个属性:
18 |
19 | - fieldInfo: FieldInfo[]类型,表示解析后的字段信息,每个元素是一个对象,包含以下属性:
20 |
21 | ```bash
22 | - fieldName: string类型,表示字段名称。
23 | - description: string类型,表示字段描述,可选。
24 | - type: DataType类型,表示字段类型,可为"string"、"int"、"float"、"date"。
25 | - role: ROLE类型,表示字段角色,可为"dimension"、"measure"。
26 | ```
27 |
28 |
29 | - dataset: DataItem类型,表示解析后的数据集,每个元素是一个对象,键为字段名称,值为对应的数据:
30 | ```ts
31 | type DataItem = Record;
32 | ```
33 |
34 | ## 使用示例
35 |
36 | ```typescript
37 | import VMind from '@visactor/vmind'
38 | const csv=`Product name,region,Sales
39 | Coke,south,2350
40 | Coke,east,1027
41 | Coke,west,1027
42 | Coke,north,1027
43 | Sprite,south,215
44 | Sprite,east,654
45 | Sprite,west,159
46 | Sprite,north,28
47 | Fanta,south,345
48 | Fanta,east,654
49 | Fanta,west,2100
50 | Fanta,north,1679
51 | Mirinda,south,1476
52 | Mirinda,east,830
53 | Mirinda,west,532
54 | Mirinda,north,498`
55 | const vmind = new VMind(options)
56 | const { fieldInfo, dataset } = vmind.parseCSVData(csv);
57 | ```
58 |
59 | ## 相关教程
60 | [数据格式与数据处理](../guide/Basic_Tutorial/Chart_Generation)
61 |
--------------------------------------------------------------------------------
/docs/assets/guide/en/Basic_Tutorial/How_to_Get_VMind.md:
--------------------------------------------------------------------------------
1 | # How to Get VMind
2 |
3 | There are several ways to get VMind:
4 |
5 | - Get from npm
6 | - Get from cdn
7 | - Get from GitHub repository
8 |
9 | ## Get from npm
10 |
11 | First, you need to install VMind in the root directory of the project using the following command
12 |
13 | ```bash
14 | # Install with npm
15 | npm install @visactor/vmind
16 |
17 | # Install with yarn
18 | yarn add @visactor/vmind
19 | ```
20 |
21 | VMind needs to be used in conjunction with VChart. In order to draw charts, you also need to introduce VChart into the project. For specific tutorials, please refer to [VChart Quick Start](https://www.visactor.io/vchart/guide/tutorial_docs/Getting_Started)
22 |
23 |
24 | ## Get from cdn
25 |
26 | You can get VMind from the following free CDN:
27 |
28 | ```html
29 |
30 |
31 |
32 |
33 |
34 | ```
35 |
36 | ## Get from GitHub
37 |
38 | On GitHub, you can directly get the source code of VMind:
39 |
40 | - You can directly clone the source code from GitHub.
41 | - You can also choose the corresponding version from the [release](https://github.com/VisActor/VMind/releases) page of VMind, click on Source code in Assets at the bottom of the page, download it to the local and unzip it for use.
42 |
--------------------------------------------------------------------------------
/docs/assets/guide/en/Basic_Tutorial/How_to_Import_VMind.md:
--------------------------------------------------------------------------------
1 | # How to Reference VMind in Your Project
2 |
3 | In the [How to Get VMind](./How_to_Get_VMind) section, we introduced how to get VMind. This section will introduce how to reference VMind under these acquisition methods one by one.
4 |
5 | ## Using cdn
6 |
7 | After we get the VMind file from [cdn](./How_to_Get_VMind#cdn-获取), we can add it to the `
24 |
25 |
35 | ```
36 |
37 | ## Using npm
38 |
39 | After we install `@visactor/vmind` into the project through [npm](./How_to_Get_VMind#npm-获取), we can use it in the following way:
40 |
41 | ```ts
42 | import VMind, { Model } from '@visactor/vmind'
43 |
44 | const vmind = new VMind({
45 | url, //default is https://api.openai.com/v1/chat/completions
46 | model: Model.GPT3_5,
47 | headers: {
48 | 'api-key': apiKey //Your LLM API Key
49 | }
50 | })
51 | ```
52 |
--------------------------------------------------------------------------------
/docs/assets/guide/zh/Basic_Tutorial/How_to_Get_VMind.md:
--------------------------------------------------------------------------------
1 | # 如何获取 VMind
2 |
3 | 获取 VMind 的方式有以下几种:
4 |
5 | - 从 npm 获取
6 | - 从 cdn 获取
7 | - 从 GitHub 仓库获取
8 |
9 | ## npm 获取
10 |
11 | 首先,你需要在项目根目录下使用以下命令安装 VMind
12 |
13 | ```bash
14 | # 使用 npm 安装
15 | npm install @visactor/vmind
16 |
17 | # 使用 yarn 安装
18 | yarn add @visactor/vmind
19 | ```
20 |
21 | VMind 需要配合 VChart 一起使用。为了进行图表绘制,你还需要在项目中引入 VChart,具体教程详见[VChart快速上手](https://www.visactor.io/vchart/guide/tutorial_docs/Getting_Started)
22 |
23 |
24 | ## cdn 获取
25 |
26 | 可以从以下免费的 CDN 中获取 VMind:
27 |
28 | ```html
29 |
30 |
31 |
32 |
33 |
34 | ```
35 |
36 | ## GitHub 获取
37 |
38 | 从 GitHub 上你可以直接获取 VMind 的源码:
39 |
40 | - 你可以直接从 GitHub clone 源码。
41 | - 你也可以从 VMind 的 [release](https://github.com/VisActor/VMind/releases) 页面选择对应的版本,点击页面下方 Assets 中的 Source code,将其下载至本地解压后使用。
42 |
--------------------------------------------------------------------------------
/docs/assets/guide/zh/Basic_Tutorial/How_to_Import_VMind.md:
--------------------------------------------------------------------------------
1 | # 如何在项目中引用 VMind
2 |
3 | 在[如何获取 VMind](./How_to_Get_VMind)章节中我们介绍了获取 VMind 的方式,本章节会一一介绍这些获取方式下如何引用 VMind
4 |
5 | ## cdn 使用
6 |
7 | 我们从 [cdn](./How_to_Get_VMind#cdn-获取) 获取到 VMind 文件后,就可以将其添加到 HTML 文件的 `
24 |
25 |
35 | ```
36 |
37 | ## npm 使用
38 |
39 | 我们通过 [npm](./How_to_Get_VMind#npm-获取) 的方式将 `@visactor/vmind` 安装到项目之后,就可以通过如下方式进行使用了:
40 |
41 | ```ts
42 | import VMind, { Model } from '@visactor/vmind'
43 |
44 | const vmind = new VMind({
45 | url, //default is https://api.openai.com/v1/chat/completions
46 | model: Model.GPT3_5,
47 | headers: {
48 | 'api-key': apiKey //Your LLM API Key
49 | }
50 | })
51 | ```
52 |
--------------------------------------------------------------------------------
/docs/assets/guide/zh/VMind_Website_Guide.md:
--------------------------------------------------------------------------------
1 |
2 | # VMind站点指南
3 |
4 | 本篇文章的目的是为了帮助你更有效地使用 VMind 网站,让你能更快地找到你需要的信息。
5 |
6 | ## 快速开始
7 |
8 | ### 快速上手
9 |
10 | 首先,你需要阅读 VMind 的[快速上手](./Getting_Started)章节。这个章节会教你如何配置和使用 VMind 所需的环境,以及如何使用 VMind 构建你的第一个智能可视化应用。
11 |
12 | ### 深入了解 VMind
13 |
14 | 在你完成[快速上手](./Getting_Started)后,你可以在[VMind简介](./Intro_to_VMind)了解 VMind 的功能定位和相关概念。
15 | [创建VMind对象](./Create_VMind_Object)章节将教你如何初始化一个 VMind 对象以进行后续操作。你还可以通过阅读[数据处理与输入](./Data_Input_and_Process)章节来了解 VMind 支持的数据类型。在[图表生成](./Chart_Generation)章节,你可以深入了解如何使用 VMind 进行图表智能生成。[数据聚合](./Data_Aggregation)章节将教你如何使用 VMind 对数据进行排序、筛选、聚合等操作。
16 |
17 | ## 文档
18 |
19 | VMind 的文档提供了详细的功能和 API 信息。根据你的需求,你可以查看以下几个部分:
20 |
21 | - [教程](./Basic_Tutorial/Create_VMind_Instance):介绍了 VMind 的基本概念和各种使用方法。
22 |
23 | - [API](../api/VMind_Instance):提供了 VMind 的所有可用接口的详细说明。
24 |
25 |
30 |
31 | ## 如何使用搜索功能
32 |
33 | 本站点提供了一个强大的搜索功能,让你可以快速找到相关的使用信息。点击站点顶部的搜索框,输入关键词后,你将在下拉列表中看到匹配的结果。选择合适的结果即可查看相关内容。
34 |
35 | ## 如何提问&建议
36 |
37 | 我们很高兴为你提供帮助! 如果你在使用 VMind 过程中遇到问题,可以通过以下方式提问:
38 |
39 | 1. 在 GitHub 仓库中提交一个 issue:访问 [VMind GitHub](https://github.com/VisActor/VMind/issues/new/choose),详细描述你遇到的问题,我们的团队将尽快回应并解决。
40 |
41 | 2. 在 GitHub 仓库提交一个 discussion:访问 [VMind Discussion](https://github.com/VisActor/VMind/discussions),非常欢迎你在这里提出你的想法和建议,我们的团队将尽快回应并解决。
42 |
43 | ## 如何纠错
44 |
45 | 如果你在文档示例中发现问题,或者认为某些部分可以改进,务必告诉我们。你可以通过以下方式为我们提纠错信息:
46 |
47 | 1. 在 GitHub 仓库中提交一个 pull request:纠正的内容并提交,会有团队成员审核并合并。
48 |
49 | 2. 提交一个 issue:指出文档中存在的问题,团队成员会尽快核实并修正。
50 |
51 | 感谢你的帮助!我们将不断完善文档,为所有 VMind 用户提供更好的学习体验。
52 |
--------------------------------------------------------------------------------
/docs/assets/openManus/Readme.md:
--------------------------------------------------------------------------------
1 | # Case of Sales Analysis and Strategies for Amazon Store
2 |
3 | The current folder contains all execution artifacts of [the Sales Analysis and Strategies for Amazon Store case in manus](https://manus.im/share/c3onakN6Iajcm1Vt1xAVG7?replay=1)
--------------------------------------------------------------------------------
/docs/assets/openManus/aov_trend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VisActor/VMind/556f979b7b6537b43ee2b886863ca62f419629b7/docs/assets/openManus/aov_trend.png
--------------------------------------------------------------------------------
/docs/assets/openManus/correlation_heatmap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VisActor/VMind/556f979b7b6537b43ee2b886863ca62f419629b7/docs/assets/openManus/correlation_heatmap.png
--------------------------------------------------------------------------------
/docs/assets/openManus/daily_sales_trend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VisActor/VMind/556f979b7b6537b43ee2b886863ca62f419629b7/docs/assets/openManus/daily_sales_trend.png
--------------------------------------------------------------------------------
/docs/assets/openManus/home/ubuntu/analysis/data_exploration.txt:
--------------------------------------------------------------------------------
1 | Amazon Fashion Sales Data Exploration - January 2025
2 |
3 | Dataset Overview:
4 | - 31 rows (daily sales for January 2025)
5 | - 10 columns including date, orders, customers, and financial metrics
6 | - No missing values in the dataset
7 |
8 | Columns:
9 | - Date: Date of sales (datetime64)
10 | - Orders: Number of orders per day (int64)
11 | - Unique Customers: Number of unique customers per day (int64)
12 | - Units Sold: Total units sold per day (int64)
13 | - Gross Sales: Total sales amount before deductions (float64)
14 | - Shipping Revenue: Revenue from shipping (float64)
15 | - Coupon Discounts: Discount amount from coupons (float64)
16 | - Amazon Fees: Fees paid to Amazon (float64)
17 | - Product Costs: Cost of products sold (float64)
18 | - Net Profit: Final profit after all deductions (float64)
19 |
20 | Basic Statistics:
21 | - Average daily orders: ~39
22 | - Average daily unique customers: ~39
23 | - Average daily units sold: ~101
24 | - Average daily gross sales: ~$5,348.56
25 | - Average daily net profit: ~$1,835.56
26 | - Highest daily orders: 79
27 | - Highest daily gross sales: $11,752.01
28 | - Highest daily net profit: $4,010.05
29 |
30 | Initial Observations:
31 | - Orders and unique customers are nearly identical, suggesting most customers place only one order
32 | - There appears to be significant daily variation in sales metrics
33 | - Further analysis needed to identify patterns by day of week and other factors
34 |
--------------------------------------------------------------------------------
/docs/assets/openManus/home/ubuntu/todo.md:
--------------------------------------------------------------------------------
1 | # Amazon Fashion Sales Analysis Todo List
2 |
3 | ## Data Preparation and Analysis
4 | - [x] Load and explore the Amazon Fashion Sales data
5 | - [x] Clean and preprocess data (create derived metrics)
6 | - [x] Perform comprehensive sales analysis
7 | - [x] Create data visualizations
8 | - [x] Identify key insights and trends
9 |
10 | ## Strategy Development and Reporting
11 | - [x] Develop data-driven strategies to boost sales by 10%
12 | - [x] Prepare comprehensive analysis report
13 | - [x] Deliver final report with recommendations
14 |
--------------------------------------------------------------------------------
/docs/assets/openManus/orders_by_day.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VisActor/VMind/556f979b7b6537b43ee2b886863ca62f419629b7/docs/assets/openManus/orders_by_day.png
--------------------------------------------------------------------------------
/docs/assets/openManus/outlier_comparison.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VisActor/VMind/556f979b7b6537b43ee2b886863ca62f419629b7/docs/assets/openManus/outlier_comparison.png
--------------------------------------------------------------------------------
/docs/assets/openManus/profit_margin_by_discount.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VisActor/VMind/556f979b7b6537b43ee2b886863ca62f419629b7/docs/assets/openManus/profit_margin_by_discount.png
--------------------------------------------------------------------------------
/docs/assets/openManus/sales_by_day.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VisActor/VMind/556f979b7b6537b43ee2b886863ca62f419629b7/docs/assets/openManus/sales_by_day.png
--------------------------------------------------------------------------------
/docs/assets/openManus/weekend_comparison.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VisActor/VMind/556f979b7b6537b43ee2b886863ca62f419629b7/docs/assets/openManus/weekend_comparison.png
--------------------------------------------------------------------------------
/docs/assets/openManus/weekly_sales.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VisActor/VMind/556f979b7b6537b43ee2b886863ca62f419629b7/docs/assets/openManus/weekly_sales.png
--------------------------------------------------------------------------------
/docs/assets/scenario/en/Chart_Assistant.md:
--------------------------------------------------------------------------------
1 | # Chart Intelligence Assistant
2 | VMind can serve as a visual agent for large language models, responsible for tasks such as chart generation and chart editing, thereby creating a "Chart Intelligence Assistant". This assistant can serve as an independent robot, or it can be integrated into other products in the form of a Copilot.
3 |
4 |
5 |
6 |
7 |
8 |
9 | As a chart intelligence assistant, VMind can generate corresponding charts based on the natural language description entered by the user. It can also realize secondary filtering, aggregation, and sorting of data through the intelligent data aggregation module.
10 |
11 | Whether you need to display a time series line chart or a bar chart of different categories, VMind can quickly respond and help you select the chart type and generate the chart. With VMind, users can create both aesthetically pleasing and information-rich charts without in-depth chart design knowledge, greatly improving work efficiency.
12 |
13 | ## Experience address:
14 | - [Coze](https://www.coze.com/s/Zs8MNnSod/)
15 | - [Discord](https://discord.gg/sajqrVSP): Join the Discord channel and @VMind Chart Master bot experience in chat.
16 |
--------------------------------------------------------------------------------
/docs/assets/scenario/en/Document_Assistant.md:
--------------------------------------------------------------------------------
1 | # Document Assistant
2 | When writing reports or documents, accurate and beautiful charts are indispensable. The Document Assistant built on VMind can help users quickly generate charts from selected data and insert them into documents.
3 |
4 |
5 |
6 |
7 |
8 |
9 | In addition, VMind will also introduce an intelligent insight feature, which can intelligently identify insights in chart data and automatically add annotations to them. These annotations can directly display specific data values, provide additional explanations and contextual information, and help readers better understand the charts.
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/assets/scenario/menu.json:
--------------------------------------------------------------------------------
1 | {
2 | "menu": "scripts",
3 | "children": [
4 | {
5 | "path": "OpenManus_VMind",
6 | "title": {
7 | "zh": "OpenManus X VMind : 快速打造你的数据分析助手",
8 | "en": "OpenManus X VMind: Quickly Build Your Data Analysis Assistant"
9 | }
10 | },
11 | {
12 | "path": "Chart_Assistant",
13 | "title": {
14 | "zh": "图表助手",
15 | "en": "Chart Assistant"
16 | }
17 | },
18 | {
19 | "path": "Wordcloud_Cube",
20 | "title": {
21 | "zh": "可视化叙事-词云魔方",
22 | "en": "Visual Narration: Word Cloud Cube"
23 | }
24 | },
25 | {
26 | "path": "Data_Video",
27 | "title": {
28 | "zh": "数据视频创作",
29 | "en": "Data video creation"
30 | }
31 | },
32 | {
33 | "path": "Document_Assistant",
34 | "title": {
35 | "zh": "文档助手",
36 | "en": "Document Assistant"
37 | }
38 | },
39 | {
40 | "path": "Data_Development",
41 | "title": {
42 | "zh": "数据开发",
43 | "en": "Data Development"
44 | }
45 | },
46 | {
47 | "path": "Open_API",
48 | "title": {
49 | "zh": "VMind Open API",
50 | "en": "VMind Open API"
51 | }
52 | }
53 | ]
54 | }
--------------------------------------------------------------------------------
/docs/assets/scenario/zh/Chart_Assistant.md:
--------------------------------------------------------------------------------
1 | # 图表智能助手
2 | VMind可以成为大语言模型的可视化代理(agent),负责处理图表生成、图表编辑等相关任务,从而打造出“图表智能助手”。这个助手既可以作为一个独立的机器人提供服务,也可以以Copilot形式接入其他产品。
3 |
4 |
5 |
6 |
7 |
8 |
9 | 作为图表智能助手,VMind可以根据用户输入的自然语言描述,自动生成相应的图表。还可通过智能数据聚合模块实现数据的二次筛选、聚合、排序。
10 |
11 | 无论你需要展示的是时间序列的折线图,还是不同类别的柱状图,VMind都能迅速响应并帮助你选择图表类型及生成图表。有了VMind,用户无需深厚的图表设计知识,就可以制作出既美观又信息丰富的图表,极大地提高了工作效率。
12 |
13 | ## 体验地址:
14 | - [Coze](https://www.coze.com/s/Zs8MNnSod/)
15 | - [Discord](https://discord.gg/sajqrVSP): 加入Discord频道,在聊天中 @VMind Chart Master 机器人即可体验
16 |
--------------------------------------------------------------------------------
/docs/assets/scenario/zh/Data_Development.md:
--------------------------------------------------------------------------------
1 | # 数据开发
2 | 在数据开发等python Notebook场景中,适合在SQL查询结束后,调用VMind Open API进行图表生成,配合py-vchart渲染图表,在Notebook中集成智能可视化能力。
3 |
4 |
5 |
6 |
7 |
8 | ## 示例代码
9 | ```python
10 | '''
11 | 在Notebook场景下,可在SQL查询后调用VMind Open API进行图表生成,并结合py-vchart进行图表渲染
12 | VMind支持基于大模型的图表生成和基于规则的图表生成
13 | 图表生成过程不会将明细数据传给大模型,尽可放心食用
14 | '''
15 |
16 | import requests
17 | import pandas as pd
18 | from pyvchart import render_chart
19 |
20 | url = "" #VMind OPen API url
21 |
22 | # 查询出的数据集:
23 | print('sql查询结果:')
24 | display(sales_data_df)
25 |
26 | sales_data_json =sales_data_df.to_json(orient="records", force_ascii=False)
27 |
28 | userPrompt = "帮我展示不同区域各商品销售额" # 用户的展示意图
29 |
30 | print()
31 | print('输入展示意图:')
32 | print(userPrompt)
33 | print()
34 |
35 | body = {
36 | "data": sales_data_json,
37 | "userPrompt": userPrompt,
38 | "model": "doubao" # 使用豆包模型
39 | }
40 |
41 | # 调用VMind open api进行图表生成
42 | response = requests.post(url, headers=headers, json=body)
43 |
44 | chart = response.json().get('chart')[0]
45 | spec = chart.get('spec')
46 | chartType = chart.get('chartType')
47 |
48 | # print(spec)
49 | print('生成的图表类型: '+chartType)
50 |
51 | # 调用py-vchart渲染图表
52 | render_chart(spec)
53 | ```
54 |
55 | ## 相关阅读
56 | - [VMind Open API](./Open_API)
57 | - [py-vchart](https://visactor.io/vchart/guide/tutorial_docs/Cross-terminal_and_Developer_Ecology/python)
58 |
--------------------------------------------------------------------------------
/docs/assets/scenario/zh/Data_Video.md:
--------------------------------------------------------------------------------
1 | # 数据视频创作
2 | 数据视频是一种通过图表、动画、标注、旁白等方式展示和介绍数据内容的视频形式。它能将复杂的数据变得更加易懂,并引导观众获取有用的信息和见解。数据视频广泛应用于商业展示、新闻报道、教育培训等方面,是一种高效的数据展现方式,受到了各大短视频平台的喜爱。
3 |
4 | 传统的数据视频制作流程需要创作者在收集数据后,使用专业的可视化软件将数据绘制为图表;或使用各种图表库,通过编码绘制图表并导出为视频。在短视频时代,每个人都可能是视频的创作者。然而,非专业的视频创作者往往不具备将数据可视化为图表并导出为视频的能力,这大大提高了数据视频的制作门槛。
5 |
6 | 基于VMind 结合视频编辑工具,可以很容易制作丰富多彩的数据视频。使用VMind图表智能生成模块生成带动画的图表后,用户可以将其导出为视频或者GIF,导入到剪映、pr等专业的视频剪辑软件中,制作一个完整的数据视频。
7 |
8 |
9 |
10 |
11 |
12 | 将VMind集成到视频剪辑工具中,数据视频的创作也将形成完整的闭环。
13 |
14 |
15 |
--------------------------------------------------------------------------------
/docs/assets/scenario/zh/Document_Assistant.md:
--------------------------------------------------------------------------------
1 | # 文档助手
2 | 在撰写报告或文档时,准确而美观的图表是必不可少的。基于VMind打造文档助手,能够帮助用户快速从选定的数据中生成图表,并插入到文档中。
3 |
4 |
5 |
6 |
7 |
8 |
9 | 此外,VMind还将推出智能洞察功能,这个功能能够智能地识别图表数据中的洞察,并自动为其添加标注。这些标注可以直接展示具体的数据数值,同时提供额外的解释和上下文信息,帮助读者更好地理解图表。
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/assets/scenario/zh/Wordcloud_Cube.md:
--------------------------------------------------------------------------------
1 | # 可视化叙事-词云魔方
2 | VisActor一直致力于探究数据可视化在叙事场景中的应用,VMind也将与VChart叙事模板相结合,推出智能叙事功能。
3 |
4 | 我们将VMind与Coze平台结合,推出了词云魔方机器人。用户只需要上传词云的标题和核心词,VMind便能智能地为用户生成各种主题的个性化词云。
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | VMind 本身具备根据数据自动推断图表类型,并智能生成spec 的能力,但是在词云魔方场景下,需要对结果进行约束。VMind node 服务对VMind 组件进行了一层封装,只允许VMind 在我们规定的词云模版中进行选择生成。
15 |
16 |
17 |
18 | 未来我们将添加各种各样的主题模板,如节日、生肖等,给用户的创作提供更多可能和灵感。同时,我们还将支持生成GIF动图,让词云展现出独特的动态效果,使其具有更强的视觉冲击力和表达力。
19 |
20 | 当然,我们也会突破词云的限制,将词云魔方升级成为“卡片魔方”,可以生成使用范围更广,效果更惊艳的作品。同时也借此,整体推动VMind的升级,使其更加智能化,在代码生成,图表配置,自动美化,故事编排等各个方面都能有质的提升,并通过开源服务更多的开发者。
21 |
22 | ## 体验地址:
23 | - [Coze](https://www.coze.cn/s/iY7WbPQ2/)
24 |
25 | ## 相关阅读
26 | - [一念生花,Coze 结合VisActor 文生图实战总结](https://juejin.cn/post/7340307383505436712)
27 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Documents Site
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/docs/menu.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "menu": "guide",
4 | "type": "markdown"
5 | },
6 | {
7 | "menu": "api",
8 | "type": "markdown"
9 | },
10 | {
11 | "menu": "scenario",
12 | "type": "markdown"
13 | }
14 | ]
15 |
--------------------------------------------------------------------------------
/docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@internal/docs",
3 | "version": "0.0.1",
4 | "description": "site for all VChart",
5 | "private": true,
6 | "scripts": {
7 | "serve": "vite --host",
8 | "watch": "node ./libs/template-parse/build.js --env dev --watch",
9 | "start": "npm run serve",
10 | "_start": "npx concurrently --kill-others \"npm:watch\" \"npm:serve\""
11 | },
12 | "dependencies": {
13 | "@arco-design/web-react": "2.46.1",
14 | "markdown-it": "^13.0.0",
15 | "highlight.js": "^11.8.0",
16 | "axios": "^1.4.0",
17 | "react": "^18.0.0",
18 | "react-dom": "^18.0.0",
19 | "react-router-dom": "6.9.0",
20 | "lodash": "4.17.21",
21 | "@visactor/vutils": "~0.19.3"
22 | },
23 | "devDependencies": {
24 | "@types/react": "^18.0.0",
25 | "@types/react-dom": "^18.0.0",
26 | "@types/markdown-it": "^13.0.0",
27 | "@types/highlightjs": "^9.12.0",
28 | "@vitejs/plugin-react": "3.1.0",
29 | "typescript": "4.9.5",
30 | "vite": "3.2.6",
31 | "marked": "^0.3.19",
32 | "chalk": "^3.0.0",
33 | "fs-extra": "10.1.0",
34 | "yargs": "^17.1.1",
35 | "htmlparser2": "^4.1.0",
36 | "globby": "11.1.0",
37 | "chokidar": "^3.5.0"
38 | }
39 | }
--------------------------------------------------------------------------------
/docs/src/app.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import { RouteObject, RouterProvider, createBrowserRouter, Navigate } from 'react-router-dom';
3 | import { LanguageContext, LanguageEnum, getStoredLanguage, storeLanguage } from './i18n';
4 | import menu from '../menu.json';
5 | import { Markdown } from './markdown';
6 | import { Option } from './option';
7 |
8 | const menuRoutes: RouteObject[] = menu.map(menuItem => {
9 | if (menuItem.type === 'markdown-template') {
10 | return {
11 | path: `/vmind/${menuItem.menu}`,
12 | element: ,
13 | children: [
14 | {
15 | path: '*',
16 | element:
17 | }
18 | ]
19 | };
20 | }
21 | return {
22 | path: `/vmind/${menuItem.menu}`,
23 | element: ,
24 | children: [
25 | {
26 | path: '*',
27 | element:
28 | }
29 | ]
30 | };
31 | });
32 |
33 | const router = createBrowserRouter([
34 | {
35 | path: '/',
36 | element:
37 | },
38 | ...menuRoutes
39 | ]);
40 |
41 | export function App() {
42 | const [language, setLanguage] = useState(getStoredLanguage());
43 | const languageValue = {
44 | language,
45 | setLanguage: (language: LanguageEnum) => {
46 | setLanguage(language);
47 | storeLanguage(language);
48 | }
49 | };
50 | return (
51 |
52 |
53 |
54 | );
55 | }
56 |
--------------------------------------------------------------------------------
/docs/src/i18n.tsx:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 |
3 | export enum LanguageEnum {
4 | chinese = 'zh',
5 | english = 'en'
6 | }
7 |
8 | export const getStoredLanguage = (): LanguageEnum => {
9 | const defaultLanguage = LanguageEnum.chinese;
10 | return (window.localStorage.getItem('language') as LanguageEnum) ?? defaultLanguage;
11 | };
12 |
13 | export const storeLanguage = (language: LanguageEnum) => {
14 | window.localStorage.setItem('language', language);
15 | };
16 |
17 | export const LanguageContext = createContext({
18 | language: LanguageEnum.chinese,
19 | setLanguage: (language: LanguageEnum) => {}
20 | });
21 |
--------------------------------------------------------------------------------
/docs/src/main.tsx:
--------------------------------------------------------------------------------
1 | import ReactDOM from 'react-dom/client';
2 | import { App } from './app';
3 |
4 | import '@arco-design/web-react/dist/css/arco.css';
5 |
6 |
7 | ReactDOM.createRoot(document.getElementById('root')!).render(
8 | //
9 |
10 | //
11 | );
12 |
--------------------------------------------------------------------------------
/docs/src/option/index.css:
--------------------------------------------------------------------------------
1 | .markdown-code {
2 | margin: 0 !important;
3 | }
4 |
5 | .markdown-code pre {
6 | padding: 0 !important;
7 | }
8 |
9 | .markdown-code pre code {
10 | padding: 0 !important;
11 | }
12 |
13 | .markdown-image img {
14 | max-width: min(100%, 800px);
15 | max-height: 800px;
16 | }
17 |
18 | figure {
19 | margin: 0;
20 | }
21 |
22 | code {
23 | background: rgb(242, 243, 245);
24 | padding: 4px 8px;
25 | border-radius: 2px;
26 | }
27 |
28 | pre {
29 | background: rgb(242, 243, 245);
30 | padding: 24px 40px;
31 | border-radius: 2px;
32 | overflow-x: auto;
33 | }
34 |
35 | pre:has(> .live-demo-container) {
36 | padding: 24px 0px;
37 | }
38 |
39 | p {
40 | line-height: 32px;
41 | margin-bottom: 16px;
42 | }
43 |
44 | li {
45 | margin-bottom: 8px;
46 | }
47 |
48 | .option-outline-submenu .arco-menu-inline-header {
49 | line-height: 28px !important;
50 | }
51 |
--------------------------------------------------------------------------------
/docs/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": true,
7 | "skipLibCheck": true,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx"
18 | },
19 | "include": ["src", "assets/demos"],
20 | "references": [
21 | {
22 | "path": "./tsconfig.node.json"
23 | }
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/docs/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "esnext",
5 | "moduleResolution": "node"
6 | },
7 | "include": ["vite.config.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/docs/vite.config.js:
--------------------------------------------------------------------------------
1 | import pkg from '../packages/vmind/package.json';
2 | import * as path from 'path';
3 | import react from '@vitejs/plugin-react';
4 |
5 | export default {
6 | optimizeDeps: {},
7 | server: {
8 | host: '0.0.0.0',
9 | port: 3020,
10 | https: !!process.env.HTTPS,
11 | open: true
12 | },
13 | define: {
14 | __DEV__: true,
15 | __VERSION__: JSON.stringify(pkg.version)
16 | },
17 | resolve: {
18 | alias: {
19 | }
20 | },
21 | plugins: [react()]
22 | };
23 |
--------------------------------------------------------------------------------
/option:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VisActor/VMind/556f979b7b6537b43ee2b886863ca62f419629b7/option
--------------------------------------------------------------------------------
/packages/calculator/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Bytedance Ltd. and/or its affiliates.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/calculator/jest.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const baseJestConfig = require('@internal/jest-config/jest.base');
3 |
4 | module.exports = {
5 | ...baseJestConfig,
6 | moduleNameMapper: {
7 | ...baseJestConfig.moduleNameMapper
8 | }
9 | };
10 |
--------------------------------------------------------------------------------
/packages/calculator/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@visactor/calculator",
3 | "version": "2.0.6",
4 | "description": "SQL-like query executor with DSL",
5 | "main": "lib",
6 | "module": "es",
7 | "types": "es",
8 | "sideEffects": false,
9 | "exports": {
10 | ".": {
11 | "import": "./es/index.js",
12 | "require": "./lib/index.js"
13 | }
14 | },
15 | "files": [
16 | "README.md",
17 | "dist",
18 | "lib",
19 | "es"
20 | ],
21 | "scripts": {
22 | "clean": "rimraf es lib dist build *.tsbuildinfo",
23 | "test": "jest --passWithNoTests",
24 | "test:coverage": "jest --coverage",
25 | "build:esm": "tsc -p tsconfig.esm.json",
26 | "build:cjs": "tsc -p tsconfig.cjs.json",
27 | "build": "npm-run-all clean --parallel build:esm build:cjs"
28 | },
29 | "dependencies": {
30 | "ts-pattern": "~4.1.4",
31 | "node-sql-parser": "~4.17.0",
32 | "@visactor/vutils": "~0.19.3"
33 | },
34 | "devDependencies": {
35 | "@internal/jest-config": "workspace:*",
36 | "@types/jest": "~29.5.0",
37 | "jest": "~29.5.0",
38 | "jest-environment-jsdom": "~29.5.0",
39 | "@jest/globals": "~29.5.0",
40 | "ts-jest": "~29.2.5",
41 | "@typescript-eslint/eslint-plugin": "5.30.0",
42 | "@typescript-eslint/parser": "5.30.0",
43 | "@types/node": "*",
44 | "npm-run-all": "^4.1.5",
45 | "rimraf": "^3.0.2",
46 | "ts-node": "^10.9.2",
47 | "typescript": "4.9.5",
48 | "@internal/ts-config": "workspace:*",
49 | "@internal/eslint-config": "workspace:*",
50 | "@internal/bundler": "workspace:*"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/packages/calculator/src/astParser/index.ts:
--------------------------------------------------------------------------------
1 | import NodeSQLParser from 'node-sql-parser';
2 | import { query } from '../query';
3 | import { SQLAst, SimpleFieldInfo } from './type';
4 | import { Query, TableData } from '../types';
5 | import { parseRespondField, preprocessSQL } from './utils';
6 | import { parseSqlAST } from './parseSqlAST';
7 | import { isArray } from '@visactor/vutils';
8 |
9 | /**
10 | * query the source dataset according to user's input and fieldInfo to get aggregated dataset
11 | *
12 | * @param userInput
13 | * @param fieldInfo
14 | * @param sourceDataset
15 | */
16 | export const queryDataset = async (sql: string, fieldInfo: SimpleFieldInfo[], sourceDataset: TableData) => {
17 | const { validStr, replaceMap } = preprocessSQL(sql, fieldInfo);
18 | const parser = new NodeSQLParser.Parser();
19 |
20 | const ast = parser.astify(validStr);
21 | const queryObject = parseSqlAST((isArray(ast) ? ast[0] : ast) as SQLAst, sourceDataset, fieldInfo, replaceMap);
22 |
23 | const dataset = query(queryObject as Query);
24 |
25 | const fieldInfoNew = parseRespondField(fieldInfo, dataset, replaceMap);
26 | return {
27 | dataset: dataset.length === 0 ? sourceDataset : dataset,
28 | fieldInfo: dataset.length === 0 ? fieldInfo : fieldInfoNew
29 | };
30 | };
31 |
--------------------------------------------------------------------------------
/packages/calculator/src/astParser/parseSqlAST.ts:
--------------------------------------------------------------------------------
1 | import { TableData } from '../types';
2 | import { select, from, groupBy, having, limit, orderBy, where } from './astPipes';
3 | import { ASTParserPipe, SQLAst, SimpleFieldInfo } from './type';
4 | import { execPipeline } from './utils';
5 |
6 | const Pipelines: ASTParserPipe[] = [from, select, where, groupBy, having, orderBy, limit];
7 |
8 | /**
9 | * convert the SQL AST to vizCalculator query CST(Concrete Syntax Tree).
10 | * @param ast AST of the SQL from node-sql-parser
11 | */
12 | export const parseSqlAST = (
13 | ast: SQLAst,
14 | dataSource: TableData,
15 | fieldInfo: SimpleFieldInfo[],
16 | replaceMap: Map
17 | ) => {
18 | const query = execPipeline({}, Pipelines, { ast, dataSource, fieldInfo, replaceMap });
19 | return query;
20 | };
21 |
--------------------------------------------------------------------------------
/packages/calculator/src/astParser/type.ts:
--------------------------------------------------------------------------------
1 | import { Select } from 'node-sql-parser';
2 | import { Query, TableData } from '../types';
3 |
4 | export type SQLAst = Select;
5 | export type ASTParserPipe = (query: Partial, context: ASTParserContext) => Partial;
6 |
7 | export type ASTParserContext = {
8 | ast: SQLAst;
9 | dataSource: TableData;
10 | fieldInfo: SimpleFieldInfo[];
11 | replaceMap: Map;
12 | };
13 |
14 | export type DataQueryResponse = {
15 | THOUGHT?: string;
16 | sql: string;
17 | fieldInfo: { fieldName: string; description?: string }[];
18 | };
19 |
20 | export type SimpleFieldInfo = {
21 | fieldName: string;
22 | description?: string; //additional description of the field. This will help the model have a more comprehensive understanding of this field, improving the quality of chart generation.
23 | type: DataType;
24 | role: ROLE;
25 | };
26 |
27 | export enum DataType {
28 | INT = 'int',
29 | STRING = 'string',
30 | FLOAT = 'float',
31 | DATE = 'date'
32 | }
33 |
34 | export enum ROLE {
35 | DIMENSION = 'dimension',
36 | MEASURE = 'measure'
37 | }
38 |
--------------------------------------------------------------------------------
/packages/calculator/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './types';
2 | export * from './query';
3 | export * from './join';
4 | export { getSelectColumnName, getColumnIdentityName } from './pipes/select';
5 |
6 | export * from './utils/typeCheck';
7 |
--------------------------------------------------------------------------------
/packages/calculator/src/mocks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './table'
2 |
--------------------------------------------------------------------------------
/packages/calculator/src/mocks/table.ts:
--------------------------------------------------------------------------------
1 | import type {
2 | TableData,
3 | } from '../types'
4 |
5 | export const mockSimpleTable: TableData = [
6 | { name: 'Alice', subject: 'Sword', score: 100, age: 11 },
7 | { name: 'Eugeo', subject: 'Sword', score: 100, age: 11 },
8 | { name: 'Kirito', subject: 'Sword', score: 200, age: 17 },
9 | { name: 'Fanatio', subject: 'Sword', score: 100, age: 20 },
10 | { name: 'Cardinal', subject: 'System', score: 500, age: 200 },
11 | { name: 'Admin', subject: 'System', score: 1000, age: 300 },
12 | ]
13 |
--------------------------------------------------------------------------------
/packages/calculator/src/pipe.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * `source --> pipeline --> result`
3 | *
4 | * That's what this does:
5 | *
6 | * ```
7 | * of(source).pipe(pipe1, pipe2, pipe3, ...)
8 | * = pipe3(pipe2(pipe1(source)))
9 | * ```
10 | */
11 | export const of = (source: Source): {
12 | pipe: (
13 | ...funcs: Funcs['length'] extends 0
14 | ? []
15 | : Funcs extends [(arg: Source) => any, ...AnyFunc[]]
16 | ? PipeFuncs extends Funcs ? Funcs : PipeFuncs
17 | : [(arg: Source) => any, ...AnyFunc[]]
18 | ) => LastReturnType
19 | } => ({
20 | pipe: (...funcs: AnyFunc[]) => funcs.reduce((arg, fn) => fn(arg), source as any)
21 | })
22 |
23 | type AnyFunc = (...args: any) => any
24 |
25 | type LastReturnType =
26 | F extends [...any, (...arg: any) => infer R]
27 | ? R
28 | : Else
29 |
30 | type PipeFuncs =
31 | F['length'] extends 1
32 | ? [...Acc, ...F]
33 | : F extends [(...args: infer A) => infer B, (...args: any) => infer D, ...infer Tails]
34 | ? Tails extends AnyFunc[]
35 | ? PipeFuncs<[(arg: B) => D, ...Tails], [...Acc, (...args: A) => B]>
36 | : never
37 | : Acc
38 |
--------------------------------------------------------------------------------
/packages/calculator/src/pipes/aggregate/index.ts:
--------------------------------------------------------------------------------
1 | export * from './aggregate'
2 |
--------------------------------------------------------------------------------
/packages/calculator/src/pipes/filter/having.ts:
--------------------------------------------------------------------------------
1 | import type {
2 | TableData,
3 | GroupedData,
4 | FilterNode,
5 | HavingCondition,
6 | } from '../../types'
7 | import {
8 | evaluateGroupColumnValue,
9 | } from '../select'
10 | import { judgeFilterTree } from './filter'
11 |
12 | export type HavingPipe = (params: {
13 | filter?: FilterNode;
14 | source: TableData;
15 | }) => (
16 | (grouped: GroupedData) => GroupedData
17 | )
18 |
19 | export const having: HavingPipe = ({ filter, source }: {
20 | filter?: FilterNode;
21 | source: TableData;
22 | }): ((grouped: GroupedData) => GroupedData) => {
23 | if (!filter?.conditions.length) return (grouped) => grouped
24 |
25 | return (grouped) => grouped.filter(group => {
26 | return judgeFilterTree({
27 | filterNode: filter,
28 | item: group,
29 | getValue: ({ item, condition }) => evaluateGroupColumnValue({
30 | group: item,
31 | source,
32 | column: condition,
33 | }),
34 | })
35 | })
36 | }
37 |
--------------------------------------------------------------------------------
/packages/calculator/src/pipes/filter/index.ts:
--------------------------------------------------------------------------------
1 | export * from './where'
2 | export * from './having'
3 |
--------------------------------------------------------------------------------
/packages/calculator/src/pipes/filter/where.ts:
--------------------------------------------------------------------------------
1 | import type {
2 | TableData,
3 | FilterNode,
4 | WhereCondition,
5 | } from '../../types'
6 | import { judgeFilterTree } from './filter'
7 | import {
8 | evaluateRowColumnValue,
9 | } from '../select'
10 |
11 |
12 | export type WherePipe = (params: {
13 | filter?: FilterNode;
14 | source: TableData;
15 | }) => (
16 | (tableData: TableData) => TableData
17 | )
18 |
19 | export const where: WherePipe = ({ filter, source }: {
20 | filter?: FilterNode;
21 | source: TableData;
22 | }): ((tableData: TableData) => TableData) => {
23 | if (!filter?.conditions.length) return (tableData) => tableData
24 |
25 | return (tableData) => tableData.filter(row => {
26 | return judgeFilterTree({
27 | filterNode: filter,
28 | item: row,
29 | getValue: ({ item, condition }) => evaluateRowColumnValue({
30 | row: item,
31 | source,
32 | column: condition
33 | }),
34 | })
35 | })
36 | }
37 |
--------------------------------------------------------------------------------
/packages/calculator/src/pipes/index.ts:
--------------------------------------------------------------------------------
1 | import { where, having } from './filter'
2 | import { group, buildGroupsMap } from './group'
3 | import { order, orderGroup } from './order'
4 | import { select, selectGroup } from './select'
5 | import { distinct } from './distinct'
6 | import { limit } from './limit'
7 |
8 | export {
9 | where,
10 | having,
11 | group,
12 | buildGroupsMap,
13 | order,
14 | orderGroup,
15 | select,
16 | selectGroup,
17 | distinct,
18 | limit,
19 | }
20 |
--------------------------------------------------------------------------------
/packages/calculator/src/pipes/limit.ts:
--------------------------------------------------------------------------------
1 | import type { TableData } from '../types'
2 |
3 | export type LimitPipe = (params: { limit?: number }) => (
4 | (tableData: TableData) => TableData
5 | )
6 |
7 | export const limit: LimitPipe = ({ limit: limitSize }) => {
8 | return (tableData) => {
9 | if (
10 | limitSize === undefined
11 | || limitSize < 1
12 | ) {
13 | return tableData
14 | }
15 |
16 | return tableData.slice(0, limitSize)
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/calculator/src/query.test.ts:
--------------------------------------------------------------------------------
1 | import {
2 | OrderType,
3 | AggregateType,
4 | } from './types'
5 | import { query } from './query'
6 | import { mockSimpleTable } from './mocks'
7 |
8 |
9 | test('query with empty data', () => {
10 | const result = query({
11 | from: [],
12 | select: {
13 | columns: [{ column: 'subject' }],
14 | },
15 | limit: 10,
16 | })
17 |
18 | expect(result).toEqual([])
19 | })
20 |
21 |
22 | test('query with simple select', () => {
23 | const result = query({
24 | from: mockSimpleTable,
25 | select: {
26 | columns: [{ column: 'subject' }],
27 | },
28 | orderBy: [{ column: 'score', type: OrderType.Desc }],
29 | limit: 3,
30 | })
31 |
32 | expect(result).toEqual([
33 | { subject: 'System' },
34 | { subject: 'System' },
35 | { subject: 'Sword' },
36 | ])
37 | })
38 |
39 | test('query with only select aggregate', () => {
40 | const result = query({
41 | from: mockSimpleTable,
42 | select: {
43 | columns: [
44 | { column: 'subject' },
45 | { column: 'subject', aggregate: { method: AggregateType.Count } },
46 | {
47 | column: 'subject',
48 | aggregate: { method: AggregateType.Count, distinct: true },
49 | },
50 | ],
51 | },
52 | limit: 3,
53 | })
54 |
55 | expect(result).toEqual([{
56 | subject: 'Sword',
57 | 'Count(subject)': 6,
58 | 'Count(distinct subject)': 2,
59 | }])
60 | })
61 |
62 |
--------------------------------------------------------------------------------
/packages/calculator/src/types/aggregate.ts:
--------------------------------------------------------------------------------
1 | import type { ColumnName, Value } from './data'
2 |
3 | /**
4 | * Simple aggregation methods
5 | */
6 | export enum AggregateType {
7 | Count = 'Count',
8 | Max = 'Max',
9 | Min = 'Min',
10 | Sum = 'Sum',
11 | Avg = 'Avg',
12 | }
13 |
14 | /**
15 | * Aggregation method provided by the user
16 | */
17 | export type AggregateMethod = {
18 | (params: {
19 | /** Column name to be aggregated, used as metadata */
20 | column: ColumnName;
21 | /** Extracted data for the column */
22 | values: Value[];
23 | }): Value;
24 |
25 | /**
26 | * Custom function name, must not be empty (non-anonymous function)
27 | * Used for calculating cache key and generating default column name after aggregation
28 | */
29 | name: string;
30 | }
31 |
32 | /**
33 | * Aggregation configuration
34 | */
35 | export interface Aggregation {
36 | /**
37 | * Whether to remove duplicates, executed before the aggregation method,
38 | * e.g. `count(distinct )`, `avg(distinct )`
39 | */
40 | distinct?: boolean;
41 | method: AggregateType | AggregateMethod;
42 | }
43 |
44 | /**
45 | * Cache for the calculation results of different aggregation functions in each group
46 | * The mapping at each level is as follows:
47 | * Column name -> (Whether to remove duplicates -> (Aggregation function -> Aggregated value))
48 | */
49 | export type AggregationMap = Record<
50 | ColumnName,
51 | WhetherDistinctCache
52 | >
53 |
54 | export type WhetherDistinctCache = {
55 | distinct?: AggregationCache;
56 | all?: AggregationCache;
57 | }
58 |
59 | export type AggregationCache = Map<
60 | AggregateType | AggregateMethod['name'],
61 | Value
62 | >
63 |
--------------------------------------------------------------------------------
/packages/calculator/src/types/data.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Input for the entire query calculation process, represented as a one-dimensional array of objects.
3 | * Each object represents a row, with each key representing a column name.
4 | */
5 | export type TableData = Row[]
6 | export type Row = { [column: ColumnName]: Value }
7 | export type ColumnName = string
8 | /**
9 | * The data value type only supports the format `string | number | null`.
10 | *
11 | * - The value format and validity will not be validated internally.
12 | * - `boolean` values are not supported.
13 | * - Date types are converted to the ISO 8601 basic format string `YYYY-MM-DD`, which is equivalent to string calculations.
14 | * - It is intended for static data / HTTP API / JavaScript-generated data,
15 | * therefore it does not support infinite precision number types, and does not support high-precision numbers stored as `string` for calculations.
16 | * - According to the SQL equivalent format, values cannot be `undefined`, i.e., there should be no missing field values,
17 | * and empty fields should be filled with `null`.
18 | */
19 | export type Value = string | number | null
20 |
--------------------------------------------------------------------------------
/packages/calculator/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export * from './data'
2 | export * from './join'
3 | export * from './query'
4 | export * from './filter'
5 | export * from './group'
6 | export * from './aggregate'
7 | export * from './select'
8 |
--------------------------------------------------------------------------------
/packages/calculator/src/types/join.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * direction of `join` operation
3 | * - The `Full` type is not currently used in the current scenario, so it is not implemented yet.
4 | */
5 | export enum JoinType {
6 | Left = 'Left',
7 | Right = 'Right',
8 | Inner = 'Inner',
9 | Cross = 'Cross',
10 | // Full = 'Full'
11 | }
12 |
--------------------------------------------------------------------------------
/packages/calculator/src/utils/includes.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * The `includes` method that includes type conversion for comparing `numbers`/`strings`.
3 | */
4 | export const includes = (array: (string | number)[], value: string | number) => (
5 | array.some(item => item == value)
6 | )
7 |
--------------------------------------------------------------------------------
/packages/calculator/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './ordered';
2 | export * from './includes';
3 | export * from './typeCheck';
4 |
--------------------------------------------------------------------------------
/packages/calculator/src/utils/typeCheck.ts:
--------------------------------------------------------------------------------
1 | import { isNumber } from '@visactor/vutils';
2 |
3 | export function isInteger(value: any) {
4 | return typeof value == 'number' && Number.isInteger(value);
5 | }
6 |
7 | export function isNaN(value: any) {
8 | // An `NaN` primitive is the only value that is not equal to itself.
9 | // Perform the `toStringTag` check first to avoid errors with some
10 | // ActiveX objects in IE.
11 | return isNumber(value) && value != +value;
12 | }
13 |
--------------------------------------------------------------------------------
/packages/calculator/tsconfig.cjs.json:
--------------------------------------------------------------------------------
1 | /**
2 | * NOTE: this file is symlink to '@aeolian/dev-config/tsconfig/build.cjs.json'
3 | */
4 | {
5 | "extends": "./tsconfig.json",
6 | "compilerOptions": {
7 | "outDir": "lib",
8 | "target": "es2018",
9 | "module": "CommonJS",
10 | "noEmit": false,
11 | "sourceMap": false,
12 | },
13 | "exclude": [
14 | "**/*.test.ts",
15 | "**/*.test.tsx",
16 | "**/*.stories.tsx",
17 | "**/*.mock.ts",
18 | "**/tests",
19 | "**/mocks",
20 | ],
21 | }
22 |
--------------------------------------------------------------------------------
/packages/calculator/tsconfig.esm.json:
--------------------------------------------------------------------------------
1 | /**
2 | * NOTE: this file is symlink to '@aeolian/dev-config/tsconfig/build.esm.json'
3 | */
4 | {
5 | "extends": "./tsconfig.json",
6 | "compilerOptions": {
7 | "outDir": "es",
8 | "target": "es2018",
9 | "module": "ESNext",
10 | "noEmit": false,
11 | "sourceMap": false,
12 | },
13 | "exclude": [
14 | "**/*.test.ts",
15 | "**/*.test.tsx",
16 | "**/*.stories.tsx",
17 | "**/*.mock.ts",
18 | "**/tests",
19 | "**/mocks",
20 | ],
21 | }
22 |
--------------------------------------------------------------------------------
/packages/calculator/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@internal/ts-config/tsconfig.base.json",
3 | "compilerOptions": {
4 | "declaration": true, //Generates corresponding d.ts files.
5 | "composite": true,
6 | "baseUrl": ".",
7 | "rootDir": "src",
8 | "outDir": "es",
9 | "types": [
10 | "node",
11 | "jest",
12 | ],
13 | },
14 | "include": [
15 | "src",
16 | ],
17 | // https://www.typescriptlang.org/docs/handbook/project-references.html#what-is-a-project-reference
18 | "references": [
19 | ],
20 | }
21 |
--------------------------------------------------------------------------------
/packages/calculator/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "paths": {
5 | }
6 | },
7 | "references": []
8 | }
9 |
--------------------------------------------------------------------------------
/packages/chart-advisor/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | require('@rushstack/eslint-patch/modern-module-resolution');
2 |
3 | module.exports = {
4 | extends: ['@internal/eslint-config/profile/react'],
5 | parserOptions: { tsconfigRootDir: __dirname, project: './tsconfig.eslint.json' },
6 | // ignorePatterns: [],
7 | env: {
8 | browser: true,
9 | es2021: true,
10 | node: true,
11 | jest: true
12 | },
13 | rules: {
14 | '@typescript-eslint/no-unused-vars': 'warn',
15 | 'react/display-name': 'off',
16 | 'no-console': 'warn'
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/packages/chart-advisor/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Bytedance Ltd. and/or its affiliates.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/chart-advisor/__tests__/Q1.test.ts:
--------------------------------------------------------------------------------
1 | //import { calQuantile } from '../dataUtil';
2 |
3 | //test('should be true', () => {
4 | // const mock1 = [0, 679042241.42, 1084634383.2, 485539225.08];
5 |
6 | // const Q11 = calQuantile({ data: mock1 }, 0.25);
7 | // expect(Q11).toBe(582290733.25);
8 |
9 | // const mock2 = [null, 0.02, 0.14, 0.02];
10 | // const Q12 = calQuantile({ data: mock2 }, 0.25);
11 | // expect(Q12).toBe(0.02);
12 | //});
13 | describe('Q1', () => {
14 | it('should be correct', () => {
15 | expect(1).toEqual(1);
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/packages/chart-advisor/__tests__/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "include": ["."]
4 | }
--------------------------------------------------------------------------------
/packages/chart-advisor/exampleChart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VisActor/VMind/556f979b7b6537b43ee2b886863ca62f419629b7/packages/chart-advisor/exampleChart.png
--------------------------------------------------------------------------------
/packages/chart-advisor/jest.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const baseJestConfig = require('@internal/jest-config/jest.base');
3 |
4 | module.exports = {
5 | ...baseJestConfig,
6 | moduleNameMapper: {
7 | ...baseJestConfig.moduleNameMapper
8 | }
9 | };
10 |
--------------------------------------------------------------------------------
/packages/chart-advisor/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@visactor/chart-advisor",
3 | "version": "2.0.6",
4 | "description": "图表推荐模块",
5 | "main": "lib",
6 | "module": "es",
7 | "types": "es",
8 | "sideEffects": false,
9 | "exports": {
10 | ".": {
11 | "import": "./es/index.js",
12 | "require": "./lib/index.js"
13 | }
14 | },
15 | "files": [
16 | "README.md",
17 | "lib",
18 | "es",
19 | "build"
20 | ],
21 | "scripts": {
22 | "clean": "rimraf es lib dist build *.tsbuildinfo",
23 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
24 | "test": "jest --passWithNoTests",
25 | "test:coverage": "jest --coverage",
26 | "build:esm": "tsc -p tsconfig.esm.json",
27 | "build:cjs": "tsc -p tsconfig.cjs.json",
28 | "build": "npm-run-all clean --parallel build:esm build:cjs"
29 | },
30 | "author": "",
31 | "license": "MIT",
32 | "dependencies": {
33 | "@visactor/vutils": "~0.19.3"
34 | },
35 | "devDependencies": {
36 | "@internal/jest-config": "workspace:*",
37 | "@types/jest": "~29.5.0",
38 | "jest": "~29.5.0",
39 | "jest-environment-jsdom": "~29.5.0",
40 | "@jest/globals": "~29.5.0",
41 | "ts-jest": "~29.2.5",
42 | "@types/node": "*",
43 | "typescript": "4.9.5",
44 | "undici-types": "^5.27.2",
45 | "@typescript-eslint/eslint-plugin": "5.30.0",
46 | "@typescript-eslint/parser": "5.30.0",
47 | "npm-run-all": "^4.1.5",
48 | "rimraf": "^3.0.2",
49 | "@internal/ts-config": "workspace:*",
50 | "@internal/eslint-config": "workspace:*",
51 | "@internal/bundler": "workspace:*",
52 | "@rushstack/eslint-patch": "~1.1.4"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/packages/chart-advisor/src/constant.ts:
--------------------------------------------------------------------------------
1 | import { UniqueId } from './type';
2 | //后端传来的平坦化数据集中,和前端的设置不一致
3 | export const FOLD_NAME: UniqueId = 10001;
4 | export const FOLD_VALUE: UniqueId = 10002;
5 | export const FOLD_VALUE_MAIN: UniqueId = 10011;
6 | export const FOLD_VALUE_SUB: UniqueId = 10012;
7 |
8 | export const COLOR_FIELD: UniqueId = 20001;
9 | export const GROUP_FIELD: UniqueId = 30001;
10 |
11 | // export const MAX_PIVOT_ROW: number = 0 //允许的最大透视行数
12 | // export const MAX_PIVOT_COLUMN: number = 0 //允许的最大透视列数
13 |
14 | // X轴刻度数
15 | export const X_MAX_COUNT = 5000;
16 | // 数据点数
17 | export const MAX_POINT_COUNT = 100000;
18 | // 图例个数
19 | export const LEGEND_MAX_COUNT = 1000;
20 | // 图例个数超过时数据点的限制
21 | export const LEGEND_MAX_POINT_COUNT = 200;
22 |
23 | export const MIN_BAR_NUMBER = 2;
24 | export const MAX_BAR_NUMBER = 30;
25 |
26 | export const APPLY_PIVOT = false; //透视开关
27 |
--------------------------------------------------------------------------------
/packages/chart-advisor/tsconfig.cjs.json:
--------------------------------------------------------------------------------
1 | /**
2 | * NOTE: this file is symlink to '@aeolian/dev-config/tsconfig/build.cjs.json'
3 | */
4 | {
5 | "extends": "./tsconfig.json",
6 | "compilerOptions": {
7 | "outDir": "lib",
8 | "target": "es2018",
9 | "module": "CommonJS",
10 | "noEmit": false,
11 | "sourceMap": false,
12 | },
13 | "exclude": [
14 | "**/*.test.ts",
15 | "**/*.test.tsx",
16 | "**/*.stories.tsx",
17 | "**/*.mock.ts",
18 | "**/tests",
19 | "**/mocks",
20 | ],
21 | }
22 |
--------------------------------------------------------------------------------
/packages/chart-advisor/tsconfig.eslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@internal/ts-config/tsconfig.base.json",
3 | "compilerOptions": {
4 | "types": ["jest", "node"],
5 | "lib": ["DOM", "ESNext"],
6 | "baseUrl": "./",
7 | "rootDir": "./"
8 | },
9 | "include": ["src", "__tests__"]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/chart-advisor/tsconfig.esm.json:
--------------------------------------------------------------------------------
1 | /**
2 | * NOTE: this file is symlink to '@aeolian/dev-config/tsconfig/build.esm.json'
3 | */
4 | {
5 | "extends": "./tsconfig.json",
6 | "compilerOptions": {
7 | "outDir": "es",
8 | "target": "es2018",
9 | "module": "ESNext",
10 | "noEmit": false,
11 | "sourceMap": false,
12 | "noImplicitAny": false
13 | },
14 | "exclude": [
15 | "**/*.test.ts",
16 | "**/*.test.tsx",
17 | "**/*.stories.tsx",
18 | "**/*.mock.ts",
19 | "**/tests",
20 | "**/mocks",
21 | ],
22 | }
23 |
--------------------------------------------------------------------------------
/packages/chart-advisor/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@internal/ts-config/tsconfig.base.json",
3 | "compilerOptions": {
4 | "declaration": true, //Generates corresponding d.ts files.
5 | "composite": true,
6 | "baseUrl": ".",
7 | "rootDir": "src",
8 | "outDir": "es",
9 | "types": [
10 | "node",
11 | "jest",
12 | ],
13 | "noImplicitAny": false
14 | },
15 | "include": [
16 | "src",
17 | ],
18 | // https://www.typescriptlang.org/docs/handbook/project-references.html#what-is-a-project-reference
19 | "references": [
20 | ],
21 | }
22 |
--------------------------------------------------------------------------------
/packages/chart-advisor/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "paths": {
5 | }
6 | },
7 | "references": []
8 | }
9 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/browser/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | VMind
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/browser/src/App.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { Home } from './pages/Home';
3 | import { LayoutWrap } from './Layout';
4 | import './index.scss';
5 |
6 | export default function App() {
7 | return (
8 |
9 |
10 |
11 | );
12 | }
13 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/browser/src/Layout.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { PageHeader, Button, Layout } from '@arco-design/web-react';
3 |
4 | export function LayoutWrap(props: any) {
5 | return (
6 |
7 |
12 | {props.children}
13 |
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/browser/src/index.scss:
--------------------------------------------------------------------------------
1 | #root {
2 | height: 100vh;
3 | }
4 |
5 | .flex-text-area {
6 | display: flex;
7 | flex: 1;
8 | flex-direction: column;
9 |
10 | textarea {
11 | flex: 1;
12 | }
13 | }
14 |
15 | .flex-1 {
16 | flex: 1;
17 | }
--------------------------------------------------------------------------------
/packages/vmind/__tests__/browser/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import App from './App';
4 | import '@arco-design/web-react/dist/css/arco.min.css';
5 |
6 | ReactDOM.createRoot(document.getElementById('root')!).render(
7 |
8 |
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/browser/src/pages/ChartGeneration/ChartGeneration.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { Layout } from '@arco-design/web-react';
3 | import { DataInput } from './DataInput';
4 | import { ChartPreview } from './ChartPreview';
5 | const Sider = Layout.Sider;
6 | const Content = Layout.Content;
7 |
8 | export function ChartGenerationPage() {
9 | const [spec, setSpec] = useState('');
10 | const [specList, setSpecList] = useState([]);
11 |
12 | const [time, setTime] = useState<{
13 | totalTime: number;
14 | frameArr: any[];
15 | }>();
16 | const [costTime, setCostTime] = useState(0);
17 | return (
18 |
19 |
25 | {
27 | setSpec(spec);
28 | setSpecList([]);
29 | setTime(time);
30 | setCostTime(costTime);
31 | }}
32 | onSpecListGenerate={(specList: any[], time: any, costTime: number) => {
33 | setSpec(undefined);
34 | setSpecList(specList);
35 | setTime(time);
36 | setCostTime(costTime);
37 | }}
38 | />
39 |
40 |
41 |
42 |
43 |
44 | );
45 | }
46 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/browser/src/pages/Home.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Layout, Menu } from '@arco-design/web-react';
3 | import { CollapseCSS, PLAYGROUND_MENU_INFO, PLAYGROUND_PAGES } from './constants';
4 | const Sider = Layout.Sider;
5 | const Content = Layout.Content;
6 | const MenuItem = Menu.Item;
7 |
8 | const LOCAL_STORAGE_MENU_KEY = 'VMind_playground_menu_key';
9 | export const Home: React.FC = props => {
10 | const [selectedPage, setSelectedPage] = React.useState(PLAYGROUND_PAGES.CHART_GENERATION);
11 | const [collapsed, setCollapsed] = React.useState(true);
12 | return (
13 |
14 | {
18 | type === 'clickTrigger' && setCollapsed(v);
19 | }}
20 | breakpoint="xl"
21 | collapsible
22 | >
23 |
41 |
42 | {PLAYGROUND_MENU_INFO[selectedPage].component}
43 |
44 | );
45 | };
46 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/browser/src/pages/Insight/Insight.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { Layout } from '@arco-design/web-react';
3 | import { DataInput } from './DataInput';
4 | import { ChartPreview } from './ChartPreview';
5 | const Sider = Layout.Sider;
6 | const Content = Layout.Content;
7 |
8 | export function InsightPage() {
9 | const [spec, setSpec] = useState('');
10 | const [insights, setInsights] = useState([]);
11 |
12 | const [costTime, setCostTime] = useState(0);
13 | return (
14 |
15 |
21 | {
23 | setSpec(spec);
24 | setInsights(insights);
25 | setCostTime(costTime);
26 | }}
27 | onSpecChange={(spec: any) => {
28 | setSpec(spec);
29 | }}
30 | />
31 |
32 |
33 |
34 |
35 |
36 | );
37 | }
38 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/browser/src/pages/NewChartGeneration/ChartGeneration.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { Layout } from '@arco-design/web-react';
3 | import { DataInput } from './DataInput';
4 | import { ChartPreview } from './ChartPreview';
5 | const Sider = Layout.Sider;
6 | const Content = Layout.Content;
7 |
8 | export function NewChartGenerationPage() {
9 | const [spec, setSpec] = useState('');
10 | const [command, setCommand] = useState('');
11 | const [specList, setSpecList] = useState([]);
12 |
13 | const [costTime, setCostTime] = useState(0);
14 | return (
15 |
16 |
22 | {
24 | setSpec(spec);
25 | setCommand(desc);
26 | setSpecList([]);
27 | setCostTime(costTime);
28 | }}
29 | />
30 |
31 |
32 |
33 |
34 |
35 | );
36 | }
37 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/browser/src/pages/index.scss:
--------------------------------------------------------------------------------
1 | .left-sider {
2 | padding: 10px 12px;
3 | height: 100%;
4 | box-sizing: border-box;
5 | display: flex;
6 | flex-direction: column;
7 | align-items: center;
8 | overflow-y: auto;
9 | .generate-botton {
10 | //margin-top: auto;
11 | }
12 | }
13 |
14 | .right-chart {
15 | padding: 20px;
16 | height: 100%;
17 | display: flex;
18 | flex-direction: column;
19 | box-sizing: border-box;
20 | .right-chart-title{
21 | height: 60px;
22 | display: flex;
23 | flex-direction: row;
24 | justify-content: flex-end;
25 | }
26 | }
27 |
28 | .arco-spin-children {
29 | display: flex;
30 | flex: 1;
31 | }
32 | .arco-modal {
33 | width: unset;
34 | }
35 | .arco-layout-has-sider {
36 | height: 100%;
37 | }
38 |
39 | .disabled-row {
40 | opacity: 0.5;
41 | cursor: not-allowed;
42 | }
--------------------------------------------------------------------------------
/packages/vmind/__tests__/browser/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true
8 | },
9 | "include": ["vite.config.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/experiment/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | VMind
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/experiment/src/App.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { Home } from './pages/Home';
3 | import { LayoutWrap } from './Layout';
4 |
5 | export default function App() {
6 | return (
7 |
8 |
9 |
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/experiment/src/Layout.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { PageHeader, Button, Layout } from '@arco-design/web-react';
3 |
4 | export function LayoutWrap(props: any) {
5 | return (
6 |
7 |
12 | {props.children}
13 |
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/experiment/src/index.scss:
--------------------------------------------------------------------------------
1 | #root {
2 | display: flex;
3 | height: 100vh;
4 | }
5 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/experiment/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import App from './App';
4 | import '@arco-design/web-react/dist/css/arco.min.css';
5 | import './index.scss';
6 |
7 | ReactDOM.createRoot(document.getElementById('root')!).render(
8 |
9 |
10 |
11 | );
12 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/experiment/src/pages/ChartDialogueQA/color.scss:
--------------------------------------------------------------------------------
1 | .color-bar {
2 | display: flex;
3 | flex-wrap: wrap;
4 | flex-direction: row;
5 | div {
6 | width: 20px;
7 | height: 20px;
8 | margin: 1px;
9 | }
10 | }
--------------------------------------------------------------------------------
/packages/vmind/__tests__/experiment/src/pages/ChartDialogueQA/logo.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import type { CSSProperties } from 'react';
3 |
4 | interface IProps {
5 | style?: CSSProperties;
6 | className?: string;
7 | color?: string;
8 | [foo: string]: any;
9 | }
10 |
11 | export const Logo = (props: IProps) => {
12 | return (
13 |
22 | );
23 | };
24 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/experiment/src/pages/ChartGenerator/type.tsx:
--------------------------------------------------------------------------------
1 | import type { DataTable, FieldInfo, Model } from '../../../../../src';
2 |
3 | export interface ChartGeneratorCase {
4 | dataset: string;
5 | model: Model;
6 | type: 'default' | 'fieldInfo';
7 | context: {
8 | dataTable: DataTable;
9 | fieldInfo: FieldInfo[];
10 | datasets: any[];
11 | text: string;
12 | };
13 | command?: string;
14 | spec?: any;
15 | chartRes?: {
16 | context: {
17 | dataTable: DataTable;
18 | fieldInfo: FieldInfo[];
19 | spec: any;
20 | command: string;
21 | };
22 | textRange: [string, string];
23 | }[];
24 | timeCost: number;
25 | extractionCost: number;
26 | generationCost: number;
27 | }
28 |
29 | export type ChartGeneratorResult = ChartGeneratorCase[];
30 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/experiment/src/pages/DataExtraction/type.tsx:
--------------------------------------------------------------------------------
1 | import type { DataTable, FieldInfo } from '../../../../../src';
2 |
3 | export interface ScoreDetail {
4 | originIndex: number;
5 | matchedIndex: number;
6 | nameScore: number;
7 | typeScore: number;
8 | dataScore: number;
9 | }
10 |
11 | export interface DataExtractionDataSetResult {
12 | context: {
13 | isEnglish?: boolean;
14 | dataTable: DataTable;
15 | fieldInfo: FieldInfo[];
16 | text: string;
17 | datasets?: any[];
18 | };
19 | dataClean?: {
20 | dataTable: DataTable;
21 | fieldInfo: FieldInfo[];
22 | text: string;
23 | datasets?: any[];
24 | score?: number;
25 | fieldScore?: number;
26 | dataScore?: number;
27 | scoreDetail?: ScoreDetail[];
28 | };
29 | timeCost?: string;
30 | score?: number;
31 | fieldScore?: number;
32 | dataScore?: number;
33 | scoreDetail?: ScoreDetail[];
34 | }
35 | export interface DataExtractionCase {
36 | llm: string;
37 | result: {
38 | dataset: string;
39 | defaultResult: DataExtractionDataSetResult[];
40 | fieldInfoResult: DataExtractionDataSetResult[];
41 | }[];
42 | }
43 |
44 | export type DataExtractionResult = DataExtractionCase[];
45 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/experiment/src/pages/page.scss:
--------------------------------------------------------------------------------
1 | .case-container {
2 | display: flex;
3 | padding: 16px;
4 | flex-direction: column;
5 | height: 100%;
6 | overflow: hidden;
7 |
8 | .sub-title {
9 | font-size: 16px;
10 | margin-bottom: 4px;
11 | }
12 | .compare {
13 | flex: 1;
14 | width: 100%;
15 | display: flex;
16 | flex-direction: column;
17 | overflow: auto;
18 |
19 | .title {
20 | display: flex;
21 | min-height:30px;
22 | width: 100%;
23 | border-bottom: 1px #efefef solid;
24 | text-align: center;
25 | }
26 |
27 | .result {
28 | display: flex;
29 | flex: 1;
30 | overflow: auto;
31 | padding-right: 8px;
32 | }
33 | .one-result {
34 | overflow: visible;
35 |
36 | .result-container {
37 | padding: 4px 12px;
38 | border-right: 1px #efefef solid;
39 | }
40 | .one-card {
41 | height: 400px;
42 | margin: 8px 0;
43 | overflow: auto;
44 | }
45 | .column-title {
46 | display: flex;
47 | align-items: center;
48 | span {
49 | overflow: hidden;
50 | text-overflow: ellipsis;
51 | }
52 |
53 | svg {
54 | flex-shrink: 0;
55 | }
56 |
57 | &:hover {
58 | cursor: pointer;
59 | }
60 | }
61 | }
62 | }
63 |
64 | .row-flex {
65 | display: flex;
66 | align-items: center;
67 |
68 | p {
69 | flex-shrink: 0;
70 | }
71 |
72 | .arco-select {
73 | width: 200px;
74 | margin: 0 12px;
75 | }
76 | }
77 |
78 | .arco-tabs-content {
79 | overflow: auto;
80 | height: 100%;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/experiment/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true
8 | },
9 | "include": ["vite.config.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/area-basis.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'area',
3 | data: {
4 | values: [
5 | {
6 | time: '2:00',
7 | value: 8
8 | },
9 | {
10 | time: '4:00',
11 | value: 9
12 | },
13 | {
14 | time: '6:00',
15 | value: 11
16 | },
17 | {
18 | time: '8:00',
19 | value: 14
20 | },
21 | {
22 | time: '10:00',
23 | value: 16
24 | },
25 | {
26 | time: '12:00',
27 | value: 17
28 | },
29 | {
30 | time: '14:00',
31 | value: 17
32 | },
33 | {
34 | time: '16:00',
35 | value: 16
36 | },
37 | {
38 | time: '18:00',
39 | value: 15
40 | }
41 | ]
42 | },
43 | xField: 'time',
44 | yField: 'value'
45 | };
46 |
47 | export { spec };
48 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/bar-basic.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'bar',
3 | data: [
4 | {
5 | id: 'barData',
6 | values: [
7 | { month: 'Monday', sales: 22 },
8 | { month: 'Tuesday', sales: 13 },
9 | { month: 'Wednesday', sales: 25 },
10 | { month: 'Thursday', sales: 29 },
11 | { month: 'Friday', sales: 38 }
12 | ]
13 | }
14 | ],
15 | xField: 'month',
16 | yField: 'sales'
17 | };
18 |
19 | export { spec };
20 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/bar-group.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'bar',
3 | data: [
4 | {
5 | id: 'barData',
6 | values: [
7 | { type: 'Autocracies', year: '1930', value: 129 },
8 | { type: 'Autocracies', year: '1940', value: 133 },
9 | { type: 'Autocracies', year: '1950', value: 130 },
10 | { type: 'Autocracies', year: '1960', value: 126 },
11 | { type: 'Autocracies', year: '1970', value: 117 },
12 | { type: 'Autocracies', year: '1980', value: 114 },
13 | { type: 'Autocracies', year: '1990', value: 111 },
14 | { type: 'Autocracies', year: '2000', value: 89 },
15 | { type: 'Autocracies', year: '2010', value: 80 },
16 | { type: 'Autocracies', year: '2018', value: 80 },
17 | { type: 'Democracies', year: '1930', value: 22 },
18 | { type: 'Democracies', year: '1940', value: 13 },
19 | { type: 'Democracies', year: '1950', value: 25 },
20 | { type: 'Democracies', year: '1960', value: 29 },
21 | { type: 'Democracies', year: '1970', value: 38 },
22 | { type: 'Democracies', year: '1980', value: 41 },
23 | { type: 'Democracies', year: '1990', value: 57 },
24 | { type: 'Democracies', year: '2000', value: 87 },
25 | { type: 'Democracies', year: '2010', value: 98 },
26 | { type: 'Democracies', year: '2018', value: 99 }
27 | ]
28 | }
29 | ],
30 | xField: ['year', 'type'],
31 | yField: 'value',
32 | seriesField: 'type',
33 | legends: {
34 | visible: true,
35 | orient: 'top',
36 | position: 'start'
37 | }
38 | };
39 |
40 | export { spec };
41 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/bar-h-stack.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'bar',
3 | height: 300,
4 | data: [
5 | {
6 | id: 'barData',
7 | values: [
8 | { type: 'A', year: '2000', value: 16727 },
9 | { type: 'B', year: '2000', value: 12546 },
10 | { type: 'C', year: '2000', value: 11085 },
11 | { type: 'D', year: '2000', value: 13506 },
12 | { type: 'E', year: '2000', value: 5765 },
13 | { type: 'A', year: '2010', value: 5546 },
14 | { type: 'B', year: '2010', value: 1505 },
15 | { type: 'C', year: '2010', value: 8375 },
16 | { type: 'D', year: '2010', value: 3375 },
17 | { type: 'E', year: '2010', value: 5960 }
18 | ]
19 | }
20 | ],
21 | barWidth: 20,
22 | yField: 'year',
23 | xField: 'value',
24 | legends: {},
25 | label: {
26 | visible: true,
27 | position: (datum: any) => {
28 | return datum.year === '2000' ? 'top-right' : 'bottom-right';
29 | },
30 | overlap: { strategy: [] as string[], clampForce: false },
31 | offset: 0,
32 | style: {
33 | fill: 'rgb(115,125,135)',
34 | fontSize: 12
35 | }
36 | },
37 | direction: 'horizontal',
38 | seriesField: 'type',
39 | axes: [
40 | {
41 | orient: 'bottom',
42 | paddingInner: 0.3
43 | }
44 | ]
45 | };
46 |
47 | export { spec };
48 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/circle-packing-bubble.ts:
--------------------------------------------------------------------------------
1 | const data = new Array(19).fill(0).map((_, i) => {
2 | return {
3 | name: `bubble-${i + 1}`,
4 | value: i + 1
5 | };
6 | });
7 |
8 | const spec = {
9 | data: [
10 | {
11 | id: 'data',
12 | values: data
13 | }
14 | ],
15 | type: 'circlePacking',
16 | categoryField: 'name',
17 | valueField: 'value',
18 | drill: true,
19 | // padding for each bubble
20 | // layoutPadding: 0,
21 | layoutPadding: 5,
22 | label: {
23 | style: {
24 | fontSize: 10,
25 | visible: (d: any) => {
26 | return d.depth === 0;
27 | }
28 | }
29 | },
30 | animationEnter: {
31 | easing: 'cubicInOut'
32 | },
33 | animationExit: {
34 | easing: 'cubicInOut'
35 | },
36 | animationUpdate: {
37 | easing: 'cubicInOut'
38 | }
39 | };
40 |
41 | export { spec };
42 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/funnel-basic.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'funnel',
3 | categoryField: 'name',
4 | valueField: 'value',
5 | data: [
6 | {
7 | id: 'funnel',
8 | values: [
9 | {
10 | value: 100,
11 | name: 'Step1'
12 | },
13 | {
14 | value: 80,
15 | name: 'Step2'
16 | },
17 | {
18 | value: 60,
19 | name: 'Step3'
20 | },
21 | {
22 | value: 40,
23 | name: 'Step4'
24 | },
25 | {
26 | value: 20,
27 | name: 'Step5'
28 | }
29 | ]
30 | }
31 | ],
32 | label: {
33 | visible: true
34 | },
35 | legends: {
36 | visible: true,
37 | orient: 'bottom'
38 | }
39 | };
40 |
41 | export { spec };
42 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/funnel-transform.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'funnel',
3 | categoryField: 'name',
4 | valueField: 'value',
5 | isTransform: true,
6 | isCone: false,
7 | data: [
8 | {
9 | id: 'funnel',
10 | values: [
11 | {
12 | value: 5676,
13 | name: 'Sent'
14 | },
15 | {
16 | value: 3872,
17 | name: 'Viewed'
18 | },
19 | {
20 | value: 1668,
21 | name: 'Clicked'
22 | },
23 | {
24 | value: 610,
25 | name: 'Add to Cart'
26 | },
27 | {
28 | value: 565,
29 | name: 'Purchased'
30 | }
31 | ]
32 | }
33 | ],
34 | title: {
35 | visible: true,
36 | text: 'Percentage of the customers have dropped from the sales process'
37 | },
38 | label: {
39 | visible: true
40 | },
41 | transformLabel: {
42 | visible: true
43 | },
44 | outerLabel: {
45 | position: 'right',
46 | visible: true
47 | },
48 | legends: {
49 | visible: true,
50 | orient: 'top'
51 | }
52 | };
53 |
54 | export { spec };
55 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/gauge-basic.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'gauge',
3 | data: [
4 | {
5 | id: 'id0',
6 | values: [
7 | {
8 | type: '目标A',
9 | value: 0.6
10 | }
11 | ]
12 | }
13 | ],
14 | categoryField: 'type',
15 | valueField: 'value',
16 | outerRadius: 0.8,
17 | innerRadius: 0.5,
18 | startAngle: -180,
19 | endAngle: 0
20 | };
21 |
22 | export { spec };
23 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/gauge-segment.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'gauge',
3 | data: [
4 | {
5 | id: 'pointer',
6 | values: [
7 | {
8 | type: 'A',
9 | value: 0.6
10 | }
11 | ]
12 | },
13 | {
14 | id: 'segment',
15 | values: [
16 | {
17 | type: 'Level 1',
18 | color: '#07A35A',
19 | value: 0.4
20 | },
21 | {
22 | type: 'Level 2',
23 | color: '#FFC528',
24 | value: 0.6
25 | },
26 | {
27 | type: 'Level 3',
28 | color: '#E33232',
29 | value: 0.8
30 | }
31 | ]
32 | }
33 | ],
34 | gauge: {
35 | type: 'gauge',
36 | dataIndex: 1,
37 | categoryField: 'type',
38 | valueField: 'value',
39 | seriesField: 'type',
40 | segment: {
41 | style: {
42 | cornerRadius: 10,
43 | fill: (datum: any) => datum.color
44 | }
45 | },
46 | label: {
47 | visible: true,
48 | position: 'inside-outer',
49 | offsetRadius: 10,
50 | style: {
51 | text: (datum: any) => datum.type
52 | }
53 | }
54 | },
55 | pointer: {
56 | style: {
57 | fill: '#666666'
58 | }
59 | },
60 | categoryField: 'type',
61 | valueField: 'value',
62 | outerRadius: 0.9,
63 | innerRadius: 0.6,
64 | startAngle: -180,
65 | endAngle: 0,
66 | centerY: '100%',
67 | layoutRadius: 'auto',
68 | axes: [
69 | {
70 | type: 'linear',
71 | orient: 'angle',
72 | inside: true,
73 | grid: { visible: false }
74 | }
75 | ]
76 | };
77 |
78 | export { spec };
79 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/line-bar.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'common',
3 | seriesField: 'color',
4 | data: [
5 | {
6 | id: 'id0',
7 | values: [
8 | { x: 'Mon-Tue', type: 'a', y: 19 },
9 | { x: 'Tue-Web', type: 'a', y: 18 },
10 | { x: 'Wed-Thur', type: 'a', y: 16 },
11 | { x: 'Thur-Fri', type: 'a', y: 14 },
12 | { x: 'Fri-Sat', type: 'a', y: 12 },
13 | { x: 'Sat-Sun', type: 'a', y: 11 }
14 | ]
15 | },
16 | {
17 | id: 'id1',
18 | values: [
19 | { x: 'Mon-Tue', type: 'b', y: 16 },
20 | { x: 'Tue-Web', type: 'b', y: 17 },
21 | { x: 'Wed-Thur', type: 'b', y: 18 },
22 | { x: 'Thur-Fri', type: 'b', y: 20 },
23 | { x: 'Fri-Sat', type: 'b', y: 24 },
24 | { x: 'Sat-Sun', type: 'b', y: 26 }
25 | ]
26 | }
27 | ],
28 | series: [
29 | {
30 | type: 'bar',
31 | dataIndex: 0,
32 | seriesField: 'type',
33 | xField: 'x',
34 | yField: 'y'
35 | },
36 | {
37 | type: 'line',
38 | dataIndex: 1,
39 | seriesField: 'type',
40 | xField: 'x',
41 | yField: 'y',
42 | stack: false
43 | }
44 | ],
45 | axes: [
46 | { orient: 'left' },
47 | {
48 | orient: 'bottom',
49 | visible: true,
50 | label: { visible: true },
51 | type: 'band',
52 | bandPadding: 0,
53 | paddingInner: 0,
54 | paddingOuter: 0
55 | }
56 | ]
57 | };
58 |
59 | export { spec };
60 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/line-basic.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'line',
3 | data: {
4 | values: [
5 | {
6 | time: '2:00',
7 | value: 8
8 | },
9 | {
10 | time: '4:00',
11 | value: 9
12 | },
13 | {
14 | time: '6:00',
15 | value: 11
16 | },
17 | {
18 | time: '8:00',
19 | value: 14
20 | },
21 | {
22 | time: '10:00',
23 | value: 16
24 | },
25 | {
26 | time: '12:00',
27 | value: 17
28 | },
29 | {
30 | time: '14:00',
31 | value: 17
32 | },
33 | {
34 | time: '16:00',
35 | value: 16
36 | },
37 | {
38 | time: '18:00',
39 | value: 15
40 | }
41 | ]
42 | },
43 | xField: 'time',
44 | yField: 'value'
45 | };
46 |
47 | export { spec };
48 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/linear-progress.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'linearProgress',
3 | data: [
4 | {
5 | id: 'id0',
6 | values: [
7 | {
8 | type: 'Tradition Industries',
9 | value: 0.795,
10 | text: '79.5%'
11 | },
12 | {
13 | type: 'Business Companies',
14 | value: 0.25,
15 | text: '25%'
16 | },
17 | {
18 | type: 'Customer-facing Companies',
19 | value: 0.065,
20 | text: '6.5%'
21 | }
22 | ]
23 | }
24 | ],
25 | direction: 'horizontal',
26 | xField: 'value',
27 | yField: 'type',
28 | seriesField: 'type',
29 |
30 | cornerRadius: 20,
31 | bandWidth: 30,
32 | axes: [
33 | {
34 | orient: 'left',
35 | label: { visible: true },
36 | type: 'band',
37 | domainLine: { visible: false },
38 | tick: { visible: false }
39 | },
40 | { orient: 'bottom', label: { visible: true }, type: 'linear', visible: false }
41 | ]
42 | };
43 |
44 | export { spec };
45 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/liquid-basic.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'liquid',
3 | valueField: 'value',
4 | data: {
5 | id: 'data',
6 | values: [
7 | {
8 | value: 0.3
9 | }
10 | ]
11 | },
12 | indicator: {
13 | visible: true,
14 | title: {
15 | visible: true,
16 | style: {
17 | text: '进度'
18 | }
19 | },
20 | content: [
21 | {
22 | visible: true,
23 | style: {
24 | fill: 'black',
25 | text: '30%'
26 | }
27 | }
28 | ]
29 | }
30 | };
31 |
32 | export { spec };
33 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/liquid-star.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'liquid',
3 | valueField: 'value',
4 | data: {
5 | id: 'data',
6 | values: [
7 | {
8 | value: 0.4
9 | }
10 | ]
11 | },
12 | // maskShape: 'drop', // 水滴
13 | // maskShape: 'circle',
14 | maskShape: 'star',
15 | indicator: {
16 | visible: true,
17 | title: {
18 | visible: true,
19 | style: {
20 | text: '进度'
21 | }
22 | },
23 | content: [
24 | {
25 | visible: true,
26 | style: {
27 | fill: 'black',
28 | text: '40%'
29 | }
30 | }
31 | ]
32 | },
33 | liquidBackground: {
34 | style: {
35 | fill: 'blue'
36 | }
37 | }
38 | };
39 |
40 | export { spec };
41 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/pie-basic.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'pie',
3 | data: [
4 | {
5 | id: 'id0',
6 | values: [
7 | { type: 'oxygen', value: '46.60' },
8 | { type: 'silicon', value: '27.72' },
9 | { type: 'aluminum', value: '8.13' },
10 | { type: 'iron', value: '5' },
11 | { type: 'calcium', value: '3.63' },
12 | { type: 'sodium', value: '2.83' },
13 | { type: 'potassium', value: '2.59' },
14 | { type: 'others', value: '3.5' }
15 | ]
16 | }
17 | ],
18 | outerRadius: 0.8,
19 | valueField: 'value',
20 | categoryField: 'type',
21 | title: {
22 | visible: true,
23 | text: 'Statistics of Surface Element Content'
24 | },
25 | legends: {
26 | visible: true,
27 | orient: 'left'
28 | },
29 | label: {
30 | visible: true
31 | },
32 | tooltip: {
33 | mark: {
34 | content: [
35 | {
36 | key: (datum: any) => datum.type,
37 | value: (datum: any) => datum.value + '%'
38 | }
39 | ]
40 | }
41 | }
42 | };
43 |
44 | export { spec };
45 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/pie-donut.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'pie',
3 | data: [
4 | {
5 | id: 'id0',
6 | values: [
7 | { type: 'oxygen', value: '46.60' },
8 | { type: 'silicon', value: '27.72' },
9 | { type: 'aluminum', value: '8.13' },
10 | { type: 'iron', value: '5' },
11 | { type: 'calcium', value: '3.63' },
12 | { type: 'sodium', value: '2.83' },
13 | { type: 'potassium', value: '2.59' },
14 | { type: 'others', value: '3.5' }
15 | ]
16 | }
17 | ],
18 | outerRadius: 0.8,
19 | innerRadius: 0.5,
20 | padAngle: 0.6,
21 | valueField: 'value',
22 | categoryField: 'type',
23 | pie: {
24 | style: {
25 | cornerRadius: 10
26 | },
27 | state: {
28 | hover: {
29 | outerRadius: 0.85,
30 | stroke: '#000',
31 | lineWidth: 1
32 | },
33 | selected: {
34 | outerRadius: 0.85,
35 | stroke: '#000',
36 | lineWidth: 1
37 | }
38 | }
39 | },
40 | title: {
41 | visible: true,
42 | text: 'Statistics of Surface Element Content'
43 | },
44 | legends: {
45 | visible: true,
46 | orient: 'left'
47 | },
48 | label: {
49 | visible: true
50 | },
51 | tooltip: {
52 | mark: {
53 | content: [
54 | {
55 | key: (datum: any) => datum.type,
56 | value: (datum: any) => datum.value + '%'
57 | }
58 | ]
59 | }
60 | }
61 | };
62 |
63 | export { spec };
64 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/radar-group.ts:
--------------------------------------------------------------------------------
1 | const mockData = [];
2 | const types = ['A', 'B', 'C'];
3 |
4 | types.forEach(type => {
5 | for (let i = 1; i <= 12; i++) {
6 | mockData.push({ month: i + 'th', value: Math.random() * 100 + 10, type });
7 | }
8 | });
9 |
10 | const spec = {
11 | type: 'radar',
12 | data: [
13 | {
14 | values: mockData
15 | }
16 | ],
17 | categoryField: 'month',
18 | valueField: 'value',
19 | seriesField: 'type',
20 | axes: [
21 | {
22 | orient: 'radius',
23 | grid: {
24 | smooth: true, // smooth grid lines
25 | style: {
26 | lineDash: [0]
27 | },
28 | alternateColor: '#f5f5f5' // Configure the background color between grid lines
29 | }
30 | },
31 | {
32 | orient: 'angle',
33 | tick: {
34 | visible: false
35 | },
36 | domainLine: {
37 | visible: true,
38 | style: {
39 | stroke: '#333'
40 | }
41 | },
42 | grid: {
43 | style: {
44 | lineDash: [0]
45 | }
46 | }
47 | }
48 | ],
49 | legends: {
50 | visible: true,
51 | orient: 'top'
52 | }
53 | };
54 |
55 | export { spec };
56 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/radar-innerradius.ts:
--------------------------------------------------------------------------------
1 | const mockData = [];
2 | for (let i = 0; i < 24; i++) {
3 | mockData.push({
4 | key: `key${i}`,
5 | value: parseInt(Math.random() * 10, 10)
6 | });
7 | }
8 | const spec = {
9 | type: 'radar',
10 | data: [
11 | {
12 | values: mockData
13 | }
14 | ],
15 | categoryField: 'key',
16 | valueField: 'value',
17 | innerRadius: 0.4,
18 | outerRadius: 0.9,
19 | label: {
20 | visible: true
21 | },
22 | axes: [
23 | {
24 | orient: 'radius',
25 | zIndex: 100,
26 | grid: {
27 | style: (data, index) => {
28 | if (index === 0) {
29 | return {
30 | lineDash: [0]
31 | };
32 | }
33 | return {
34 | visible: false
35 | };
36 | }
37 | }
38 | },
39 | {
40 | orient: 'angle',
41 | tick: {
42 | visible: false
43 | },
44 | domainLine: {
45 | visible: true
46 | },
47 | grid: {
48 | alignWithLabel: false,
49 | style: {
50 | lineDash: [0]
51 | },
52 | alternateColor: 'rgba(0, 0, 0, 0.04)'
53 | }
54 | }
55 | ],
56 | indicator: {
57 | visible: true,
58 | trigger: 'hover',
59 | limitRatio: 0.4,
60 | title: {
61 | visible: true,
62 | autoFit: true,
63 | style: {
64 | fontWeight: 'bolder',
65 | fontFamily: 'Times New Roman',
66 | fill: '#888',
67 | text: 'Radar'
68 | }
69 | }
70 | }
71 | };
72 |
73 | export { spec };
74 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/range-bar.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'rangeColumn',
3 | data: [
4 | {
5 | id: 'data0',
6 | values: [
7 | { type: 'Category One', min: 76, max: 100 },
8 | { type: 'Category Two', min: 56, max: 108 },
9 | { type: 'Category Three', min: 38, max: 129 },
10 | { type: 'Category Four', min: 58, max: 155 },
11 | { type: 'Category Five', min: 45, max: 120 },
12 | { type: 'Category Six', min: 23, max: 99 },
13 | { type: 'Category Seven', min: 18, max: 56 },
14 | { type: 'Category Eight', min: 18, max: 34 }
15 | ]
16 | }
17 | ],
18 | direction: 'horizontal',
19 | yField: 'type',
20 | xField: ['min', 'max'],
21 | label: {
22 | visible: true
23 | }
24 | };
25 |
26 | export { spec };
27 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/range-column.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'rangeColumn',
3 | data: [
4 | {
5 | values: [
6 | { type: 'Category One', min: 76, max: 100 },
7 | { type: 'Category Two', min: 56, max: 108 },
8 | { type: 'Category Three', min: 38, max: 129 },
9 | { type: 'Category Four', min: 58, max: 155 },
10 | { type: 'Category Five', min: 45, max: 120 },
11 | { type: 'Category Six', min: 23, max: 99 },
12 | { type: 'Category Seven', min: 18, max: 56 },
13 | { type: 'Category Eight', min: 18, max: 34 }
14 | ]
15 | }
16 | ],
17 | xField: 'type',
18 | yField: ['min', 'max'],
19 | label: {
20 | position: 'bothEnd'
21 | }
22 | };
23 | export { spec };
24 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/rose-basis.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'rose',
3 | data: [
4 | {
5 | values: [
6 | {
7 | value: '159',
8 | type: 'Tradition Industries'
9 | },
10 | {
11 | value: '50',
12 | type: 'Business Companies'
13 | },
14 | {
15 | value: '13',
16 | type: 'Customer-facing Companies'
17 | }
18 | ]
19 | }
20 | ],
21 | outerRadius: 0.8,
22 | innerRadius: 0.2,
23 | categoryField: 'type',
24 | valueField: 'value',
25 | seriesField: 'type',
26 | label: {
27 | visible: true,
28 | layout: {
29 | tangentConstraint: false
30 | }
31 | }
32 | };
33 |
34 | export { spec };
35 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/venn-three.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'venn',
3 | data: {
4 | values: [
5 | { sets: ['A'], value: 8 },
6 | { sets: ['B'], value: 10 },
7 | { sets: ['C'], value: 12 },
8 | { sets: ['A', 'B'], value: 4 },
9 | { sets: ['A', 'C'], value: 4 },
10 | { sets: ['B', 'C'], value: 4 },
11 | { sets: ['A', 'B', 'C'], value: 2 }
12 | ]
13 | },
14 | categoryField: 'sets',
15 | valueField: 'value',
16 | seriesField: 'sets',
17 | legends: [{ visible: true, position: 'middle', orient: 'bottom' }]
18 | };
19 |
20 | export { spec };
21 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/waterfall-h.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'waterfall',
3 | direction: 'horizontal',
4 | data: {
5 | id: 'id0',
6 | values: [
7 | { x: 'Feb.4', total: true, value: 45 },
8 | { x: 'Feb.11', y: -5 },
9 | { x: 'Feb.20', y: 2 },
10 | { x: 'Feb.25', y: -2 },
11 | { x: 'Mar.4', y: 2 },
12 | { x: 'Mar.11', y: 2 },
13 | { x: 'Mar.19', y: -2 },
14 | { x: 'Mar.26', y: 1 },
15 | { x: 'Apr.1', y: 1 },
16 | { x: 'Apr.8', y: 1 },
17 | { x: 'Apr.15', y: 2 },
18 | { x: 'Apr.22', y: 1 },
19 | { x: 'Apr.29', y: -2 },
20 | { x: 'May.6', y: -1 },
21 | { x: 'total', total: true }
22 | ]
23 | },
24 | legends: { visible: true, orient: 'bottom' },
25 | xField: 'y',
26 | yField: 'x',
27 | stackLabel: {
28 | valueType: 'absolute',
29 | formatMethod: text => {
30 | return text + '%';
31 | }
32 | },
33 | seriesFieldName: {
34 | total: 'total',
35 | increase: 'increase',
36 | decrease: 'reduce'
37 | },
38 | total: {
39 | type: 'field',
40 | tagField: 'total',
41 | valueField: 'value'
42 | },
43 | axes: [
44 | {
45 | orient: 'bottom',
46 | range: { min: 30, max: 50 },
47 | title: { visible: true, text: 'favorability' },
48 | label: {
49 | formatMethod: v => {
50 | return v + '%';
51 | }
52 | }
53 | },
54 | {
55 | orient: 'left',
56 | label: { visible: true },
57 | type: 'band',
58 | paddingInner: 0.4,
59 | title: { visible: true, text: 'date' }
60 | }
61 | ]
62 | };
63 |
64 | export { spec };
65 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/waterfall.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'waterfall',
3 | data: {
4 | id: 'id0',
5 | values: [
6 | { x: 'Feb.4', total: true, value: 45 },
7 | { x: 'Feb.11', y: -5 },
8 | { x: 'Feb.20', y: 2 },
9 | { x: 'Feb.25', y: -2 },
10 | { x: 'Mar.4', y: 2 },
11 | { x: 'Mar.11', y: 2 },
12 | { x: 'Mar.19', y: -2 },
13 | { x: 'Mar.26', y: 1 },
14 | { x: 'Apr.1', y: 1 },
15 | { x: 'Apr.8', y: 1 },
16 | { x: 'Apr.15', y: 2 },
17 | { x: 'Apr.22', y: 1 },
18 | { x: 'Apr.29', y: -2 },
19 | { x: 'May.6', y: -1 },
20 | { x: 'total', total: true }
21 | ]
22 | },
23 | legends: { visible: true, orient: 'bottom' },
24 | xField: 'x',
25 | yField: 'y',
26 | stackLabel: {
27 | valueType: 'absolute',
28 | formatMethod: text => {
29 | return text + '%';
30 | }
31 | },
32 | seriesFieldName: {
33 | total: 'total',
34 | increase: 'increase',
35 | decrease: 'reduce'
36 | },
37 | total: {
38 | type: 'field',
39 | tagField: 'total',
40 | valueField: 'value'
41 | },
42 | axes: [
43 | {
44 | orient: 'left',
45 | range: { min: 30, max: 50 },
46 | title: { visible: true, text: 'favorability' },
47 | label: {
48 | formatMethod: v => {
49 | return v + '%';
50 | }
51 | }
52 | },
53 | {
54 | orient: 'bottom',
55 | label: { visible: true },
56 | type: 'band',
57 | paddingInner: 0.4,
58 | title: { visible: true, text: 'date' }
59 | }
60 | ]
61 | };
62 |
63 | export { spec };
64 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/image-to-spec/spec/wordcloud-basic.ts:
--------------------------------------------------------------------------------
1 | const spec = {
2 | type: 'wordCloud',
3 | nameField: 'name',
4 | valueField: 'value',
5 | wordCloudConfig: {
6 | zoomToFit: {
7 | enlarge: true,
8 | fontSizeLimitMax: 20
9 | }
10 | },
11 | data: {
12 | name: 'baseData',
13 | values: [
14 | {
15 | name: '螺蛳粉',
16 | value: 957
17 | },
18 | {
19 | name: '钵钵鸡',
20 | value: 942
21 | },
22 | {
23 | name: '板栗',
24 | value: 842
25 | },
26 | {
27 | name: '胡辣汤',
28 | value: 828
29 | },
30 | {
31 | name: '关东煮',
32 | value: 665
33 | },
34 | {
35 | name: '羊肉汤',
36 | value: 627
37 | },
38 | {
39 | name: '热干面',
40 | value: 574
41 | }
42 | ]
43 | }
44 | };
45 |
46 | export { spec };
47 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@internal/ts-config/tsconfig.base.json",
3 | "include": ["./", "../src"],
4 | "compilerOptions": {
5 | "paths": {
6 | "@visactor/calculator": ["../../calculator/src"],
7 | "@visactor/chart-advisor": ["../../chart-advisor/src"]
8 | },
9 | "lib": ["DOM", "ESNext"]
10 | },
11 | "references": []
12 | }
13 |
--------------------------------------------------------------------------------
/packages/vmind/__tests__/unit/index.test.ts:
--------------------------------------------------------------------------------
1 | describe('VMind', () => {
2 | it('should be correct', () => {
3 | expect(1).toEqual(1);
4 | });
5 | });
6 |
--------------------------------------------------------------------------------
/packages/vmind/bundler.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @type {Partial}
3 | */
4 | const json = require('@rollup/plugin-json');
5 |
6 | module.exports = {
7 | formats: ['cjs', 'es', 'umd'],
8 | outputDir: {
9 | es: 'esm',
10 | cjs: 'cjs',
11 | umd: 'build'
12 | },
13 | name: 'VMind',
14 | umdOutputFilename: 'index',
15 | rollupOptions: {
16 | plugins: [json()]
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/packages/vmind/jest.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const baseJestConfig = require('@internal/jest-config/jest.base');
3 |
4 | module.exports = {
5 | ...baseJestConfig,
6 | moduleNameMapper: {
7 | ...baseJestConfig.moduleNameMapper,
8 | '@visactor/calculator': path.resolve(__dirname, '../calculator/src'),
9 | '@visactor/chart-advisor': path.resolve(__dirname, '../chart-advisor/src')
10 | },
11 | transform: {
12 | '^.+\\.tsx?$': [
13 | 'ts-jest',
14 | {
15 | diagnostics: false // ignore TypeScript error
16 | }
17 | ]
18 | }
19 | };
20 |
--------------------------------------------------------------------------------
/packages/vmind/jest.performance.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const baseJestConfig = require('@internal/jest-config/jest.base');
3 |
4 | module.exports = {
5 | ...baseJestConfig,
6 | moduleNameMapper: {
7 | ...baseJestConfig.moduleNameMapper,
8 | axios: path.resolve(__dirname, 'node_modules/axios/dist/node/axios.cjs')
9 | },
10 | verbose: true,
11 | // 在测试之前设置环境变量
12 | setupFiles: ['./test-setup.js']
13 | };
14 |
15 | // module.exports = {
16 | // preset: 'ts-jest',
17 | // silent: false,
18 | // globals: {
19 | // 'ts-jest': {
20 | // resolveJsonModule: true,
21 | // esModuleInterop: true,
22 | // experimentalDecorators: true,
23 | // module: 'ESNext',
24 | // tsconfig: './tsconfig.test.json'
25 | // }
26 | // },
27 | // testTimeout: 60000,
28 | // moduleNameMapper: {
29 | // axios: 'axios/dist/node/axios.cjs',
30 | // 'd3-hierarchy': 'd3-hierarchy/dist/d3-hierarchy.min.js',
31 | // '^src/(.*)$': '/src/$1'
32 | // },
33 | // verbose: true,
34 | // // 在测试之前设置环境变量
35 | // setupFiles: ['./test-setup.js'],
36 | // testEnvironment: 'node'
37 | // };
38 |
--------------------------------------------------------------------------------
/packages/vmind/src/applications/chartGeneration/index.ts:
--------------------------------------------------------------------------------
1 | import type { LLMManage } from '../../core/llm';
2 | import { Schedule } from '../../schedule';
3 | import type { ILLMOptions } from '../../types';
4 | import { AtomName, Model } from '../../types';
5 |
6 | export const getData2ChartSchedule = (llm: LLMManage, options: ILLMOptions) => {
7 | const useChartAdvisor =
8 | !llm.options.customRequestFunc?.chartGenerate &&
9 | (llm.options.model === Model.CHART_ADVISOR || !llm.options?.headers);
10 | if (useChartAdvisor) {
11 | return new Schedule([AtomName.CHART_GENERATE], {
12 | base: { llm },
13 | chartGenerate: { useChartAdvisor: true }
14 | });
15 | }
16 | return new Schedule([AtomName.IMAGE_READER, AtomName.DATA_QUERY, AtomName.CHART_COMMAND, AtomName.CHART_GENERATE], {
17 | base: { llm, showThoughts: options?.showThoughts },
18 | chartCommand: { useDataTable: true }
19 | });
20 | };
21 |
--------------------------------------------------------------------------------
/packages/vmind/src/applications/dataAggregation/index.ts:
--------------------------------------------------------------------------------
1 | import type { LLMManage } from '../../core/llm';
2 | import type { ILLMOptions } from '../../types';
3 | import { AtomName } from '../../types';
4 | import { Schedule } from '../../schedule';
5 |
6 | export const getDataQuerySchedule = (llm: LLMManage, options: ILLMOptions) => {
7 | return new Schedule([AtomName.DATA_QUERY], {
8 | base: { llm, showThoughts: options?.showThoughts }
9 | });
10 | };
11 |
--------------------------------------------------------------------------------
/packages/vmind/src/applications/dataExtraction/index.ts:
--------------------------------------------------------------------------------
1 | import type { LLMManage } from '../../core/llm';
2 | import { Schedule } from '../../schedule';
3 | import type { ILLMOptions } from '../../types';
4 | import { AtomName } from '../../types';
5 |
6 | export const getText2DataSchedule = (llm: LLMManage, options: ILLMOptions) => {
7 | return new Schedule([AtomName.DATA_EXTRACT, AtomName.DATA_CLEAN], {
8 | base: { llm, showThoughts: options?.showThoughts }
9 | });
10 | };
11 |
12 | export const getText2MultipleDataSchedule = (llm: LLMManage, options: ILLMOptions) => {
13 | return new Schedule([AtomName.DATA_EXTRACT, AtomName.MULTIPLE_DATA_CLEAN], {
14 | base: { llm, showThoughts: options?.showThoughts }
15 | });
16 | };
17 |
18 | export const getText2ChartSchedule = (llm: LLMManage, options: ILLMOptions) => {
19 | return new Schedule(
20 | [AtomName.DATA_EXTRACT, AtomName.DATA_CLEAN, AtomName.DATA_QUERY, AtomName.CHART_COMMAND, AtomName.CHART_GENERATE],
21 | {
22 | base: { llm, showThoughts: options?.showThoughts },
23 | chartGenerate: { useChartRule: true }
24 | }
25 | );
26 | };
27 |
--------------------------------------------------------------------------------
/packages/vmind/src/applications/dataInsight/index.ts:
--------------------------------------------------------------------------------
1 | import type { LLMManage } from '../../core/llm';
2 | import type { ILLMOptions } from '../../types';
3 | import { AtomName } from '../../types';
4 | import { Schedule } from '../../schedule';
5 |
6 | export const getDataInsightSchedule = (llm: LLMManage, options: ILLMOptions) => {
7 | return new Schedule([AtomName.DATA_INSIGHT, AtomName.SPEC_INSIGHT], {
8 | base: { llm, showThoughts: options?.showThoughts }
9 | });
10 | };
11 |
--------------------------------------------------------------------------------
/packages/vmind/src/applications/index.ts:
--------------------------------------------------------------------------------
1 | export { getDataQuerySchedule } from './dataAggregation';
2 | export { getData2ChartSchedule } from './chartGeneration';
3 | export { getText2DataSchedule, getText2MultipleDataSchedule, getText2ChartSchedule } from './dataExtraction';
4 | export { getDataInsightSchedule } from './dataInsight';
5 | export { getScheduleLLmOptions } from './utils';
6 |
--------------------------------------------------------------------------------
/packages/vmind/src/applications/utils.ts:
--------------------------------------------------------------------------------
1 | import type { ILLMOptions, VMindOptions } from '../types';
2 | import { AtomName } from '../types';
3 |
4 | export const getScheduleLLmOptions = (vmindOptions: VMindOptions): ILLMOptions => {
5 | const { customRequestFunc = {}, ...others } = vmindOptions;
6 | const llmCustomOptions: ILLMOptions['customRequestFunc'] = {};
7 | Object.keys(customRequestFunc).forEach(oldName => {
8 | switch (oldName) {
9 | case 'dataExtraction':
10 | llmCustomOptions[AtomName.DATA_EXTRACT] = customRequestFunc[oldName];
11 | case 'dataQuery':
12 | llmCustomOptions[AtomName.DATA_QUERY] = customRequestFunc[oldName];
13 | break;
14 | case 'chartCommand':
15 | llmCustomOptions[AtomName.CHART_COMMAND] = customRequestFunc[oldName];
16 | break;
17 | case 'chartAdvisor':
18 | llmCustomOptions[AtomName.CHART_GENERATE] = customRequestFunc[oldName];
19 | break;
20 | case 'IntelligentInsight':
21 | llmCustomOptions[AtomName.DATA_INSIGHT] = customRequestFunc[oldName];
22 | break;
23 | default:
24 | break;
25 | }
26 | });
27 | return {
28 | ...others,
29 | customRequestFunc: llmCustomOptions
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/VChartSpec/index.ts:
--------------------------------------------------------------------------------
1 | import { AtomName } from '../../types/atom';
2 | import { BaseAtom } from '../base';
3 | import type { BaseOptions, VChartSpecCtx } from '../../types';
4 | import { runOperactionsOfSpec } from './utils';
5 | import { Factory } from '../../core/factory';
6 | import type { BaseAtomConstructor } from '../../types';
7 |
8 | export class VChartSpec extends BaseAtom {
9 | name = AtomName.VCHART_SPEC;
10 |
11 | isLLMAtom = false;
12 |
13 | constructor(context: VChartSpecCtx, option: BaseOptions) {
14 | super(context, option);
15 | }
16 |
17 | buildDefaultContext(context: VChartSpecCtx): VChartSpecCtx {
18 | return {
19 | ...context,
20 | spec: {}
21 | };
22 | }
23 |
24 | _runWithOutLLM(): VChartSpecCtx {
25 | const { prevSpec, originalSpec, operations } = this.context;
26 | const baseSpec = prevSpec ?? originalSpec;
27 |
28 | if (!operations || !operations.length) {
29 | this.context.spec = baseSpec;
30 |
31 | return this.context;
32 | }
33 | const { spec: newSpec } = runOperactionsOfSpec(baseSpec, operations);
34 |
35 | this.context.prevSpec = baseSpec;
36 | this.context.spec = newSpec;
37 |
38 | return this.context;
39 | }
40 | }
41 |
42 | export const registerVChartSpecAtom = () => {
43 | Factory.registerAtom(AtomName.VCHART_SPEC, VChartSpec as unknown as BaseAtomConstructor);
44 | };
45 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/chartGenerator/spec/constants.ts:
--------------------------------------------------------------------------------
1 | export const WORDCLOUD_NUM_LIMIT = 100;
2 |
3 | export const COLOR_THEMES = {
4 | default: ['#1DD0F3', '#2693FF', '#3259F4', '#1B0CA1', '#CB2BC6', '#FF581D', '#FBBB16', '#F6FB17', '#73EC55']
5 | };
6 |
7 | export const LINEAR_COLOR_THEMES = [
8 | ['#1DD0F3', '#73EC55'],
9 | ['#2693FF', '#F6FB17'],
10 | ['#3259F4', '#FBBB16'],
11 | ['#1B0CA1', '#FF581D'],
12 | ['#1DD0F3', '#CB2BC6']
13 | ];
14 |
15 | export const BASIC_HEAT_MAP_COLOR_THEMES = ['#feedde', '#fdbe85', '#fd8d3c', '#e6550d', '#a63603'];
16 |
17 | export const animationDuration = 500;
18 | export const oneByOneGroupSize = 10;
19 | export const DEFAULT_VIDEO_LENGTH = 2000;
20 | export const DEFAULT_PIE_VIDEO_LENGTH = 5000;
21 | export const DEFAULT_VIDEO_LENGTH_LONG = 10000;
22 | export const VIDEO_LENGTH_BY_CHART_TYPE: Record = {
23 | pie: DEFAULT_PIE_VIDEO_LENGTH,
24 | wordCloud: DEFAULT_VIDEO_LENGTH_LONG,
25 | wordcloud: DEFAULT_VIDEO_LENGTH_LONG
26 | };
27 |
28 | export const DIMENSION_AXIS_ID = 'dimensionAxis';
29 | export const MEASURE_AXIS_LEFT_ID = 'measureAxisLeft';
30 | export const MEASURE_AXIS_RIGHT_ID = 'measureAxisRight';
31 |
32 | export const MAIN_SERIES_ID = 'mainSeries';
33 | export const SUB_SERIES_ID = 'subSeries';
34 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/chartGenerator/spec/transformers/circlePacking.ts:
--------------------------------------------------------------------------------
1 | import type { GenerateChartCellContext } from '../../type';
2 | import { color, data, revisedVChartType, theme } from './common';
3 |
4 | export const bubbleCirclePackingData = (context: GenerateChartCellContext) => {
5 | const { dataTable, spec, cell } = context;
6 | if (cell.size) {
7 | dataTable.forEach(data => {
8 | data.value = data[cell.size];
9 |
10 | if (cell.size !== 'value') {
11 | delete data[cell.size];
12 | }
13 | });
14 | }
15 | return { spec };
16 | };
17 |
18 | export const bubbleCirclePackingField = (context: GenerateChartCellContext) => {
19 | //assign field in spec according to cell
20 | const { cell, spec } = context;
21 | spec.categoryField = cell.color || cell.x;
22 |
23 | if (cell.size) {
24 | spec.valueField = cell.size;
25 | }
26 |
27 | return { spec };
28 | };
29 |
30 | export const bubbleCirclePackingDisplayConf = (context: GenerateChartCellContext) => {
31 | const { spec } = context;
32 | spec.drill = true;
33 | spec.layoutPadding = 5;
34 | spec.animationEnter = {
35 | easing: 'cubicInOut'
36 | };
37 | spec.animationExit = {
38 | easing: 'cubicInOut'
39 | };
40 | spec.animationUpdate = {
41 | easing: 'cubicInOut'
42 | };
43 | return { spec };
44 | };
45 |
46 | export const pipelineBubbleCirclePacking = [
47 | bubbleCirclePackingData,
48 | data,
49 | color,
50 | bubbleCirclePackingField,
51 | bubbleCirclePackingDisplayConf
52 | ];
53 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/chartGenerator/spec/transformers/circularProgress.ts:
--------------------------------------------------------------------------------
1 | import type { GenerateChartCellContext } from '../../type';
2 | import { color, data, indicator, revisedVChartType, theme } from './common';
3 |
4 | export const circularProgressField = (context: GenerateChartCellContext) => {
5 | //assign field in spec according to cell
6 | const { cell, spec } = context;
7 |
8 | spec.categoryField = cell.color;
9 | spec.valueField = cell.value;
10 | spec.seriesField = cell.color;
11 |
12 | spec.radius = 0.8;
13 | spec.innerRadius = 0.7;
14 | spec.roundCap = true;
15 | spec.cornerRadius = 20;
16 |
17 | return { spec };
18 | };
19 |
20 | export const circularProgressStyle = (context: GenerateChartCellContext) => {
21 | const { spec } = context;
22 | spec.progress = {
23 | ...spec.progress,
24 | style: {}
25 | };
26 | return { spec };
27 | };
28 |
29 | export const pipelineCircularProgress = [data, color, circularProgressField, circularProgressStyle, indicator];
30 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/chartGenerator/spec/transformers/funnel.ts:
--------------------------------------------------------------------------------
1 | import { isValidDataTable } from '../../../../utils/dataTable';
2 | import type { GenerateChartCellContext } from '../../type';
3 | import { color, commonLabel, discreteLegend, revisedVChartType, theme } from './common';
4 |
5 | export const funnelData = (context: GenerateChartCellContext) => {
6 | const { dataTable, cell, spec } = context;
7 | // spec.data = [dataTable]
8 | spec.data = {
9 | id: 'data',
10 | values: isValidDataTable(dataTable)
11 | ? dataTable.sort((a: any, b: any) => b[cell.y as string] - a[cell.y as string])
12 | : []
13 | };
14 |
15 | return { spec };
16 | };
17 |
18 | export const funnelField = (context: GenerateChartCellContext) => {
19 | //assign field in spec according to cell
20 | const { cell, spec } = context;
21 | spec.categoryField = cell.color || cell.x;
22 | spec.valueField = cell.value || cell.y;
23 |
24 | return { spec };
25 | };
26 |
27 | export const pipelineFunnel = [funnelData, color, funnelField, discreteLegend, commonLabel];
28 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/chartGenerator/spec/transformers/gauge.ts:
--------------------------------------------------------------------------------
1 | import type { GenerateChartCellContext } from '../../type';
2 | import { arrayData, color, revisedVChartType, theme } from './common';
3 |
4 | export const gaugeField = (context: GenerateChartCellContext) => {
5 | const { spec, cell } = context;
6 | spec.valueField = cell.size;
7 | spec.categoryField = cell.color;
8 | return { spec };
9 | };
10 |
11 | export const gaugeDisplayConf = (context: GenerateChartCellContext) => {
12 | const { spec } = context;
13 | spec.outerRadius = 0.8;
14 | spec.innerRadius = 0.5;
15 | spec.startAngle = -180;
16 | spec.endAngle = 0;
17 | return { spec };
18 | };
19 |
20 | export const pipelineGauge = [arrayData, color, gaugeField, gaugeDisplayConf];
21 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/chartGenerator/spec/transformers/index.ts:
--------------------------------------------------------------------------------
1 | export { data, discreteLegend as legend } from './common';
2 | export { funnelData } from './funnel';
3 | export { sankeyData } from './sankey';
4 | export { wordCloudData } from './wordcloud';
5 | export { sequenceData } from './rankingBar';
6 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/chartGenerator/spec/transformers/liquid.ts:
--------------------------------------------------------------------------------
1 | import type { GenerateChartCellContext } from '../../type';
2 | import { color, data, indicator, revisedVChartType, theme } from './common';
3 |
4 | export const liquidField = (context: GenerateChartCellContext) => {
5 | const { cell, spec } = context;
6 |
7 | spec.valueField = cell.value;
8 | spec.indicatorSmartInvert = true;
9 |
10 | return { spec };
11 | };
12 |
13 | export const liquidStyle = (context: GenerateChartCellContext) => {
14 | const { spec } = context;
15 | spec.liquid = {
16 | ...spec.liquid,
17 | style: {}
18 | };
19 | return { spec };
20 | };
21 |
22 | export const pipelineLiquid = [data, color, liquidField, liquidStyle, indicator];
23 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/chartGenerator/spec/transformers/map.ts:
--------------------------------------------------------------------------------
1 | import type { GenerateChartCellContext } from '../../type';
2 | import { arrayData, color, revisedVChartType, theme } from './common';
3 |
4 | export const basemap = (context: GenerateChartCellContext) => {
5 | const { basemapOption, spec } = context;
6 | if (basemapOption.regionProjectType) {
7 | spec.region = [
8 | {
9 | roam: true,
10 | projection: { type: basemapOption.regionProjectType },
11 | coordinate: basemapOption.regionCoordinate
12 | }
13 | ];
14 | } else {
15 | spec.region = [
16 | {
17 | roam: true,
18 | coordinate: basemapOption.regionCoordinate
19 | }
20 | ];
21 | }
22 |
23 | spec.map = 'map';
24 | return { spec };
25 | };
26 |
27 | export const mapField = (context: GenerateChartCellContext) => {
28 | const { spec, cell } = context;
29 |
30 | spec.nameField = cell.color;
31 | spec.valueField = cell.size;
32 | spec.nameProperty = cell.color;
33 | return { spec };
34 | };
35 |
36 | export const mapDisplayConf = (context: GenerateChartCellContext) => {
37 | const { spec, cell } = context;
38 | spec.legends = [
39 | {
40 | visible: true,
41 | type: 'color',
42 | field: cell.size,
43 | orient: 'bottom',
44 | position: 'start'
45 | }
46 | ];
47 | spec.area = {
48 | style: {
49 | fill: {
50 | field: cell.size,
51 | scale: 'color',
52 | changeDomain: 'replace'
53 | }
54 | }
55 | };
56 | return { spec };
57 | };
58 |
59 | export const pipelineMapChart = [basemap, color, arrayData, mapField, mapDisplayConf];
60 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/chartGenerator/spec/transformers/pie.ts:
--------------------------------------------------------------------------------
1 | import type { GenerateChartCellContext } from '../../type';
2 | import { color, commonLabel, data, discreteLegend, revisedVChartType, theme } from './common';
3 |
4 | export const pieField = (context: GenerateChartCellContext) => {
5 | //assign field in spec according to cell
6 | const { cell, spec } = context;
7 | spec.valueField = cell.angle || cell.value;
8 | if (cell.color || (cell as any).category) {
9 | spec.categoryField = cell.color || (cell as any).category;
10 | }
11 | return { spec };
12 | };
13 |
14 | export const pipelinePie = [
15 | data,
16 | color,
17 | pieField,
18 | discreteLegend,
19 | commonLabel
20 | // animationCartesianPie,
21 | ];
22 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/chartGenerator/spec/transformers/rangeColumn.ts:
--------------------------------------------------------------------------------
1 | import type { GenerateChartCellContext } from '../../type';
2 | import { color, data, revisedVChartType, theme } from './common';
3 |
4 | export const rangeColumnField = (context: GenerateChartCellContext) => {
5 | //assign field in spec according to cell
6 | const { cell, spec } = context;
7 | spec.yField = cell.x;
8 |
9 | spec.xField = [cell.y[0], cell.y[1]];
10 |
11 | return { spec };
12 | };
13 |
14 | export const rangeColumnDisplayConf = (context: GenerateChartCellContext) => {
15 | const { spec } = context;
16 | spec.direction = 'horizontal';
17 | spec.label = {
18 | visible: true
19 | };
20 | return { spec };
21 | };
22 |
23 | export const pipelineRangeColumn = [data, color, rangeColumnField, rangeColumnDisplayConf];
24 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/chartGenerator/spec/transformers/rose.ts:
--------------------------------------------------------------------------------
1 | import type { GenerateChartCellContext } from '../../type';
2 | import { color, commonLabel, data, discreteLegend, revisedVChartType, theme } from './common';
3 |
4 | export const roseField = (context: GenerateChartCellContext) => {
5 | const { cell, spec } = context;
6 | spec.valueField = cell.radius || cell.angle;
7 | if (cell.color) {
8 | spec.categoryField = cell.category ?? cell.color;
9 | spec.seriesField = cell.color;
10 | }
11 | spec.outerRadius = 0.8;
12 | spec.innerRadius = 0.2;
13 |
14 | return { spec };
15 | };
16 |
17 | export const roseAxis = (context: GenerateChartCellContext) => {
18 | const { spec } = context;
19 |
20 | spec.axes = [
21 | {
22 | orient: 'angle',
23 | domainLine: {
24 | visible: false
25 | },
26 | grid: {
27 | visible: false,
28 | alignWithLabel: false
29 | },
30 | label: {
31 | visible: true
32 | }
33 | },
34 | {
35 | orient: 'radius',
36 | grid: {
37 | visible: false,
38 | smooth: true
39 | }
40 | }
41 | ];
42 | return { spec };
43 | };
44 |
45 | export const pipelineRose = [
46 | data,
47 | color,
48 | roseField,
49 | roseAxis,
50 | discreteLegend,
51 | commonLabel
52 | //animationCartesianPie,
53 | ];
54 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/chartGenerator/spec/transformers/venn.ts:
--------------------------------------------------------------------------------
1 | import { registerVennChart } from '@visactor/vchart';
2 | import { color, discreteLegend, revisedVChartType, theme } from './common';
3 | import type { GenerateChartCellContext } from '../../type';
4 | import type { DataCell } from '../../../../types/base';
5 |
6 | export const vennData = (context: GenerateChartCellContext) => {
7 | const { dataTable, spec, cell } = context;
8 | const id2dataMap: Record<
9 | DataCell,
10 | {
11 | sets: DataCell[];
12 | value: DataCell;
13 | }
14 | > = {};
15 | const setsField = cell.color[0];
16 | const nameField = cell.color[1];
17 | dataTable.forEach(data => {
18 | if (id2dataMap[data[setsField]]) {
19 | id2dataMap[data[setsField]].sets.push(data[nameField]);
20 | } else {
21 | id2dataMap[data[setsField]] = { sets: [data[nameField]], value: data[cell.size] };
22 | }
23 | });
24 | spec.data = {
25 | values: Object.values(id2dataMap)
26 | };
27 |
28 | return { spec };
29 | };
30 |
31 | export const vennField = (context: GenerateChartCellContext) => {
32 | const { spec } = context;
33 | spec.valueField = 'value';
34 | spec.categoryField = 'sets';
35 | spec.seriesField = 'sets';
36 | return { spec };
37 | };
38 |
39 | export const registerChart = (context: GenerateChartCellContext) => {
40 | const { spec } = context;
41 | if (spec.type === 'venn') {
42 | registerVennChart();
43 | }
44 | return { spec };
45 | };
46 |
47 | export const pipelineVenn = [registerChart, vennData, color, vennField, discreteLegend];
48 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/chartGenerator/spec/transformers/waterfall.ts:
--------------------------------------------------------------------------------
1 | import type { GenerateChartCellContext } from '../../type';
2 | import { color, data, discreteLegend, revisedVChartType, theme } from './common';
3 |
4 | export const waterfallField = (context: GenerateChartCellContext) => {
5 | //assign field in spec according to cell
6 | const { cell, spec } = context;
7 | spec.xField = cell.x;
8 | spec.yField = cell.y;
9 | spec.total = {
10 | type: 'end',
11 | text: '总计'
12 | };
13 |
14 | return { spec };
15 | };
16 |
17 | export const waterfallAxes = (context: GenerateChartCellContext) => {
18 | //assign axises
19 | const { spec } = context;
20 | spec.axes = [
21 | {
22 | orient: 'left',
23 | title: { visible: true, text: 'favorability' },
24 | label: {
25 | formatMethod: (v: any) => {
26 | return v + '%';
27 | }
28 | }
29 | },
30 | {
31 | orient: 'bottom',
32 | label: { visible: true },
33 | type: 'band',
34 | paddingInner: 0.4,
35 | title: { visible: true, text: 'date' }
36 | }
37 | ];
38 | return { spec };
39 | };
40 |
41 | export const waterfallStackLabel = (context: GenerateChartCellContext) => {
42 | //assign axises
43 | const { spec } = context;
44 | spec.stackLabel = {
45 | valueType: 'absolute',
46 | formatMethod: (text: any) => {
47 | return text + '%';
48 | }
49 | };
50 | return { spec };
51 | };
52 |
53 | export const pipelineWaterfall = [data, color, waterfallField, waterfallAxes, waterfallStackLabel, discreteLegend];
54 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/chartGenerator/spec/transformers/wordcloud.ts:
--------------------------------------------------------------------------------
1 | import { isValidDataTable } from '../../../../utils/dataTable';
2 | import type { GenerateChartCellContext } from '../../type';
3 | import { WORDCLOUD_NUM_LIMIT } from '../constants';
4 | import { color, revisedVChartType, theme } from './common';
5 |
6 | export const wordCloudData = (context: GenerateChartCellContext) => {
7 | const { dataTable, spec } = context;
8 | spec.data = {
9 | id: 'data',
10 | values: isValidDataTable(dataTable) ? dataTable.slice(0, WORDCLOUD_NUM_LIMIT) : []
11 | };
12 |
13 | return { spec };
14 | };
15 |
16 | export const wordCloudField = (context: GenerateChartCellContext) => {
17 | //assign field in spec according to cell
18 | const { cell, spec } = context;
19 | spec.nameField = cell.color;
20 |
21 | if (cell.size) {
22 | spec.valueField = cell.size;
23 | }
24 |
25 | spec.seriesField = spec.nameField;
26 |
27 | return { spec };
28 | };
29 |
30 | export const wordCloudDisplayConf = (context: GenerateChartCellContext) => {
31 | const { spec, chartTheme } = context;
32 |
33 | if (chartTheme) {
34 | return { spec };
35 | }
36 | spec.fontSizeRange = [20, 50];
37 | spec.fontWeightRange = [800, 800];
38 | //spec.wordCloudConfig = {
39 | // zoomToFit: {
40 | // enlarge: true
41 | // }
42 | //}
43 | return { spec };
44 | };
45 | export const pipelineWordCloud = [
46 | wordCloudData,
47 | color,
48 | wordCloudField,
49 | wordCloudDisplayConf
50 | //animationOneByOne,
51 | ];
52 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/customAtom/index.ts:
--------------------------------------------------------------------------------
1 | import { AtomName } from '../../types/atom';
2 | import type { CustomPromptOptions } from '../../types';
3 | import { BaseAtom } from '../base';
4 | import type { LLMMessage } from '../../types/llm';
5 | import { Factory } from '../../core/factory';
6 | import type { BaseAtomConstructor } from '../../types';
7 |
8 | export class CustomPrompt extends BaseAtom {
9 | name = AtomName.CUSTOM_PROMPT;
10 |
11 | isLLMAtom = true;
12 |
13 | constructor(context: any, option: CustomPromptOptions) {
14 | super(context, option);
15 | }
16 |
17 | getLLMMessages(query?: string): LLMMessage[] {
18 | const { text } = this.context;
19 | return [
20 | {
21 | role: 'system',
22 | content: this.options.promptTemplate
23 | },
24 | ...(this.responses || []),
25 | {
26 | role: 'user',
27 | content: query || text
28 | }
29 | ];
30 | }
31 |
32 | parseLLMContent(resJson: any, toolJson?: any): any {
33 | return {
34 | ...this.context,
35 | ...resJson,
36 | toolRes: toolJson
37 | };
38 | }
39 | }
40 |
41 | export const registerCustomPromptAtom = () => {
42 | Factory.registerAtom(
43 | AtomName.CUSTOM_PROMPT,
44 | CustomPrompt as unknown as BaseAtomConstructor
45 | );
46 | };
47 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/dataClean/index.ts:
--------------------------------------------------------------------------------
1 | export * from './multiple';
2 | export * from './dataClean';
3 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/dataExtraction/prompt/prompt.ts:
--------------------------------------------------------------------------------
1 | import type { LLMMessage } from '../../../types';
2 | import { isDoubaoModel } from '../../../utils/llm';
3 | import { getCapCutPrompt, getCapCutPromptInGpt } from './capcutPrompt';
4 | import { getBasePrompt as doubaoBasePrompt } from './doubaoPrompt';
5 | import { getBasePrompt as gptBasePrompt } from './gptPrompt';
6 | export { getFieldInfoPrompt } from './gptPrompt';
7 |
8 | export const getBasePrompt = (
9 | model: string,
10 | language: 'chinese' | 'english',
11 | isMultiple = false,
12 | showThoughs: boolean = false
13 | ) => {
14 | if (isMultiple) {
15 | return isDoubaoModel(model) ? getCapCutPrompt(language) : getCapCutPromptInGpt(language);
16 | }
17 | const func = isDoubaoModel(model) ? doubaoBasePrompt : gptBasePrompt;
18 | return func(language, showThoughs);
19 | };
20 |
21 | export const getUserQuery = (model: string, language: 'chinese' | 'english', isMultiple = false): LLMMessage[] => {
22 | if (isMultiple && !isDoubaoModel(model)) {
23 | return [
24 | {
25 | role: 'user',
26 | content: 'Extract all data'
27 | }
28 | ];
29 | }
30 | return [];
31 | };
32 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/dataInsight/const.ts:
--------------------------------------------------------------------------------
1 | export const DEFAULT_SERIES_NAME = 'vmind_default_series';
2 |
--------------------------------------------------------------------------------
/packages/vmind/src/atom/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dataClean';
2 | export * from './dataExtraction';
3 | export * from './dataQuery';
4 | export * from './dataInsight';
5 | export * from './specInsight';
6 | export * from './chartCommand';
7 | export * from './chartCommand/multiple';
8 | export * from './chartGenerator';
9 | export * from './chartQAExtraction';
10 | export * from './customAtom';
11 | export * from './base';
12 | export * from './VChartSpec';
13 | export * from './dataInsight/type';
14 | export * from './imageReader';
15 |
--------------------------------------------------------------------------------
/packages/vmind/src/core/factory.ts:
--------------------------------------------------------------------------------
1 | import type { BaseAtomConstructor, BaseContext, BaseOptions } from '../types/atom';
2 | import { BaseAtom } from '../atom/base';
3 |
4 | export class Factory {
5 | private static atoms: Record = {};
6 |
7 | static registerAtom(name: string, Ctr: BaseAtomConstructor) {
8 | this.atoms[name] = Ctr;
9 | }
10 |
11 | static getAtom(name: string) {
12 | return this.atoms[name];
13 | }
14 |
15 | static createAtom(name: string, context: Partial, options: Partial) {
16 | const Ctr = this.getAtom(name);
17 |
18 | if (Ctr) {
19 | return new Ctr(context, options);
20 | }
21 |
22 | return new BaseAtom(context, options);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/packages/vmind/src/core/memory.ts:
--------------------------------------------------------------------------------
1 | import type { LLMMessage } from '../types';
2 |
3 | export class Memory {
4 | private messages: LLMMessage[];
5 | }
6 |
--------------------------------------------------------------------------------
/packages/vmind/src/index.ts:
--------------------------------------------------------------------------------
1 | import VMind from './core/VMind';
2 |
3 | export { Model } from './types/llm';
4 | export { Schedule } from './schedule';
5 | export { LLMManage } from './core/llm';
6 | export { RAGManage } from './core/rag';
7 | export * from './types';
8 | export * from './atom';
9 | export * from './core/factory';
10 | export default VMind;
11 |
12 | import { registerDataExtractionAtom } from './atom/dataExtraction';
13 | import { registerDataCleanAtom } from './atom/dataClean';
14 | import { registerDataQueryAtom } from './atom/dataQuery';
15 | import { registerDataInsightAtom } from './atom/dataInsight';
16 | import { registerSpecInsightAtom } from './atom/specInsight';
17 | import { registerVChartSpecAtom } from './atom/VChartSpec';
18 | import { registerChartGeneratorAtom } from './atom/chartGenerator';
19 | import { registerChartCommandAtom } from './atom/chartCommand';
20 | import { registerMultipleChartCommandAtom } from './atom/chartCommand/multiple';
21 | import { registerChartQAExtractionAtom } from './atom/chartQAExtraction';
22 | import { registerCustomPromptAtom } from './atom/customAtom';
23 | import { registerImageReaderAtom } from './atom/imageReader';
24 | import { registerBaseAtom } from './atom/base';
25 |
26 | registerDataExtractionAtom();
27 | registerDataCleanAtom();
28 | registerDataQueryAtom();
29 | registerDataInsightAtom();
30 | registerSpecInsightAtom();
31 | registerVChartSpecAtom();
32 | registerChartGeneratorAtom();
33 | registerChartCommandAtom();
34 | registerMultipleChartCommandAtom();
35 | registerChartQAExtractionAtom();
36 | registerCustomPromptAtom();
37 | registerImageReaderAtom();
38 | registerBaseAtom();
39 |
--------------------------------------------------------------------------------
/packages/vmind/src/types/base.ts:
--------------------------------------------------------------------------------
1 | /** Base DataCell */
2 | export type DataCell = string | number;
3 |
4 | /** Base Data Item */
5 | export type DataItem = Record;
6 |
7 | /** Data Table */
8 | export type DataTable = DataItem[];
9 |
10 | export enum DataType {
11 | DATE = 'date',
12 | TIME = 'time',
13 | STRING = 'string',
14 | REGION = 'region',
15 | NUMERICAL = 'numerical',
16 | RATIO = 'ratio',
17 | COUNT = 'count',
18 | FLOAT = 'float',
19 | INT = 'int'
20 | }
21 |
22 | export enum ROLE {
23 | DIMENSION = 'dimension',
24 | MEASURE = 'measure'
25 | }
26 |
27 | /** field information Of Data Table */
28 | export interface FieldInfo {
29 | /** name of field */
30 | fieldName: string;
31 | /** alias of field */
32 | alias?: string;
33 | /** description of field */
34 | description?: string;
35 | /** field type, eg: time / category / numerical */
36 | type: DataType;
37 | /** field role */
38 | role: ROLE;
39 | /** field location */
40 | location?: ROLE;
41 | /** example of field value */
42 | dataExample?: DataCell[];
43 | /** domain of field value */
44 | domain?: (string | number)[];
45 | /** unit of measure field */
46 | unit?: string;
47 | /** */
48 | ratioGranularity?: '%' | '‰';
49 | /** granularity of date field */
50 | dateGranularity?: 'year' | 'quarter' | 'month' | 'week' | 'day';
51 | }
52 |
--------------------------------------------------------------------------------
/packages/vmind/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export * from './llm';
2 | export * from './atom';
3 | export * from './schedule';
4 | export * from './chart';
5 | export * from './base';
6 | export * from './utils';
7 |
--------------------------------------------------------------------------------
/packages/vmind/src/types/rag.ts:
--------------------------------------------------------------------------------
1 | export interface IRAGOptions {
2 | /** url of vector db */
3 | url: string;
4 | /** viking db name */
5 | vikingdbName: string;
6 | headers?: HeadersInit;
7 | method?: 'POST' | 'GET';
8 | }
9 |
10 | export interface RecallOptions {
11 | indexName: string;
12 | topK: number;
13 | subIndex?: string;
14 | dslQuery?: Record;
15 | isRandomRecall?: boolean;
16 | vector?: number[];
17 | sparseVector?: string[];
18 | sparseLogitAlpha?: number;
19 | missAsEmpty?: boolean;
20 | /** need get chunk manually */
21 | manualChunk?: boolean;
22 | }
23 |
24 | export interface RecallResult {
25 | scores: number;
26 | label_upper64: number;
27 | label_lower64: number;
28 | attrs: string;
29 | extraInfos: string;
30 | }
31 |
32 | export interface RawEmbeddingOptions {
33 | rawDatas: { text: string }[];
34 | }
35 |
36 | export interface RawEmbdeddingResult {
37 | vector?: number[];
38 | sparseVector?: string[];
39 | error?: string;
40 | }
41 |
42 | export type RawRecallOptions = Omit & {
43 | text: string;
44 | };
45 |
--------------------------------------------------------------------------------
/packages/vmind/src/types/utils.ts:
--------------------------------------------------------------------------------
1 | import type { FFmpeg } from '@ffmpeg/ffmpeg';
2 | import type { ManualTicker, DefaultTimeline } from '@visactor/vrender-core';
3 |
4 | export type TimeType = {
5 | totalTime: number;
6 | frameArr: any[];
7 | };
8 |
9 | export type OuterPackages = {
10 | VChart: any;
11 | FFmpeg: FFmpeg;
12 | fetchFile: (data: string | Buffer | Blob | File) => Promise;
13 | ManualTicker: typeof ManualTicker;
14 | defaultTimeline: DefaultTimeline;
15 | createCanvas: any;
16 | };
17 |
18 | export interface UnfoldTransformOptions {
19 | groupBy?: string[] | string;
20 | keyField: string;
21 | valueField: string;
22 | aggregateType?: 'sum' | 'min' | 'max' | 'count' | 'mean';
23 | }
24 |
--------------------------------------------------------------------------------
/packages/vmind/src/utils/json.ts:
--------------------------------------------------------------------------------
1 | import JSON5 from 'json5';
2 | import { jsonrepair } from 'jsonrepair';
3 | import { replaceAll } from './text';
4 |
5 | export const matchJSONStr = (str: string) => {
6 | const first = str.indexOf('{');
7 | const last = str.lastIndexOf('}');
8 | const result = str.substring(first, last + 1);
9 | return result && result.length > 0 ? replaceAll(result, '\n', ' ') : str;
10 | };
11 |
12 | export const revisedJSONStr = (str: string) => {
13 | let res = str;
14 | if (str.includes('"unit":"%""')) {
15 | res = res.replaceAll('"unit":"%""', "unit:'%'");
16 | }
17 | if (str.includes('"unit": "%""')) {
18 | res = res.replaceAll('"unit": "%""', "unit:'%'");
19 | }
20 | return res;
21 | };
22 |
23 | export const parseLLMJson = (JsonStr: string, prefix?: string) => {
24 | const parseNoPrefixStr = (str: string) => {
25 | try {
26 | return JSON5.parse(str);
27 | } catch (err) {
28 | try {
29 | return JSON5.parse(jsonrepair(str));
30 | } catch (err) {
31 | return {
32 | error: `LLM Result is not Valid JSON; llm res: ${JsonStr}`,
33 | errorInfo: err
34 | };
35 | }
36 | }
37 | };
38 | if (prefix) {
39 | const splitArr = JsonStr.split(prefix);
40 | const splittedStr = splitArr[splitArr.length - 2];
41 | const res = parseNoPrefixStr(splittedStr);
42 | if (!res.error) {
43 | return res;
44 | }
45 | }
46 | const res2 = parseNoPrefixStr(JsonStr);
47 | if (res2.error) {
48 | console.error(res2.errorInfo);
49 | }
50 | return res2;
51 | };
52 |
--------------------------------------------------------------------------------
/packages/vmind/src/utils/llm.ts:
--------------------------------------------------------------------------------
1 | export const isDoubaoModel = (model: string) => model.includes('doubao');
2 |
--------------------------------------------------------------------------------
/packages/vmind/src/utils/text.ts:
--------------------------------------------------------------------------------
1 | export const getLanguageOfText = (text: string) => {
2 | const chineseRegex = /[\u4e00-\u9fa5]/;
3 |
4 | const chineseMatch = (text || '').match(chineseRegex);
5 | if (chineseMatch) {
6 | return 'chinese';
7 | }
8 | return 'english';
9 | };
10 |
11 | export const capitalize = (str: any) => {
12 | if (typeof str !== 'string') {
13 | return '';
14 | }
15 | return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
16 | };
17 |
18 | export const replaceAll = (originStr: string, replaceStr: string, newStr: string) => {
19 | return originStr.split(replaceStr).join(newStr);
20 | };
21 |
22 | export const extractFirstNumberInString = (str: string) => {
23 | const regex = /\d+/g;
24 | const matches = str.match(regex);
25 |
26 | return matches ? matches.map(Number)[0] : null;
27 | };
28 |
--------------------------------------------------------------------------------
/packages/vmind/test-setup.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config({ path: './.env.local' });
2 | const { error, log, warn, info, debug } = require('console');
3 |
4 | global.console = {
5 | // eslint-disable-next-line no-undef
6 | //log: jest.fn(), // console.log are ignored in tests
7 | log: log,
8 |
9 | // Keep native behaviour for other methods, use those to print out things in your own tests, not `console.log`
10 | error: error,
11 | warn: warn,
12 | info: jest.fn(),
13 | debug: jest.fn()
14 | };
15 |
16 | global.TextEncoder = require('util').TextEncoder;
17 | global.TextDecoder = require('util').TextDecoder;
18 |
--------------------------------------------------------------------------------
/packages/vmind/tsconfig.eslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@internal/ts-config/tsconfig.base.json",
3 | "compilerOptions": {
4 | "types": ["jest", "node"],
5 | "lib": ["DOM", "ESNext"],
6 | "baseUrl": "./",
7 | "rootDir": "./"
8 | },
9 | "include": ["src", "__tests__"]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/vmind/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@internal/ts-config/tsconfig.base.json",
3 | "compilerOptions": {
4 | "typeRoots": ["./node_modules/@types", "./types"],
5 | "types": ["jest", "node"],
6 | "lib": ["DOM", "ESNext"],
7 | "baseUrl": "./",
8 | "rootDir": "./src",
9 | "outDir": "./esm",
10 | "composite": true,
11 | "paths": {
12 | }
13 | },
14 | "ts-node": {
15 | "transpileOnly": true,
16 | "compilerOptions": {
17 | "module": "commonjs"
18 | }
19 | },
20 | "include": ["src", "types"],
21 | "references": [
22 | {
23 | "path": "../calculator",
24 | },
25 | {
26 | "path": "../chart-advisor",
27 | }
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/packages/vmind/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "paths": {
5 | "@visactor/chart-advisor": ["../chart-advisor/src"],
6 | }
7 | },
8 | "references": [
9 | {
10 | "path": "../calculator",
11 | },
12 | {
13 | "path": "../chart-advisor",
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/packages/vmind/types/jstat.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'jstat' {
2 | const jStat: any;
3 | export default jStat;
4 | }
5 |
--------------------------------------------------------------------------------
/share/eslint-config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@internal/eslint-config",
3 | "version": "0.0.1",
4 | "description": "sharable eslint configuration settings",
5 | "private": true,
6 | "dependencies": {
7 | "@typescript-eslint/eslint-plugin": "5.30.0",
8 | "@typescript-eslint/parser": "5.30.0",
9 | "eslint-config-prettier": "8.5.0",
10 | "eslint-plugin-promise": "6.0.0",
11 | "eslint-plugin-react": "7.30.1",
12 | "eslint-plugin-react-hooks": "4.6.0"
13 | },
14 | "devDependencies": {
15 | "eslint": "~8.18.0",
16 | "typescript": "4.9.5"
17 | },
18 | "peerDependencies": {
19 | "eslint": "~8.18.0",
20 | "typescript": ">=4"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/share/eslint-config/profile/lib.js:
--------------------------------------------------------------------------------
1 | var config = require('./common')('node');
2 | module.exports = config;
3 |
--------------------------------------------------------------------------------
/share/eslint-config/profile/react.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./common')('react')
--------------------------------------------------------------------------------
/share/jest-config/jest.base.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'jsdom',
6 | testTimeout: 30000,
7 | silent: true,
8 | testMatch: ['**/__tests__/**/*.test.[jt]s'],
9 | transform: {
10 | '^.+\\.ts?$': [
11 | 'ts-jest',
12 | {
13 | resolveJsonModule: true,
14 | esModuleInterop: true,
15 | experimentalDecorators: true,
16 | module: 'ESNext',
17 | tsconfig: '/__tests__/tsconfig.json'
18 | // ts-jest configuration goes here
19 | }
20 | ]
21 | },
22 | globals: {
23 | __VERSION__: JSON.stringify('test'),
24 | __DEV__: JSON.stringify(true)
25 | },
26 | verbose: false,
27 | moduleNameMapper: {
28 | '^src/(.*)$': '/src/$1'
29 | // 'd3-color': path.resolve(__dirname, './node_modules/d3-color/dist/d3-color.min.js'),
30 | // 'd3-array': path.resolve(__dirname, './node_modules/d3-array/dist/d3-array.min.js')
31 | },
32 | coverageDirectory: 'coverage',
33 | coverageProvider: 'v8',
34 | coverageReporters: ['json-summary', 'lcov', 'text'],
35 | collectCoverageFrom: [
36 | '**/src/**',
37 | '!.rollup.cache/**',
38 | '!**/cjs/**',
39 | '!**/dist/**',
40 | '!**/es/**',
41 | '!**/node_modules/**',
42 | '!**/__tests__/**',
43 | '!**/types/**',
44 | '!**/interface.ts',
45 | '!**/*.d.ts'
46 | ],
47 | coverageThreshold: {
48 | global: {
49 | branches: 80,
50 | functions: 80,
51 | lines: 80,
52 | statements: 80
53 | }
54 | }
55 | };
56 |
--------------------------------------------------------------------------------
/share/jest-config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@internal/jest-config",
3 | "private": true,
4 | "version": "0.0.1",
5 | "dependencies": {
6 | "jsdom": "~22.1.0",
7 | "@jest/globals": "~29.5.0",
8 | "jest-environment-jsdom": "~29.5.0"
9 | },
10 | "devDependencies": {
11 | "jest": "~29.5.0",
12 | "@types/jest": "~29.5.0",
13 | "typescript": "4.9.5"
14 | },
15 | "peerDependencies": {
16 | "jest": "~29.5.0",
17 | "typescript": "4.3 - 6.x"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/share/ts-config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@internal/ts-config",
3 | "private": true,
4 | "version": "0.0.1"
5 | }
6 |
--------------------------------------------------------------------------------
/share/ts-config/tsconfig.base.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2018",
4 | "experimentalDecorators": true,
5 | "strict": true,
6 | "noImplicitAny": true,
7 | "removeComments": true,
8 | "preserveConstEnums": true,
9 | "sourceMap": false,
10 | "moduleResolution": "node",
11 | "module": "esnext",
12 | "esModuleInterop": true,
13 | "importHelpers": false,
14 | "isolatedModules": false,
15 | "noImplicitReturns": true,
16 | "noImplicitThis": true,
17 | "noUnusedParameters": false,
18 | "noUnusedLocals": false,
19 | "resolveJsonModule": true,
20 | "suppressImplicitAnyIndexErrors": true,
21 | "strictNullChecks": false,
22 | "skipLibCheck": true
23 | }
24 | }
--------------------------------------------------------------------------------
/tools/bundler/.eslintrc.js:
--------------------------------------------------------------------------------
1 | require("@rushstack/eslint-patch/modern-module-resolution");
2 |
3 | module.exports = {
4 | extends: ["@internal/eslint-config/profile/lib"],
5 | parserOptions: { tsconfigRootDir: __dirname },
6 | ignorePatterns: ["bin", "output", "vitest.config.ts", "fixtures"],
7 | };
8 |
--------------------------------------------------------------------------------
/tools/bundler/bin/index.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | "use strict";
3 |
4 | require('../output/bootstrap');
5 |
--------------------------------------------------------------------------------
/tools/bundler/fixtures/config/.gitignore:
--------------------------------------------------------------------------------
1 | es
2 | cjs
3 | dist
4 | umd
--------------------------------------------------------------------------------
/tools/bundler/fixtures/config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@foo/qux",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "compile": "tsc --noEmit"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/tools/bundler/fixtures/config/source/foo/bar/index.ts:
--------------------------------------------------------------------------------
1 | import { isObject } from '@/utils';
2 |
3 | export function bar(val: unknown) {
4 | return isObject(val);
5 | }
6 |
--------------------------------------------------------------------------------
/tools/bundler/fixtures/config/source/foo/bar/web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VisActor/VMind/556f979b7b6537b43ee2b886863ca62f419629b7/tools/bundler/fixtures/config/source/foo/bar/web.png
--------------------------------------------------------------------------------
/tools/bundler/fixtures/config/source/foo/index.ts:
--------------------------------------------------------------------------------
1 | export const Foo = 'Foo';
2 |
--------------------------------------------------------------------------------
/tools/bundler/fixtures/config/source/global.d.ts:
--------------------------------------------------------------------------------
1 | declare const __VERSION__: string;
2 | declare const __DEV__: boolean;
3 |
--------------------------------------------------------------------------------
/tools/bundler/fixtures/config/source/index.ts:
--------------------------------------------------------------------------------
1 | import { isArray } from '@/utils';
2 |
3 | export type Viking = {
4 | foo: string;
5 | };
6 |
7 | export function bar(value: unknown) {
8 | if (isArray(value)) {
9 | return value.length;
10 | }
11 | if (__DEV__) {
12 | console.log('xxx');
13 | }
14 | return 0;
15 | }
16 |
17 | export const version = __VERSION__;
18 |
--------------------------------------------------------------------------------
/tools/bundler/fixtures/config/source/utils/index.ts:
--------------------------------------------------------------------------------
1 | import { Foo } from '@/foo';
2 |
3 | export function isObject(value: unknown): value is Record {
4 | return Object.prototype.toString.call(value) === '[object Object]';
5 | }
6 |
7 | export function isArray(value: unknown): value is Array {
8 | return Object.prototype.toString.call(value) === '[object Array]';
9 | }
10 |
11 | export function isFunction(value: unknown): value is Function {
12 | return typeof value === 'function';
13 | }
14 |
15 | export const Bar = Foo;
16 |
--------------------------------------------------------------------------------
/tools/bundler/fixtures/config/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@internal/ts-config/tsconfig.base.json",
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "rootDir": "./",
6 | "outDir": "output",
7 | "target": "ES2015",
8 | "module": "ESNext",
9 | "declaration": true,
10 | "sourceMap": false,
11 | "jsx": "react-jsx",
12 | "paths": {
13 | "@/*": ["source/*"]
14 | }
15 | },
16 | "include": ["source"]
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/tools/bundler/src/global.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'gulp-clean' {
2 | const m = (opt?: { force: boolean }): NodeJS.ReadWriteStream => {};
3 | export = m;
4 | }
5 |
--------------------------------------------------------------------------------
/tools/bundler/src/index.ts:
--------------------------------------------------------------------------------
1 | export type { Config } from './logic/config';
2 | export type { RawPackageJson } from './logic/package';
3 |
4 | export { loadPackageJson } from './logic/package';
5 | export { loadConfigFile } from './logic/config';
6 |
7 | export { clean } from './tasks/clean';
8 | export { buildStyle } from './tasks/style';
9 |
--------------------------------------------------------------------------------
/tools/bundler/src/logic/babel.config.ts:
--------------------------------------------------------------------------------
1 | import type { PluginItem, TransformOptions } from '@babel/core';
2 |
3 | export type BabelPlugins = {
4 | presets: PluginItem[];
5 | plugins: PluginItem[];
6 | };
7 | export function getBabelPlugins(
8 | packageName: string,
9 | options?: {
10 | envOptions?: TransformOptions;
11 | }
12 | ): BabelPlugins {
13 | const plugins = [
14 | require.resolve('@babel/plugin-transform-private-methods'),
15 | require.resolve('@babel/plugin-proposal-export-default-from'),
16 | require.resolve('@babel/plugin-proposal-class-properties'),
17 | [
18 | require.resolve('babel-plugin-import'),
19 | {
20 | style: true,
21 | libraryName: packageName,
22 | libraryDirectory: 'es',
23 | camel2DashComponentName: false
24 | }
25 | ]
26 | ];
27 |
28 | const presets = [
29 | require.resolve('@babel/preset-react'),
30 | [require.resolve('@babel/preset-env'), { targets: 'defaults and not IE 11', ...options?.envOptions }],
31 | require.resolve('@babel/preset-typescript')
32 | ];
33 |
34 | return {
35 | presets,
36 | plugins
37 | };
38 | }
39 |
--------------------------------------------------------------------------------
/tools/bundler/src/logic/debug.ts:
--------------------------------------------------------------------------------
1 | import createDebug from 'debug';
2 |
3 | const debug = createDebug('Bundler');
4 |
5 | export const DebugConfig = debug.extend('config');
6 | export const DebugCompile = debug.extend('compile');
7 |
--------------------------------------------------------------------------------
/tools/bundler/src/logic/package.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs-extra';
2 |
3 | export type RawPackageJson = {
4 | name: string;
5 | description?: string;
6 | version: string;
7 | main?: string;
8 | scripts?: Record;
9 | repository?: Record;
10 | devDependencies?: Record;
11 | dependencies?: Record;
12 | peerDependencies?: Record;
13 | keywords?: string[];
14 | author?: string;
15 | browserslist?: string[];
16 | homepage?: string;
17 | } & Record;
18 |
19 | export function loadPackageJson(absPath: string): RawPackageJson | null {
20 | try {
21 | return fs.readJsonSync(`${absPath}/package.json`, { encoding: 'utf-8' });
22 | } catch (error) {
23 | // eslint-disable-next-line no-console
24 | console.error(error);
25 | return null;
26 | }
27 | }
28 |
29 | export function packageNameToPath(name: string) {
30 | return name.replace('@', '').replace('/', '_');
31 | }
32 |
--------------------------------------------------------------------------------
/tools/bundler/src/tasks/clean.ts:
--------------------------------------------------------------------------------
1 | import gulp from 'gulp';
2 | import gulpClean from 'gulp-clean';
3 |
4 | export function clean(folders: string[], cwd?: string) {
5 | return new Promise(resolve => {
6 | gulp
7 | .src(folders, {
8 | cwd: cwd,
9 | read: false,
10 | allowEmpty: true
11 | })
12 | .pipe(gulpClean({ force: true }))
13 | .on('finish', () => {
14 | resolve(undefined);
15 | });
16 | });
17 | }
18 |
--------------------------------------------------------------------------------
/tools/bundler/src/tasks/copy.ts:
--------------------------------------------------------------------------------
1 | import gulp from 'gulp';
2 | import path from 'path';
3 |
4 | import type { Config } from '../logic/config';
5 |
6 | export function copyFiles(projectRoot: string, config: Config) {
7 | return new Promise(resolve => {
8 | const willCopyAssets = gulp.src(config.copy.map(ext => `${projectRoot}/${config.sourceDir}/**/*.${ext}`));
9 |
10 | const esFolder = path.resolve(projectRoot, config.outputDir.es!);
11 | const cjsFolder = path.resolve(projectRoot, config.outputDir.cjs!);
12 | let stream: NodeJS.ReadableStream | undefined = undefined;
13 | if (config.formats.includes('cjs')) {
14 | stream = willCopyAssets.pipe(gulp.dest(cjsFolder));
15 | }
16 | if (config.formats.includes('es')) {
17 | stream = (stream || willCopyAssets).pipe(gulp.dest(esFolder));
18 | }
19 |
20 | stream?.on('finish', () => {
21 | resolve(undefined);
22 | });
23 | });
24 | }
25 |
--------------------------------------------------------------------------------
/tools/bundler/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@internal/ts-config/tsconfig.base.json",
3 | "ts-node": {
4 | "transpileOnly": true,
5 | "compilerOptions": {
6 | "declaration": true,
7 | "sourceMap": true
8 | }
9 | },
10 | "compilerOptions": {
11 | "baseUrl": ".",
12 | "outDir": "output",
13 | "target": "ES2015",
14 | "module": "CommonJS",
15 | "declaration": true,
16 | "sourceMap": false
17 | },
18 | "include": [
19 | "src"
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/tools/bundler/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vitest/config';
2 |
3 | export default defineConfig({
4 | test: {
5 | include: ['src/**/*.{test,spec}.ts']
6 | }
7 | });
8 |
--------------------------------------------------------------------------------
/tools/typescript-json-schema/bin/typescript-json-schema:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | var app = require('../dist/typescript-json-schema-cli.js');
3 | app.run();
4 |
--------------------------------------------------------------------------------
/tools/typescript-json-schema/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@internal/typescript-json-schema",
3 | "version": "0.0.1",
4 | "private": true,
5 | "description": "typescript-json-schema generates JSON Schema files from your Typescript sources",
6 | "main": "dist/typescript-json-schema.js",
7 | "typings": "dist/typescript-json-schema.d.ts",
8 | "bin": {
9 | "schema": "./bin/typescript-json-schema"
10 | },
11 | "dependencies": {
12 | "@types/json-schema": "^7.0.9",
13 | "@types/node": "*",
14 | "glob": "^7.1.7",
15 | "path-equal": "^1.2.5",
16 | "safe-stable-stringify": "^2.2.0",
17 | "ts-node": "^10.9.2",
18 | "typescript": "4.9.5",
19 | "yargs": "^17.1.1"
20 | },
21 | "devDependencies": {
22 | "@types/chai": "^4.2.21",
23 | "@types/glob": "^7.1.4",
24 | "@types/mocha": "^9.0.0",
25 | "ajv": "^8.12.0",
26 | "ajv-formats": "^2.1.1",
27 | "chai": "^4.3.4",
28 | "mocha": "^9.1.3",
29 | "source-map-support": "^0.5.20"
30 | },
31 | "scripts": {
32 | "postinstall": "npm run build",
33 | "prepublishOnly": "npm run build",
34 | "debug": "node --inspect=19248 --inspect-brk -r ts-node/register typescript-json-schema-cli.ts",
35 | "run": "rm -rf ./dist && ts-node typescript-json-schema-cli.ts",
36 | "build": "tsc",
37 | "dev": "tsc -w",
38 | "test:dev": "mocha -t 5000 --watch --require source-map-support/register dist/test"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/tools/typescript-json-schema/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "moduleResolution": "node",
6 | "outDir": "dist",
7 | "isolatedModules": false,
8 | "experimentalDecorators": true,
9 | "emitDecoratorMetadata": true,
10 | "declaration": true,
11 | "noImplicitAny": true,
12 | "suppressImplicitAnyIndexErrors": true,
13 | "strictNullChecks": true,
14 | "noImplicitReturns": true,
15 | "noFallthroughCasesInSwitch": true,
16 | "noUnusedLocals": true,
17 | "noUnusedParameters": true,
18 | "removeComments": true,
19 | "noLib": false,
20 | "preserveConstEnums": true,
21 | "sourceMap": true,
22 | "watch": false,
23 | "typeRoots": ["node_modules/@types"]
24 | },
25 | "include": ["**/*.ts", "node_modules/@types/**/*.d.ts"],
26 | "exclude": ["node_modules", "dist"],
27 | "compileOnSave": true,
28 | "buildOnSave": false
29 | }
30 |
--------------------------------------------------------------------------------