visualifyjs 2.5.3 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/mem/TIMELINE.md +36 -0
- package/.claude/mem/notes/2026-02-11-3d-visualization-docs-fix-external-script-solution.md +24 -0
- package/.claude/mem/notes/2026-02-11-3d-visualization-docs-fix-session-summary.md +43 -0
- package/.claude/mem/notes/2026-02-11-cli-fix-editor-command-alias.md +26 -0
- package/.claude/mem/notes/2026-02-11-phase-3-developer-experience-completed.md +51 -0
- package/.claude/mem/notes/2026-02-11-phase-4-web-workers-implementation-complete.md +59 -0
- package/.claude/mem/notes/2026-02-11-visualify-phase-2-3d-visualization-complete.md +50 -0
- package/.claude/mem/notes/2026-02-11-visualify-phase-2-committed-ready-for-phase-3.md +33 -0
- package/.claude/mem/notes/2026-02-11-visualify-phase-3-complete-developer-experience.md +52 -0
- package/.claude/mem/notes/2026-02-11-visualify-repository-cleanup-complete.md +28 -0
- package/.claude/mem/notes/2026-02-18-codebase-cleanup-docsify-plugin-documentation.md +37 -0
- package/.claude/mem/notes/2026-02-19-css-grid-layout-fix-displaycontents-on-vcontroller.md +18 -0
- package/.claude/mem/notes/2026-02-19-docsify-plugin-fixes-latex-and-visualify-code-bloc.md +26 -0
- package/.claude/mem/notes/2026-02-19-page-mode-docs-update-decisions.md +23 -0
- package/.claude/mem/notes/2026-02-19-react-context-infinite-re-render-loop-fix-pattern.md +31 -0
- package/.claude/mem/notes/2026-02-19-version-300-bump-and-build-fixes.md +32 -0
- package/.claude/mem/notes/2026-02-19-visualify-build-deployment-architecture-bug-fixes.md +25 -0
- package/.claude/mem/notes/2026-02-19-visualify-dist-iife-self-contained-build-config.md +30 -0
- package/.claude/mem/notes/2026-02-19-visualify-infinite-loop-i18n-fixes.md +31 -0
- package/.claude/mem/notes/2026-02-19-visualify-v3-bundle-splitting-docs-restructuring.md +32 -0
- package/.claude/mem/notes/2026-02-20-bundle-externalization-final-architecture.md +29 -0
- package/.claude/mem/notes/2026-02-20-chromium-page-fix-unstable-keys-and-double-event-b.md +27 -0
- package/.claude/mem/notes/2026-02-20-console-cleanup-bundle-optimization-commit.md +20 -0
- package/.claude/mem/notes/2026-02-20-dotbio-dot-plot-fix-useeffect-dependency.md +21 -0
- package/.claude/mem/notes/2026-02-20-public-folder-cleanup-and-readme-rewrite.md +25 -0
- package/.claude/mem/notes/2026-02-20-v300-release-and-beta-channel-strategy.md +29 -0
- package/.claude/mem/notes/2026-02-20-visium-background-image-unknown-legend-fix.md +19 -0
- package/.claude/mem/notes/2026-02-20-visualify-cdn-loader-bundle-externalization.md +34 -0
- package/.claude/mem/sessions/session-2026-02-20-031524.md +54 -0
- package/.claude/settings.local.json +21 -0
- package/.github/workflows/static.yml.bak +51 -51
- package/.sisyphus/boulder.json +65 -0
- package/.sisyphus/plans/phase-4-advanced-optimizations.md +217 -0
- package/LICENSE +674 -674
- package/README.md +94 -59
- package/config-overrides.js +31 -31
- package/dist/stats.html +4949 -0
- package/dist/visualify-3d.esm.js +1 -0
- package/dist/visualify-3d.js +1 -0
- package/dist/visualify-core.esm.js +1 -0
- package/dist/visualify-core.js +1 -0
- package/dist/visualify-docs.esm.js +1 -0
- package/dist/visualify-docs.js +1 -0
- package/dist/visualify-loader.js +1 -0
- package/dist/visualify-pages.esm.js +1 -0
- package/dist/visualify-pages.js +1 -0
- package/dist/visualify-portal.esm.js +1 -0
- package/dist/visualify-portal.js +1 -0
- package/dist/visualify-shared.js +26571 -0
- package/dist/visualify.js +1 -188
- package/docs/CHANGELOG.md +148 -0
- package/docs/cli/commands.md +513 -0
- package/docs/configuration/visualify-json.md +474 -0
- package/docs/docs/3d-visualization.md +374 -0
- package/docs/docs/CLI.md +303 -34
- package/docs/docs/README.md +65 -65
- package/docs/docs/Rechart/bar.md +190 -190
- package/docs/docs/Rechart/funnel.md +241 -193
- package/docs/docs/Rechart/line.md +355 -355
- package/docs/docs/Rechart/pie.md +225 -225
- package/docs/docs/Rechart/radar.md +253 -253
- package/docs/docs/Rechart/scatter.md +298 -0
- package/docs/docs/_404.md +51 -51
- package/docs/docs/_coverpage.md +11 -11
- package/docs/docs/_sidebar.md +54 -43
- package/docs/docs/components/dotBio.md +87 -34
- package/docs/docs/components/echart.md +171 -82
- package/docs/docs/components/html.md +61 -34
- package/docs/docs/components/macaron.md +156 -145
- package/docs/docs/components/markdown.md +42 -0
- package/docs/docs/components/more.md +183 -142
- package/docs/docs/components/plotly.md +132 -62
- package/docs/docs/components/scatterL.md +171 -70
- package/docs/docs/components/visium.md +112 -57
- package/docs/docs/configuration.md +121 -123
- package/docs/docs/deploy.md +31 -31
- package/docs/docs/docsify-plugin.md +655 -0
- package/docs/docs/hmr.md +165 -0
- package/docs/docs/i18n.md +332 -0
- package/docs/docs/log.md +30 -1
- package/docs/docs/more-pages.md +23 -23
- package/docs/docs/quickstart.md +148 -119
- package/docs/docs/rechart-attributes.md +74 -74
- package/docs/docs/rechart-basic-usage.md +160 -162
- package/docs/docs/theme.md +5 -5
- package/docs/docs/typescript.md +306 -0
- package/docs/docs/visual-editor.md +359 -0
- package/docs/index.html +85 -71
- package/docs/manifest.json +23 -23
- package/docs/migration/v3-migration.md +392 -0
- package/docs/static/css/fluff-stuff.css +169 -169
- package/docs/static/css/font-awesome.min.css +4 -4
- package/docs/static/css/visualify.css +6 -25
- package/docs/static/js/3d-viz-examples.js +181 -0
- package/docs/static/js/configuration.js +630 -448
- package/docs/static/js/visualify.js +1 -188
- package/package.json +106 -84
- package/rollup.config.mjs +766 -76
- package/src/_css/404.css +115 -115
- package/src/_css/App.css +37 -37
- package/src/_css/autoSuggestion.css +26 -26
- package/src/_css/circular-progress.css +32 -32
- package/src/_css/index.css +36 -36
- package/src/_css/modern.css +350 -25
- package/src/_media/corner.svg +8 -8
- package/src/_media/download.svg +3 -3
- package/src/_media/logo.svg +14 -14
- package/src/_test/App.test.js +15 -15
- package/src/_utils/reportWebVitals.js +13 -13
- package/src/a11y/README.md +177 -0
- package/src/a11y/aria-labels.js +339 -0
- package/src/a11y/color-contrast.js +535 -0
- package/src/a11y/index.js +197 -0
- package/src/a11y/keyboard-nav.js +523 -0
- package/src/a11y/styles.css +165 -0
- package/src/cli/commands/dev.js +214 -0
- package/src/cli/commands/docs.js +521 -0
- package/src/cli/commands/edit.js +379 -0
- package/src/cli/commands/init.js +213 -0
- package/src/cli/commands/portal.js +236 -0
- package/src/cli/dev-server.js +530 -0
- package/src/cli/hmr.js +456 -0
- package/src/cli/index.js +180 -0
- package/src/cli/utils/config.js +207 -0
- package/src/cli/utils/logger.js +241 -0
- package/src/config/defaults.ts +122 -0
- package/src/config/index.ts +72 -0
- package/src/config/loader.ts +478 -0
- package/src/config/schema.ts +227 -0
- package/src/config/validator.ts +337 -0
- package/src/core/appContext.js +34 -27
- package/src/core/components/Bar.js +383 -0
- package/src/core/components/Bar3D.js +473 -0
- package/src/core/components/LargeDatasetChart.js +296 -0
- package/src/core/components/Line3D.js +310 -0
- package/src/core/components/Scatter.js +392 -188
- package/src/core/components/Scatter3D.js +455 -0
- package/src/core/components/ScatterBio.js +601 -572
- package/src/core/components/Surface3D.js +326 -0
- package/src/core/components/ThreeCustom.js +648 -0
- package/src/core/components/ThreeScene.js +459 -0
- package/src/core/components/VisiumPlot.js +191 -165
- package/src/core/components/browser.js +42 -42
- package/src/core/components/dotplot.js +413 -413
- package/src/core/components/html.js +29 -29
- package/src/core/components/list.js +178 -178
- package/src/core/components/macaron.js +206 -201
- package/src/core/components/markdown.js +56 -56
- package/src/core/components/parser.scatterBio.js +582 -579
- package/src/core/components/ratio.js +82 -80
- package/src/core/components/scatterL.js +206 -173
- package/src/core/components/searchbar.js +156 -131
- package/src/core/components/selection.js +310 -193
- package/src/core/components/timeline.js +236 -281
- package/src/core/components/visium.js +114 -97
- package/src/core/data-processor.js +413 -0
- package/src/core/fetch/condfetch.js +82 -82
- package/src/core/fetch/fetch.js +92 -92
- package/src/core/fetch/json.js +29 -29
- package/src/core/fetch/vfetch.js +42 -42
- package/src/core/hmr-client.js +724 -0
- package/src/core/liveEditor.js +44 -44
- package/src/core/modules/codeEditorWithPreview.js +104 -104
- package/src/core/modules/echarts/common.js +20 -20
- package/src/core/modules/echarts/gl.js +228 -0
- package/src/core/modules/echarts/presetHandler.js +41 -41
- package/src/core/modules/echarts/presets/esodev.chromium.js +172 -172
- package/src/core/modules/echarts/presets/esodev.codex.js +130 -130
- package/src/core/modules/echarts/presets/esodev.visium.js +123 -123
- package/src/core/modules/echarts/presets/mmtrbc.js +186 -186
- package/src/core/modules/echarts.js +70 -71
- package/src/core/modules/echartsUtils.js +43 -43
- package/src/core/modules/echartswitcher.js +227 -152
- package/src/core/modules/replotly/presetHandler.js +24 -24
- package/src/core/modules/replotly/presets/minimum.js +18 -18
- package/src/core/modules/replotly/presets/mmtrbc.dot.js +114 -114
- package/src/core/modules/replotly/presets/mmtrbc.violin.js +100 -100
- package/src/core/modules/replotly.js +74 -71
- package/src/core/modules/threejs/Camera.js +373 -0
- package/src/core/modules/threejs/Lighting.js +459 -0
- package/src/core/modules/threejs/Renderer.js +364 -0
- package/src/core/modules/threejs/Scene.js +266 -0
- package/src/core/modules/threejs/index.js +155 -0
- package/src/core/pages/404.js +50 -50
- package/src/core/pages/error.js +27 -27
- package/src/core/pages/jsonPage.js +62 -62
- package/src/core/pages/loading.js +44 -44
- package/src/core/parser/echart.data.js +204 -183
- package/src/core/parser/echart.features.js +125 -125
- package/src/core/parser/echart.general.js +147 -143
- package/src/core/parser/echart.hilbert.js +57 -57
- package/src/core/parser/echart.parser.js +210 -210
- package/src/core/parser/echart.series.js +67 -67
- package/src/core/parser/echart.types.js +76 -76
- package/src/core/parser/plotly.config.js +10 -10
- package/src/core/parser/plotly.data.js +132 -132
- package/src/core/parser/plotly.layout.js +9 -9
- package/src/core/parser/plotly.violin.js +18 -18
- package/src/core/recharts.js +361 -62
- package/src/core/router/alias.js +49 -49
- package/src/core/router/jsonRouter.js +31 -31
- package/src/core/themes/modern.js +32 -32
- package/src/core/themes/themeSelector.js +33 -33
- package/src/core/visualify.js +213 -47
- package/src/core/widgets/circularProgress.js +23 -23
- package/src/core/widgets/controller.js +116 -83
- package/src/core/widgets/errorBoundary.js +36 -36
- package/src/core/widgets/footer.js +185 -177
- package/src/core/widgets/header.js +238 -234
- package/src/core/widgets/layout/Grid.js +31 -31
- package/src/core/widgets/layout.js +36 -36
- package/src/core/widgets/mapping.js +56 -42
- package/src/core/workers/data-worker.js +349 -0
- package/src/core/workers/worker-pool.js +396 -0
- package/src/docsify/bundle.js +215 -0
- package/src/docsify/markdown.js +271 -0
- package/src/docsify/plugin.js +268 -0
- package/src/editor/README.md +172 -0
- package/src/editor/components/ChartBuilder.jsx +341 -0
- package/src/editor/components/ChartTypeSidebar.jsx +91 -0
- package/src/editor/components/Editor.jsx +367 -0
- package/src/editor/components/Preview.jsx +446 -0
- package/src/editor/components/PropertyPanel.jsx +468 -0
- package/src/editor/components/StatusBar.jsx +85 -0
- package/src/editor/context/EditorContext.js +248 -0
- package/src/editor/hooks/useDebounce.js +32 -0
- package/src/editor/index.js +315 -0
- package/src/editor/styles/editor.css +637 -0
- package/src/editor/utils/chartValidator.js +263 -0
- package/src/entries/charts3d.js +70 -0
- package/src/entries/core.js +78 -0
- package/src/entries/docs.js +154 -0
- package/src/entries/pages.js +93 -0
- package/src/entries/portal.js +204 -0
- package/src/entries/shared.js +50 -0
- package/src/i18n/formatters.js +455 -0
- package/src/i18n/index.js +169 -0
- package/src/i18n/locales/ar.json +137 -0
- package/src/i18n/locales/de.json +137 -0
- package/src/i18n/locales/en.json +137 -0
- package/src/i18n/locales/es.json +137 -0
- package/src/i18n/locales/he.json +137 -0
- package/src/i18n/locales/zh.json +137 -0
- package/src/i18n/rtl.css +183 -0
- package/src/index.js +82 -62
- package/src/loader.js +103 -0
- package/src/setupTests.js +5 -5
- package/tsconfig.json +51 -0
- package/types/charts.d.ts +569 -0
- package/types/components.d.ts +441 -0
- package/types/config.d.ts +199 -0
- package/types/index.d.ts +353 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration validation logic using AJV with i18n support
|
|
3
|
+
* @module validator
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import Ajv from 'ajv';
|
|
7
|
+
import type { ErrorObject, Options as AjvOptions } from 'ajv';
|
|
8
|
+
import schema from './schema';
|
|
9
|
+
import { ValidationError, ValidationResult, VisualifyConfig } from '../../types';
|
|
10
|
+
|
|
11
|
+
// i18n support for validation messages
|
|
12
|
+
let currentLocale = 'en';
|
|
13
|
+
const translations: Record<string, Record<string, string>> = {
|
|
14
|
+
en: {
|
|
15
|
+
'required': "Missing required property '{property}'",
|
|
16
|
+
'type': "Property '{property}' should be {expected}, received {received}",
|
|
17
|
+
'enum': "Property '{property}' must be one of: {values}",
|
|
18
|
+
'minLength': "Property '{property}' cannot be empty",
|
|
19
|
+
'format': "Property '{property}' has invalid format",
|
|
20
|
+
'additionalProperties': "Unknown property '{property}'",
|
|
21
|
+
'configObject': 'Configuration must be an object',
|
|
22
|
+
'configObjectSuggestion': 'Provide a valid JSON object with configuration properties',
|
|
23
|
+
},
|
|
24
|
+
zh: {
|
|
25
|
+
'required': "缺少必需属性'{property}'",
|
|
26
|
+
'type': "属性'{property}'应为{expected},实际为{received}",
|
|
27
|
+
'enum': "属性'{property}'必须是以下之一:{values}",
|
|
28
|
+
'minLength': "属性'{property}'不能为空",
|
|
29
|
+
'format': "属性'{property}'格式无效",
|
|
30
|
+
'additionalProperties': "未知属性'{property}'",
|
|
31
|
+
'configObject': '配置必须是一个对象',
|
|
32
|
+
'configObjectSuggestion': '提供一个包含配置属性的有效JSON对象',
|
|
33
|
+
},
|
|
34
|
+
es: {
|
|
35
|
+
'required': "Falta la propiedad obligatoria '{property}'",
|
|
36
|
+
'type': "La propiedad '{property}' debería ser {expected}, se recibió {received}",
|
|
37
|
+
'enum': "La propiedad '{property}' debe ser una de: {values}",
|
|
38
|
+
'minLength': "La propiedad '{property}' no puede estar vacía",
|
|
39
|
+
'format': "La propiedad '{property}' tiene un formato inválido",
|
|
40
|
+
'additionalProperties': "Propiedad desconocida '{property}'",
|
|
41
|
+
'configObject': 'La configuración debe ser un objeto',
|
|
42
|
+
'configObjectSuggestion': 'Proporcione un objeto JSON válido con propiedades de configuración',
|
|
43
|
+
},
|
|
44
|
+
de: {
|
|
45
|
+
'required': "Eigenschaft '{property}' ist erforderlich",
|
|
46
|
+
'type': "Eigenschaft '{property}' sollte {expected} sein, empfangen wurde {received}",
|
|
47
|
+
'enum': "Eigenschaft '{property}' muss einer der folgenden sein: {values}",
|
|
48
|
+
'minLength': "Eigenschaft '{property}' darf nicht leer sein",
|
|
49
|
+
'format': "Eigenschaft '{property}' hat ein ungültiges Format",
|
|
50
|
+
'additionalProperties': "Unbekannte Eigenschaft '{property}'",
|
|
51
|
+
'configObject': 'Konfiguration muss ein Objekt sein',
|
|
52
|
+
'configObjectSuggestion': 'Geben Sie ein gültiges JSON-Objekt mit Konfigurationseigenschaften an',
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Set the current locale for validation messages
|
|
58
|
+
* @param locale - Locale code
|
|
59
|
+
*/
|
|
60
|
+
export function setValidationLocale(locale: string): void {
|
|
61
|
+
currentLocale = locale;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get the current locale
|
|
66
|
+
* @returns Current locale code
|
|
67
|
+
*/
|
|
68
|
+
export function getValidationLocale(): string {
|
|
69
|
+
return currentLocale;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Translate a key with interpolation
|
|
74
|
+
* @param key - Translation key
|
|
75
|
+
* @param params - Interpolation parameters
|
|
76
|
+
* @returns Translated string
|
|
77
|
+
*/
|
|
78
|
+
function t(key: string, params: Record<string, string> = {}): string {
|
|
79
|
+
const messages = translations[currentLocale] || translations['en'];
|
|
80
|
+
let message = messages[key] || key;
|
|
81
|
+
|
|
82
|
+
Object.keys(params).forEach((param) => {
|
|
83
|
+
message = message.replace(new RegExp(`{${param}}`, 'g'), params[param]);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return message;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Error message templates for common validation errors
|
|
91
|
+
*/
|
|
92
|
+
const ERROR_TEMPLATES: Record<string, string> = {
|
|
93
|
+
required: "Missing required property '{property}'",
|
|
94
|
+
type: "Property '{property}' should be {expected}, received {received}",
|
|
95
|
+
enum: "Property '{property}' must be one of: {values}",
|
|
96
|
+
minLength: "Property '{property}' cannot be empty",
|
|
97
|
+
format: "Property '{property}' has invalid format",
|
|
98
|
+
additionalProperties: "Unknown property '{property}'",
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Suggested fixes for common errors
|
|
103
|
+
* Maps property paths to fix functions
|
|
104
|
+
*/
|
|
105
|
+
const SUGGESTED_FIXES: Record<
|
|
106
|
+
string,
|
|
107
|
+
(error: ErrorObject) => string | null
|
|
108
|
+
> = {
|
|
109
|
+
version: (error: ErrorObject): string | null => {
|
|
110
|
+
if (error.keyword === 'enum') {
|
|
111
|
+
return "Set version to '3.0.0'";
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
},
|
|
115
|
+
mode: (error: ErrorObject): string | null => {
|
|
116
|
+
if (error.keyword === 'enum') {
|
|
117
|
+
return "Use one of: 'docs', 'portal', 'hybrid', 'auto'";
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
},
|
|
121
|
+
defaultLibrary: (error: ErrorObject): string | null => {
|
|
122
|
+
if (error.keyword === 'enum') {
|
|
123
|
+
return "Use either 'echarts' or 'plotly'";
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
},
|
|
127
|
+
'docs.basePath': (): string => "Use a relative path like './docs' or './documentation'",
|
|
128
|
+
'docs.theme': (): string => "Available themes: 'vue', 'modern', 'classic'",
|
|
129
|
+
'portal.homepage': (): string => "Use a filename like 'home.json' or 'index.json'",
|
|
130
|
+
'portal.dataSources': (error: ErrorObject): string | null => {
|
|
131
|
+
if (error.keyword === 'required') {
|
|
132
|
+
return "Each data source needs 'name' and 'type' properties";
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Validation options
|
|
140
|
+
*/
|
|
141
|
+
interface ValidateOptions {
|
|
142
|
+
/** Source identifier for error context */
|
|
143
|
+
source?: string;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Initialize AJV instance with configuration
|
|
148
|
+
* @returns Configured AJV instance
|
|
149
|
+
*/
|
|
150
|
+
function createValidator(): InstanceType<typeof Ajv> {
|
|
151
|
+
const options: AjvOptions = {
|
|
152
|
+
allErrors: true,
|
|
153
|
+
verbose: true,
|
|
154
|
+
};
|
|
155
|
+
return new Ajv(options);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Format a single validation error into a readable message
|
|
160
|
+
* @param error - AJV error object
|
|
161
|
+
* @param configSource - Source of the configuration (for context)
|
|
162
|
+
* @returns Formatted error with message, path, and suggestion
|
|
163
|
+
*/
|
|
164
|
+
function formatError(error: ErrorObject, configSource = 'config'): ValidationError {
|
|
165
|
+
// Handle both AJV v6 (dataPath) and v8+ (instancePath) property names
|
|
166
|
+
const instancePath = (error as { instancePath?: string; dataPath?: string }).instancePath
|
|
167
|
+
|| (error as { dataPath?: string }).dataPath
|
|
168
|
+
|| '';
|
|
169
|
+
const path = instancePath
|
|
170
|
+
? instancePath.slice(1).replace(/\//g, '.')
|
|
171
|
+
: (error.params as { missingProperty?: string }).missingProperty || 'root';
|
|
172
|
+
|
|
173
|
+
const property = path.split('.').pop() || 'root';
|
|
174
|
+
|
|
175
|
+
// Build base message using i18n
|
|
176
|
+
const params = error.params as Record<string, unknown>;
|
|
177
|
+
let message = t(error.keyword, {
|
|
178
|
+
property: path,
|
|
179
|
+
expected: params.type as string,
|
|
180
|
+
received: typeof error.data,
|
|
181
|
+
values: (params.allowedValues as string[])?.join(', '),
|
|
182
|
+
}) || ERROR_TEMPLATES[error.keyword] || error.message || 'Validation error';
|
|
183
|
+
|
|
184
|
+
// Get suggestion if available
|
|
185
|
+
const suggestionKey = Object.keys(SUGGESTED_FIXES).find(
|
|
186
|
+
(key) => path === key || path.endsWith(`.${key}`)
|
|
187
|
+
);
|
|
188
|
+
const suggestion = suggestionKey
|
|
189
|
+
? SUGGESTED_FIXES[suggestionKey](error as ErrorObject)
|
|
190
|
+
: null;
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
path,
|
|
194
|
+
property,
|
|
195
|
+
message,
|
|
196
|
+
suggestion,
|
|
197
|
+
keyword: error.keyword,
|
|
198
|
+
value: error.data,
|
|
199
|
+
source: configSource,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Validate configuration against the schema
|
|
205
|
+
* @param config - Configuration object to validate
|
|
206
|
+
* @param options - Validation options
|
|
207
|
+
* @returns Validation result with valid flag, errors array, and summary
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```typescript
|
|
211
|
+
* const result = validateConfig({
|
|
212
|
+
* version: '3.0.0',
|
|
213
|
+
* mode: 'docs'
|
|
214
|
+
* });
|
|
215
|
+
*
|
|
216
|
+
* if (!result.valid) {
|
|
217
|
+
* console.error(result.errors[0].message);
|
|
218
|
+
* if (result.errors[0].suggestion) {
|
|
219
|
+
* console.log('Suggestion:', result.errors[0].suggestion);
|
|
220
|
+
* }
|
|
221
|
+
* }
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
function validateConfig(
|
|
225
|
+
config: unknown,
|
|
226
|
+
options: ValidateOptions = {}
|
|
227
|
+
): ValidationResult {
|
|
228
|
+
const { source = 'config' } = options;
|
|
229
|
+
|
|
230
|
+
// Check if config is an object
|
|
231
|
+
if (config === null || typeof config !== 'object') {
|
|
232
|
+
return {
|
|
233
|
+
valid: false,
|
|
234
|
+
errors: [
|
|
235
|
+
{
|
|
236
|
+
path: 'root',
|
|
237
|
+
property: 'root',
|
|
238
|
+
message: t('configObject'),
|
|
239
|
+
suggestion: t('configObjectSuggestion'),
|
|
240
|
+
keyword: 'type',
|
|
241
|
+
value: config,
|
|
242
|
+
source,
|
|
243
|
+
},
|
|
244
|
+
],
|
|
245
|
+
summary: t('configObject'),
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const ajv = createValidator();
|
|
250
|
+
const validate = ajv.compile(schema);
|
|
251
|
+
const valid = validate(config);
|
|
252
|
+
|
|
253
|
+
if (valid) {
|
|
254
|
+
return {
|
|
255
|
+
valid: true,
|
|
256
|
+
errors: [],
|
|
257
|
+
summary: null,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const errors = (validate.errors || []).map((error: ErrorObject) => formatError(error, source));
|
|
262
|
+
|
|
263
|
+
// Build summary message
|
|
264
|
+
const errorCount = errors.length;
|
|
265
|
+
const summary =
|
|
266
|
+
errorCount === 1
|
|
267
|
+
? `1 validation error: ${errors[0].message}`
|
|
268
|
+
: `${errorCount} validation errors found`;
|
|
269
|
+
|
|
270
|
+
return {
|
|
271
|
+
valid: false,
|
|
272
|
+
errors,
|
|
273
|
+
summary,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Validate a specific configuration property
|
|
279
|
+
* @param path - Dot-notation path to the property
|
|
280
|
+
* @param value - Value to validate
|
|
281
|
+
* @returns Validation result for the property
|
|
282
|
+
*/
|
|
283
|
+
function validateProperty(path: string, value: unknown): ValidationResult {
|
|
284
|
+
const pathParts = path.split('.');
|
|
285
|
+
|
|
286
|
+
// Build minimal config with the property
|
|
287
|
+
const config = pathParts.reduceRight((acc, part, index) => {
|
|
288
|
+
if (index === pathParts.length - 1) {
|
|
289
|
+
return { [part]: value };
|
|
290
|
+
}
|
|
291
|
+
return { [part]: acc };
|
|
292
|
+
}, {} as Record<string, unknown>);
|
|
293
|
+
|
|
294
|
+
// Add required version
|
|
295
|
+
(config as Record<string, unknown>).version = '3.0.0';
|
|
296
|
+
|
|
297
|
+
return validateConfig(config, { source: `property:${path}` });
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Check if a version is compatible with the current schema
|
|
302
|
+
* @param version - Version string to check
|
|
303
|
+
* @returns True if compatible
|
|
304
|
+
*/
|
|
305
|
+
function isVersionCompatible(version: string): boolean {
|
|
306
|
+
return version === '3.0.0';
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Type guard to check if a value is a valid VisualifyConfig
|
|
311
|
+
* @param value - Value to check
|
|
312
|
+
* @returns True if value is a valid VisualifyConfig
|
|
313
|
+
*/
|
|
314
|
+
function isValidConfig(value: unknown): value is VisualifyConfig {
|
|
315
|
+
const result = validateConfig(value);
|
|
316
|
+
return result.valid;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export {
|
|
320
|
+
validateConfig,
|
|
321
|
+
validateProperty,
|
|
322
|
+
isVersionCompatible,
|
|
323
|
+
isValidConfig,
|
|
324
|
+
ERROR_TEMPLATES,
|
|
325
|
+
SUGGESTED_FIXES,
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
export default {
|
|
329
|
+
validateConfig,
|
|
330
|
+
validateProperty,
|
|
331
|
+
isVersionCompatible,
|
|
332
|
+
isValidConfig,
|
|
333
|
+
setValidationLocale,
|
|
334
|
+
getValidationLocale,
|
|
335
|
+
ERROR_TEMPLATES,
|
|
336
|
+
SUGGESTED_FIXES,
|
|
337
|
+
};
|
package/src/core/appContext.js
CHANGED
|
@@ -1,27 +1,34 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @Author : Lihao leolihao@arizona.edu
|
|
3
|
-
* @Date : 2023-12-23 15:50:00
|
|
4
|
-
* @FilePath : /visualifyjs/src/core/appContext.js
|
|
5
|
-
* @Description :
|
|
6
|
-
* Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
|
|
7
|
-
*/
|
|
8
|
-
import React, { createContext, useContext, useState } from 'react';
|
|
9
|
-
|
|
10
|
-
// Create the AppContext
|
|
11
|
-
const Visualify = createContext();
|
|
12
|
-
|
|
13
|
-
// Create a custom hook for accessing the AppContext
|
|
14
|
-
export function useAppContext() {
|
|
15
|
-
return useContext(Visualify);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Create the AppProvider component to wrap your app with the context
|
|
19
|
-
export function VisualifyProvider({ children }) {
|
|
20
|
-
const [sharedData, setSharedData] = useState({}); // Initialize your shared data here
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
1
|
+
/*
|
|
2
|
+
* @Author : Lihao leolihao@arizona.edu
|
|
3
|
+
* @Date : 2023-12-23 15:50:00
|
|
4
|
+
* @FilePath : /visualifyjs/src/core/appContext.js
|
|
5
|
+
* @Description :
|
|
6
|
+
* Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
|
|
7
|
+
*/
|
|
8
|
+
import React, { createContext, useContext, useState, useMemo } from 'react';
|
|
9
|
+
|
|
10
|
+
// Create the AppContext
|
|
11
|
+
const Visualify = createContext();
|
|
12
|
+
|
|
13
|
+
// Create a custom hook for accessing the AppContext
|
|
14
|
+
export function useAppContext() {
|
|
15
|
+
return useContext(Visualify);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Create the AppProvider component to wrap your app with the context
|
|
19
|
+
export function VisualifyProvider({ children }) {
|
|
20
|
+
const [sharedData, setSharedData] = useState({}); // Initialize your shared data here
|
|
21
|
+
|
|
22
|
+
// Memoize the context value to prevent unnecessary re-renders
|
|
23
|
+
// Only creates a new object when sharedData actually changes
|
|
24
|
+
const contextValue = useMemo(
|
|
25
|
+
() => ({ sharedData, setSharedData }),
|
|
26
|
+
[sharedData],
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<Visualify.Provider value={contextValue}>
|
|
31
|
+
{children}
|
|
32
|
+
</Visualify.Provider>
|
|
33
|
+
);
|
|
34
|
+
}
|