visualifyjs 2.5.3-2.dev → 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.
Files changed (252) hide show
  1. package/.claude/mem/TIMELINE.md +36 -0
  2. package/.claude/mem/notes/2026-02-11-3d-visualization-docs-fix-external-script-solution.md +24 -0
  3. package/.claude/mem/notes/2026-02-11-3d-visualization-docs-fix-session-summary.md +43 -0
  4. package/.claude/mem/notes/2026-02-11-cli-fix-editor-command-alias.md +26 -0
  5. package/.claude/mem/notes/2026-02-11-phase-3-developer-experience-completed.md +51 -0
  6. package/.claude/mem/notes/2026-02-11-phase-4-web-workers-implementation-complete.md +59 -0
  7. package/.claude/mem/notes/2026-02-11-visualify-phase-2-3d-visualization-complete.md +50 -0
  8. package/.claude/mem/notes/2026-02-11-visualify-phase-2-committed-ready-for-phase-3.md +33 -0
  9. package/.claude/mem/notes/2026-02-11-visualify-phase-3-complete-developer-experience.md +52 -0
  10. package/.claude/mem/notes/2026-02-11-visualify-repository-cleanup-complete.md +28 -0
  11. package/.claude/mem/notes/2026-02-18-codebase-cleanup-docsify-plugin-documentation.md +37 -0
  12. package/.claude/mem/notes/2026-02-19-css-grid-layout-fix-displaycontents-on-vcontroller.md +18 -0
  13. package/.claude/mem/notes/2026-02-19-docsify-plugin-fixes-latex-and-visualify-code-bloc.md +26 -0
  14. package/.claude/mem/notes/2026-02-19-page-mode-docs-update-decisions.md +23 -0
  15. package/.claude/mem/notes/2026-02-19-react-context-infinite-re-render-loop-fix-pattern.md +31 -0
  16. package/.claude/mem/notes/2026-02-19-version-300-bump-and-build-fixes.md +32 -0
  17. package/.claude/mem/notes/2026-02-19-visualify-build-deployment-architecture-bug-fixes.md +25 -0
  18. package/.claude/mem/notes/2026-02-19-visualify-dist-iife-self-contained-build-config.md +30 -0
  19. package/.claude/mem/notes/2026-02-19-visualify-infinite-loop-i18n-fixes.md +31 -0
  20. package/.claude/mem/notes/2026-02-19-visualify-v3-bundle-splitting-docs-restructuring.md +32 -0
  21. package/.claude/mem/notes/2026-02-20-bundle-externalization-final-architecture.md +29 -0
  22. package/.claude/mem/notes/2026-02-20-chromium-page-fix-unstable-keys-and-double-event-b.md +27 -0
  23. package/.claude/mem/notes/2026-02-20-console-cleanup-bundle-optimization-commit.md +20 -0
  24. package/.claude/mem/notes/2026-02-20-dotbio-dot-plot-fix-useeffect-dependency.md +21 -0
  25. package/.claude/mem/notes/2026-02-20-public-folder-cleanup-and-readme-rewrite.md +25 -0
  26. package/.claude/mem/notes/2026-02-20-v300-release-and-beta-channel-strategy.md +29 -0
  27. package/.claude/mem/notes/2026-02-20-visium-background-image-unknown-legend-fix.md +19 -0
  28. package/.claude/mem/notes/2026-02-20-visualify-cdn-loader-bundle-externalization.md +34 -0
  29. package/.claude/mem/sessions/session-2026-02-20-031524.md +54 -0
  30. package/.claude/settings.local.json +21 -0
  31. package/.github/workflows/static.yml.bak +51 -51
  32. package/.sisyphus/boulder.json +65 -0
  33. package/.sisyphus/plans/phase-4-advanced-optimizations.md +217 -0
  34. package/LICENSE +674 -674
  35. package/README.md +94 -59
  36. package/config-overrides.js +31 -31
  37. package/dist/stats.html +4949 -0
  38. package/dist/visualify-3d.esm.js +1 -0
  39. package/dist/visualify-3d.js +1 -0
  40. package/dist/visualify-core.esm.js +1 -0
  41. package/dist/visualify-core.js +1 -0
  42. package/dist/visualify-docs.esm.js +1 -0
  43. package/dist/visualify-docs.js +1 -0
  44. package/dist/visualify-loader.js +1 -0
  45. package/dist/visualify-pages.esm.js +1 -0
  46. package/dist/visualify-pages.js +1 -0
  47. package/dist/visualify-portal.esm.js +1 -0
  48. package/dist/visualify-portal.js +1 -0
  49. package/dist/visualify-shared.js +26571 -0
  50. package/dist/visualify.js +1 -188
  51. package/docs/CHANGELOG.md +148 -0
  52. package/docs/cli/commands.md +513 -0
  53. package/docs/configuration/visualify-json.md +474 -0
  54. package/docs/docs/3d-visualization.md +374 -0
  55. package/docs/docs/CLI.md +303 -34
  56. package/docs/docs/README.md +65 -65
  57. package/docs/docs/Rechart/bar.md +190 -190
  58. package/docs/docs/Rechart/funnel.md +241 -241
  59. package/docs/docs/Rechart/line.md +355 -355
  60. package/docs/docs/Rechart/pie.md +225 -225
  61. package/docs/docs/Rechart/radar.md +253 -253
  62. package/docs/docs/Rechart/scatter.md +298 -298
  63. package/docs/docs/_404.md +51 -51
  64. package/docs/docs/_coverpage.md +11 -11
  65. package/docs/docs/_sidebar.md +54 -44
  66. package/docs/docs/components/dotBio.md +87 -34
  67. package/docs/docs/components/echart.md +171 -82
  68. package/docs/docs/components/html.md +61 -34
  69. package/docs/docs/components/macaron.md +156 -145
  70. package/docs/docs/components/markdown.md +42 -0
  71. package/docs/docs/components/more.md +183 -142
  72. package/docs/docs/components/plotly.md +132 -62
  73. package/docs/docs/components/scatterL.md +171 -70
  74. package/docs/docs/components/visium.md +112 -57
  75. package/docs/docs/configuration.md +121 -121
  76. package/docs/docs/deploy.md +31 -31
  77. package/docs/docs/docsify-plugin.md +655 -0
  78. package/docs/docs/hmr.md +165 -0
  79. package/docs/docs/i18n.md +332 -0
  80. package/docs/docs/log.md +30 -9
  81. package/docs/docs/more-pages.md +23 -23
  82. package/docs/docs/quickstart.md +148 -124
  83. package/docs/docs/rechart-attributes.md +74 -74
  84. package/docs/docs/rechart-basic-usage.md +160 -162
  85. package/docs/docs/theme.md +5 -5
  86. package/docs/docs/typescript.md +306 -0
  87. package/docs/docs/visual-editor.md +359 -0
  88. package/docs/index.html +85 -71
  89. package/docs/manifest.json +23 -23
  90. package/docs/migration/v3-migration.md +392 -0
  91. package/docs/static/css/fluff-stuff.css +169 -169
  92. package/docs/static/css/font-awesome.min.css +4 -4
  93. package/docs/static/css/visualify.css +6 -25
  94. package/docs/static/js/3d-viz-examples.js +181 -0
  95. package/docs/static/js/configuration.js +630 -448
  96. package/docs/static/js/visualify.js +1 -188
  97. package/package.json +106 -84
  98. package/rollup.config.mjs +766 -76
  99. package/src/_css/404.css +115 -115
  100. package/src/_css/App.css +37 -37
  101. package/src/_css/autoSuggestion.css +26 -26
  102. package/src/_css/circular-progress.css +32 -32
  103. package/src/_css/index.css +36 -36
  104. package/src/_css/modern.css +350 -25
  105. package/src/_media/corner.svg +8 -8
  106. package/src/_media/download.svg +3 -3
  107. package/src/_media/logo.svg +14 -14
  108. package/src/_test/App.test.js +15 -15
  109. package/src/_utils/reportWebVitals.js +13 -13
  110. package/src/a11y/README.md +177 -0
  111. package/src/a11y/aria-labels.js +339 -0
  112. package/src/a11y/color-contrast.js +535 -0
  113. package/src/a11y/index.js +197 -0
  114. package/src/a11y/keyboard-nav.js +523 -0
  115. package/src/a11y/styles.css +165 -0
  116. package/src/cli/commands/dev.js +214 -0
  117. package/src/cli/commands/docs.js +521 -0
  118. package/src/cli/commands/edit.js +379 -0
  119. package/src/cli/commands/init.js +213 -0
  120. package/src/cli/commands/portal.js +236 -0
  121. package/src/cli/dev-server.js +530 -0
  122. package/src/cli/hmr.js +456 -0
  123. package/src/cli/index.js +180 -0
  124. package/src/cli/utils/config.js +207 -0
  125. package/src/cli/utils/logger.js +241 -0
  126. package/src/config/defaults.ts +122 -0
  127. package/src/config/index.ts +72 -0
  128. package/src/config/loader.ts +478 -0
  129. package/src/config/schema.ts +227 -0
  130. package/src/config/validator.ts +337 -0
  131. package/src/core/appContext.js +34 -27
  132. package/src/core/components/Bar.js +383 -0
  133. package/src/core/components/Bar3D.js +473 -0
  134. package/src/core/components/LargeDatasetChart.js +296 -0
  135. package/src/core/components/Line3D.js +310 -0
  136. package/src/core/components/Scatter.js +392 -188
  137. package/src/core/components/Scatter3D.js +455 -0
  138. package/src/core/components/ScatterBio.js +601 -572
  139. package/src/core/components/Surface3D.js +326 -0
  140. package/src/core/components/ThreeCustom.js +648 -0
  141. package/src/core/components/ThreeScene.js +459 -0
  142. package/src/core/components/VisiumPlot.js +191 -165
  143. package/src/core/components/browser.js +42 -42
  144. package/src/core/components/dotplot.js +413 -413
  145. package/src/core/components/html.js +29 -29
  146. package/src/core/components/list.js +178 -178
  147. package/src/core/components/macaron.js +206 -201
  148. package/src/core/components/markdown.js +56 -56
  149. package/src/core/components/parser.scatterBio.js +582 -587
  150. package/src/core/components/ratio.js +82 -80
  151. package/src/core/components/scatterL.js +206 -173
  152. package/src/core/components/searchbar.js +156 -131
  153. package/src/core/components/selection.js +310 -193
  154. package/src/core/components/timeline.js +236 -281
  155. package/src/core/components/visium.js +114 -97
  156. package/src/core/data-processor.js +413 -0
  157. package/src/core/fetch/condfetch.js +82 -82
  158. package/src/core/fetch/fetch.js +92 -92
  159. package/src/core/fetch/json.js +29 -29
  160. package/src/core/fetch/vfetch.js +42 -42
  161. package/src/core/hmr-client.js +724 -0
  162. package/src/core/liveEditor.js +44 -44
  163. package/src/core/modules/codeEditorWithPreview.js +104 -104
  164. package/src/core/modules/echarts/common.js +20 -20
  165. package/src/core/modules/echarts/gl.js +228 -0
  166. package/src/core/modules/echarts/presetHandler.js +41 -41
  167. package/src/core/modules/echarts/presets/esodev.chromium.js +172 -172
  168. package/src/core/modules/echarts/presets/esodev.codex.js +130 -130
  169. package/src/core/modules/echarts/presets/esodev.visium.js +123 -123
  170. package/src/core/modules/echarts/presets/mmtrbc.js +186 -186
  171. package/src/core/modules/echarts.js +70 -71
  172. package/src/core/modules/echartsUtils.js +43 -43
  173. package/src/core/modules/echartswitcher.js +227 -152
  174. package/src/core/modules/replotly/presetHandler.js +24 -24
  175. package/src/core/modules/replotly/presets/minimum.js +18 -18
  176. package/src/core/modules/replotly/presets/mmtrbc.dot.js +114 -114
  177. package/src/core/modules/replotly/presets/mmtrbc.violin.js +100 -100
  178. package/src/core/modules/replotly.js +74 -71
  179. package/src/core/modules/threejs/Camera.js +373 -0
  180. package/src/core/modules/threejs/Lighting.js +459 -0
  181. package/src/core/modules/threejs/Renderer.js +364 -0
  182. package/src/core/modules/threejs/Scene.js +266 -0
  183. package/src/core/modules/threejs/index.js +155 -0
  184. package/src/core/pages/404.js +50 -50
  185. package/src/core/pages/error.js +27 -27
  186. package/src/core/pages/jsonPage.js +62 -62
  187. package/src/core/pages/loading.js +44 -44
  188. package/src/core/parser/echart.data.js +204 -183
  189. package/src/core/parser/echart.features.js +125 -125
  190. package/src/core/parser/echart.general.js +147 -147
  191. package/src/core/parser/echart.hilbert.js +57 -57
  192. package/src/core/parser/echart.parser.js +210 -210
  193. package/src/core/parser/echart.series.js +67 -67
  194. package/src/core/parser/echart.types.js +76 -76
  195. package/src/core/parser/plotly.config.js +10 -10
  196. package/src/core/parser/plotly.data.js +132 -132
  197. package/src/core/parser/plotly.layout.js +9 -9
  198. package/src/core/parser/plotly.violin.js +18 -18
  199. package/src/core/recharts.js +361 -62
  200. package/src/core/router/alias.js +49 -49
  201. package/src/core/router/jsonRouter.js +31 -31
  202. package/src/core/themes/modern.js +32 -32
  203. package/src/core/themes/themeSelector.js +33 -33
  204. package/src/core/visualify.js +213 -47
  205. package/src/core/widgets/circularProgress.js +23 -23
  206. package/src/core/widgets/controller.js +116 -83
  207. package/src/core/widgets/errorBoundary.js +36 -36
  208. package/src/core/widgets/footer.js +185 -177
  209. package/src/core/widgets/header.js +238 -234
  210. package/src/core/widgets/layout/Grid.js +31 -31
  211. package/src/core/widgets/layout.js +36 -36
  212. package/src/core/widgets/mapping.js +56 -42
  213. package/src/core/workers/data-worker.js +349 -0
  214. package/src/core/workers/worker-pool.js +396 -0
  215. package/src/docsify/bundle.js +215 -0
  216. package/src/docsify/markdown.js +271 -0
  217. package/src/docsify/plugin.js +268 -0
  218. package/src/editor/README.md +172 -0
  219. package/src/editor/components/ChartBuilder.jsx +341 -0
  220. package/src/editor/components/ChartTypeSidebar.jsx +91 -0
  221. package/src/editor/components/Editor.jsx +367 -0
  222. package/src/editor/components/Preview.jsx +446 -0
  223. package/src/editor/components/PropertyPanel.jsx +468 -0
  224. package/src/editor/components/StatusBar.jsx +85 -0
  225. package/src/editor/context/EditorContext.js +248 -0
  226. package/src/editor/hooks/useDebounce.js +32 -0
  227. package/src/editor/index.js +315 -0
  228. package/src/editor/styles/editor.css +637 -0
  229. package/src/editor/utils/chartValidator.js +263 -0
  230. package/src/entries/charts3d.js +70 -0
  231. package/src/entries/core.js +78 -0
  232. package/src/entries/docs.js +154 -0
  233. package/src/entries/pages.js +93 -0
  234. package/src/entries/portal.js +204 -0
  235. package/src/entries/shared.js +50 -0
  236. package/src/i18n/formatters.js +455 -0
  237. package/src/i18n/index.js +169 -0
  238. package/src/i18n/locales/ar.json +137 -0
  239. package/src/i18n/locales/de.json +137 -0
  240. package/src/i18n/locales/en.json +137 -0
  241. package/src/i18n/locales/es.json +137 -0
  242. package/src/i18n/locales/he.json +137 -0
  243. package/src/i18n/locales/zh.json +137 -0
  244. package/src/i18n/rtl.css +183 -0
  245. package/src/index.js +82 -62
  246. package/src/loader.js +103 -0
  247. package/src/setupTests.js +5 -5
  248. package/tsconfig.json +51 -0
  249. package/types/charts.d.ts +569 -0
  250. package/types/components.d.ts +441 -0
  251. package/types/config.d.ts +199 -0
  252. package/types/index.d.ts +353 -0
@@ -0,0 +1,396 @@
1
+ /**
2
+ * @fileoverview Web Worker Pool Manager
3
+ * @module core/workers/worker-pool
4
+ *
5
+ * Manages a pool of web workers for concurrent data processing.
6
+ * Provides task queuing, load balancing, and error handling.
7
+ */
8
+
9
+ /**
10
+ * Default configuration for worker pool
11
+ * @readonly
12
+ */
13
+ const DEFAULT_CONFIG = {
14
+ minWorkers: 2,
15
+ maxWorkers: navigator.hardwareConcurrency || 4,
16
+ taskTimeout: 30000,
17
+ idleTimeout: 60000,
18
+ };
19
+
20
+ /**
21
+ * Worker task status
22
+ * @readonly
23
+ */
24
+ const TASK_STATUS = {
25
+ PENDING: 'pending',
26
+ RUNNING: 'running',
27
+ COMPLETED: 'completed',
28
+ FAILED: 'failed',
29
+ CANCELLED: 'cancelled',
30
+ };
31
+
32
+ /**
33
+ * Worker Pool Manager
34
+ * Manages multiple web workers for parallel data processing
35
+ */
36
+ class WorkerPool {
37
+ /**
38
+ * Create a new worker pool
39
+ * @param {Object} options - Pool configuration
40
+ * @param {string} options.workerScript - Path to worker script
41
+ * @param {number} options.minWorkers - Minimum number of workers
42
+ * @param {number} options.maxWorkers - Maximum number of workers
43
+ * @param {number} options.taskTimeout - Task timeout in milliseconds
44
+ * @param {number} options.idleTimeout - Idle worker termination timeout
45
+ */
46
+ constructor(options = {}) {
47
+ this.config = { ...DEFAULT_CONFIG, ...options };
48
+ this.workerScript = options.workerScript;
49
+
50
+ if (!this.workerScript) {
51
+ throw new Error('WorkerPool requires a workerScript path');
52
+ }
53
+
54
+ this.workers = new Map();
55
+ this.taskQueue = [];
56
+ this.activeTasks = new Map();
57
+ this.taskIdCounter = 0;
58
+ this.isTerminated = false;
59
+
60
+ // Initialize minimum workers
61
+ this._ensureMinWorkers();
62
+ }
63
+
64
+ /**
65
+ * Ensure minimum number of workers are available
66
+ * @private
67
+ */
68
+ _ensureMinWorkers() {
69
+ const currentCount = this.workers.size;
70
+ const needed = this.config.minWorkers - currentCount;
71
+
72
+ for (let i = 0; i < needed; i++) {
73
+ this._createWorker();
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Create a new worker
79
+ * @private
80
+ * @returns {string} Worker ID
81
+ */
82
+ _createWorker() {
83
+ const workerId = `worker-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
84
+
85
+ try {
86
+ const worker = new Worker(this.workerScript, { type: 'module' });
87
+
88
+ const workerInfo = {
89
+ id: workerId,
90
+ worker,
91
+ status: 'idle',
92
+ currentTask: null,
93
+ createdAt: Date.now(),
94
+ taskCount: 0,
95
+ };
96
+
97
+ worker.onmessage = (event) => this._handleMessage(workerId, event);
98
+ worker.onerror = (error) => this._handleError(workerId, error);
99
+ worker.onmessageerror = (error) => this._handleMessageError(workerId, error);
100
+
101
+ this.workers.set(workerId, workerInfo);
102
+
103
+ return workerId;
104
+ } catch (error) {
105
+ console.error('[WorkerPool] Failed to create worker:', error);
106
+ throw error;
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Handle message from worker
112
+ * @private
113
+ * @param {string} workerId - Worker ID
114
+ * @param {MessageEvent} event - Message event
115
+ */
116
+ _handleMessage(workerId, event) {
117
+ const { type, taskId, payload, error } = event.data;
118
+ const workerInfo = this.workers.get(workerId);
119
+
120
+ if (!workerInfo) return;
121
+
122
+ const task = this.activeTasks.get(taskId);
123
+ if (!task) return;
124
+
125
+ // Clear timeout
126
+ if (task.timeoutId) {
127
+ clearTimeout(task.timeoutId);
128
+ }
129
+
130
+ // Update worker status
131
+ workerInfo.status = 'idle';
132
+ workerInfo.currentTask = null;
133
+ workerInfo.taskCount++;
134
+
135
+ // Remove from active tasks
136
+ this.activeTasks.delete(taskId);
137
+
138
+ // Resolve or reject the task
139
+ if (type === 'error' || error) {
140
+ task.status = TASK_STATUS.FAILED;
141
+ task.reject(new Error(error?.message || 'Worker error'));
142
+ } else {
143
+ task.status = TASK_STATUS.COMPLETED;
144
+ task.resolve(payload);
145
+ }
146
+
147
+ // Process next task in queue
148
+ this._processQueue();
149
+ }
150
+
151
+ /**
152
+ * Handle worker error
153
+ * @private
154
+ * @param {string} workerId - Worker ID
155
+ * @param {ErrorEvent} error - Error event
156
+ */
157
+ _handleError(workerId, error) {
158
+ console.error(`[WorkerPool] Worker ${workerId} error:`, error);
159
+
160
+ const workerInfo = this.workers.get(workerId);
161
+ if (workerInfo?.currentTask) {
162
+ const task = this.activeTasks.get(workerInfo.currentTask);
163
+ if (task) {
164
+ task.status = TASK_STATUS.FAILED;
165
+ task.reject(new Error(`Worker error: ${error.message}`));
166
+ this.activeTasks.delete(workerInfo.currentTask);
167
+ }
168
+ }
169
+
170
+ // Terminate and remove the faulty worker
171
+ this._terminateWorker(workerId);
172
+
173
+ // Create a replacement if needed
174
+ if (this.workers.size < this.config.minWorkers) {
175
+ this._createWorker();
176
+ }
177
+
178
+ // Process queue
179
+ this._processQueue();
180
+ }
181
+
182
+ /**
183
+ * Handle message error
184
+ * @private
185
+ * @param {string} workerId - Worker ID
186
+ * @param {ErrorEvent} error - Error event
187
+ */
188
+ _handleMessageError(workerId, error) {
189
+ console.error(`[WorkerPool] Worker ${workerId} message error:`, error);
190
+ this._handleError(workerId, error);
191
+ }
192
+
193
+ /**
194
+ * Terminate a worker
195
+ * @private
196
+ * @param {string} workerId - Worker ID
197
+ */
198
+ _terminateWorker(workerId) {
199
+ const workerInfo = this.workers.get(workerId);
200
+ if (workerInfo) {
201
+ workerInfo.worker.terminate();
202
+ this.workers.delete(workerId);
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Get an available worker
208
+ * @private
209
+ * @returns {Object|null} Worker info or null if none available
210
+ */
211
+ _getAvailableWorker() {
212
+ for (const workerInfo of this.workers.values()) {
213
+ if (workerInfo.status === 'idle') {
214
+ return workerInfo;
215
+ }
216
+ }
217
+ return null;
218
+ }
219
+
220
+ /**
221
+ * Process the task queue
222
+ * @private
223
+ */
224
+ _processQueue() {
225
+ if (this.isTerminated || this.taskQueue.length === 0) return;
226
+
227
+ const availableWorker = this._getAvailableWorker();
228
+ if (!availableWorker) {
229
+ // Try to create a new worker if under max
230
+ if (this.workers.size < this.config.maxWorkers) {
231
+ const newWorkerId = this._createWorker();
232
+ this._assignTask(newWorkerId, this.taskQueue.shift());
233
+ }
234
+ return;
235
+ }
236
+
237
+ const task = this.taskQueue.shift();
238
+ this._assignTask(availableWorker.id, task);
239
+ }
240
+
241
+ /**
242
+ * Assign a task to a worker
243
+ * @private
244
+ * @param {string} workerId - Worker ID
245
+ * @param {Object} task - Task object
246
+ */
247
+ _assignTask(workerId, task) {
248
+ const workerInfo = this.workers.get(workerId);
249
+ if (!workerInfo) {
250
+ task.reject(new Error('Worker not found'));
251
+ return;
252
+ }
253
+
254
+ workerInfo.status = 'busy';
255
+ workerInfo.currentTask = task.id;
256
+
257
+ task.status = TASK_STATUS.RUNNING;
258
+ this.activeTasks.set(task.id, task);
259
+
260
+ // Set timeout
261
+ task.timeoutId = setTimeout(() => {
262
+ task.status = TASK_STATUS.FAILED;
263
+ task.reject(new Error(`Task ${task.id} timed out after ${this.config.taskTimeout}ms`));
264
+ this.activeTasks.delete(task.id);
265
+
266
+ // Reset worker
267
+ workerInfo.status = 'idle';
268
+ workerInfo.currentTask = null;
269
+
270
+ // Terminate and recreate worker
271
+ this._terminateWorker(workerId);
272
+ this._createWorker();
273
+ this._processQueue();
274
+ }, this.config.taskTimeout);
275
+
276
+ // Send task to worker
277
+ workerInfo.worker.postMessage({
278
+ type: 'task',
279
+ taskId: task.id,
280
+ payload: task.payload,
281
+ });
282
+ }
283
+
284
+ /**
285
+ * Execute a task in a worker
286
+ * @param {Object} payload - Task payload
287
+ * @returns {Promise<any>} Task result
288
+ */
289
+ execute(payload) {
290
+ if (this.isTerminated) {
291
+ return Promise.reject(new Error('Worker pool has been terminated'));
292
+ }
293
+
294
+ return new Promise((resolve, reject) => {
295
+ const task = {
296
+ id: `task-${++this.taskIdCounter}`,
297
+ payload,
298
+ status: TASK_STATUS.PENDING,
299
+ resolve,
300
+ reject,
301
+ timeoutId: null,
302
+ createdAt: Date.now(),
303
+ };
304
+
305
+ this.taskQueue.push(task);
306
+ this._processQueue();
307
+ });
308
+ }
309
+
310
+ /**
311
+ * Execute multiple tasks in parallel
312
+ * @param {Array<Object>} payloads - Array of task payloads
313
+ * @returns {Promise<Array<any>>} Array of results
314
+ */
315
+ executeAll(payloads) {
316
+ return Promise.all(payloads.map((payload) => this.execute(payload)));
317
+ }
318
+
319
+ /**
320
+ * Get pool statistics
321
+ * @returns {Object} Pool statistics
322
+ */
323
+ getStats() {
324
+ let idleWorkers = 0;
325
+ let busyWorkers = 0;
326
+
327
+ for (const workerInfo of this.workers.values()) {
328
+ if (workerInfo.status === 'idle') idleWorkers++;
329
+ else busyWorkers++;
330
+ }
331
+
332
+ return {
333
+ totalWorkers: this.workers.size,
334
+ idleWorkers,
335
+ busyWorkers,
336
+ queuedTasks: this.taskQueue.length,
337
+ activeTasks: this.activeTasks.size,
338
+ isTerminated: this.isTerminated,
339
+ };
340
+ }
341
+
342
+ /**
343
+ * Terminate all workers and clear queue
344
+ */
345
+ terminate() {
346
+ this.isTerminated = true;
347
+
348
+ // Clear queue
349
+ for (const task of this.taskQueue) {
350
+ task.status = TASK_STATUS.CANCELLED;
351
+ task.reject(new Error('Worker pool terminated'));
352
+ }
353
+ this.taskQueue = [];
354
+
355
+ // Cancel active tasks
356
+ for (const task of this.activeTasks.values()) {
357
+ if (task.timeoutId) clearTimeout(task.timeoutId);
358
+ task.status = TASK_STATUS.CANCELLED;
359
+ task.reject(new Error('Worker pool terminated'));
360
+ }
361
+ this.activeTasks.clear();
362
+
363
+ // Terminate all workers
364
+ for (const workerId of this.workers.keys()) {
365
+ this._terminateWorker(workerId);
366
+ }
367
+ }
368
+ }
369
+
370
+ // Singleton instance
371
+ let globalPool = null;
372
+
373
+ /**
374
+ * Get or create global worker pool
375
+ * @param {Object} config - Pool configuration
376
+ * @returns {WorkerPool} Global worker pool instance
377
+ */
378
+ export function getWorkerPool(config = {}) {
379
+ if (!globalPool) {
380
+ globalPool = new WorkerPool(config);
381
+ }
382
+ return globalPool;
383
+ }
384
+
385
+ /**
386
+ * Terminate global worker pool
387
+ */
388
+ export function terminateWorkerPool() {
389
+ if (globalPool) {
390
+ globalPool.terminate();
391
+ globalPool = null;
392
+ }
393
+ }
394
+
395
+ export { WorkerPool, TASK_STATUS };
396
+ export default WorkerPool;
@@ -0,0 +1,215 @@
1
+ /**
2
+ * @fileoverview Docsify + Visualify Bundled Distribution
3
+ * @module docsify/bundle
4
+ *
5
+ * UMD bundle entry point that combines Docsify with Visualify plugin.
6
+ * Auto-initializes if Docsify configuration is present.
7
+ *
8
+ * @example
9
+ * // In HTML:
10
+ * <script src="visualify-docsify.min.js"></script>
11
+ * <script>
12
+ * window.$docsify = {
13
+ * // Docsify configuration
14
+ * };
15
+ * </script>
16
+ * <script src="https://cdn.jsdelivr.net/npm/docsify@4/lib/docsify.min.js"></script>
17
+ */
18
+
19
+ import DocsifyPlugin from './plugin';
20
+ import { processMarkdown, processVisualifyBlocks, extractConfigs } from './markdown';
21
+
22
+ /**
23
+ * Bundle version (replaced during build)
24
+ * @type {string}
25
+ */
26
+ const VERSION = process.env.VISUALIFY_VERSION || 'dev';
27
+
28
+ /**
29
+ * Check if running in browser environment
30
+ * @type {boolean}
31
+ */
32
+ const isBrowser = typeof window !== 'undefined';
33
+
34
+ /**
35
+ * Default Docsify configuration with Visualify support
36
+ * @type {Object}
37
+ */
38
+ const DEFAULT_DOCSIFY_CONFIG = {
39
+ // Enable markdown plugin
40
+ markdown: {
41
+ renderer: {
42
+ code: function (code, lang) {
43
+ if (lang === 'visualify') {
44
+ return processMarkdown(code);
45
+ }
46
+ // Default code rendering
47
+ return (
48
+ '<pre v-pre><code class="lang-' +
49
+ lang +
50
+ '">' +
51
+ code +
52
+ '</code></pre>'
53
+ );
54
+ },
55
+ },
56
+ },
57
+ // Add Visualify plugin
58
+ plugins: [DocsifyPlugin.install],
59
+ };
60
+
61
+ /**
62
+ * Merge user config with defaults
63
+ * @param {Object} userConfig - User's Docsify configuration
64
+ * @returns {Object} Merged configuration
65
+ */
66
+ function mergeConfig(userConfig = {}) {
67
+ const merged = {
68
+ ...DEFAULT_DOCSIFY_CONFIG,
69
+ ...userConfig,
70
+ };
71
+
72
+ // Merge markdown renderer carefully
73
+ if (userConfig.markdown) {
74
+ if (typeof userConfig.markdown === 'function') {
75
+ // User provided a custom markdown function
76
+ const userMarkdown = userConfig.markdown;
77
+ merged.markdown = function (marked, renderer) {
78
+ const result = userMarkdown(marked, renderer);
79
+ // Ensure visualify code blocks are handled
80
+ const originalCode = renderer.code;
81
+ renderer.code = function (code, lang) {
82
+ if (lang === 'visualify') {
83
+ return processMarkdown(code);
84
+ }
85
+ return originalCode ? originalCode.call(this, code, lang) : code;
86
+ };
87
+ return result;
88
+ };
89
+ } else if (userConfig.markdown.renderer) {
90
+ // Merge renderers
91
+ merged.markdown = {
92
+ ...userConfig.markdown,
93
+ renderer: {
94
+ ...DEFAULT_DOCSIFY_CONFIG.markdown.renderer,
95
+ ...userConfig.markdown.renderer,
96
+ },
97
+ };
98
+ }
99
+ }
100
+
101
+ // Merge plugins array
102
+ if (userConfig.plugins) {
103
+ merged.plugins = [DocsifyPlugin.install, ...userConfig.plugins];
104
+ }
105
+
106
+ return merged;
107
+ }
108
+
109
+ /**
110
+ * Initialize Docsify with Visualify plugin
111
+ * @param {Object} [config] - Optional configuration override
112
+ */
113
+ function init(config = {}) {
114
+ if (!isBrowser) {
115
+ console.warn('[VisualifyDocs] init() can only be called in browser environment');
116
+ return;
117
+ }
118
+
119
+ // Merge with existing $docsify config if present
120
+ const existingConfig = window.$docsify || {};
121
+ window.$docsify = mergeConfig({ ...existingConfig, ...config });
122
+
123
+ console.log('[VisualifyDocs] Configuration applied. Load Docsify to initialize.');
124
+ }
125
+
126
+ /**
127
+ * Auto-initialize if Docsify is already present
128
+ */
129
+ function autoInit() {
130
+ if (!isBrowser) {
131
+ return;
132
+ }
133
+
134
+ // Check if Docsify config exists
135
+ if (window.$docsify) {
136
+ // Merge our config with existing
137
+ window.$docsify = mergeConfig(window.$docsify);
138
+ console.log('[VisualifyDocs] Auto-initialized with existing Docsify config');
139
+ } else {
140
+ // Set up default config for when Docsify loads
141
+ window.$docsify = DEFAULT_DOCSIFY_CONFIG;
142
+ console.log('[VisualifyDocs] Default configuration set');
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Main bundle exports
148
+ */
149
+ const VisualifyDocsifyBundle = {
150
+ // Version
151
+ VERSION,
152
+
153
+ // Core plugin
154
+ plugin: DocsifyPlugin,
155
+
156
+ // Markdown processing utilities
157
+ markdown: {
158
+ process: processMarkdown,
159
+ processBlocks: processVisualifyBlocks,
160
+ extractConfigs,
161
+ },
162
+
163
+ // Configuration
164
+ config: DEFAULT_DOCSIFY_CONFIG,
165
+
166
+ // Initialization
167
+ init,
168
+ mergeConfig,
169
+ autoInit,
170
+
171
+ /**
172
+ * Mount all charts in a container
173
+ * @param {Element} [container] - Container element
174
+ */
175
+ mountAll(container) {
176
+ return DocsifyPlugin.mountAllCharts(container);
177
+ },
178
+
179
+ /**
180
+ * Cleanup charts in a container
181
+ * @param {Element} [container] - Container element
182
+ */
183
+ cleanup(container) {
184
+ return DocsifyPlugin.cleanupCharts(container);
185
+ },
186
+ };
187
+
188
+ // Auto-initialize in browser
189
+ if (isBrowser) {
190
+ // Wait for DOM ready
191
+ if (document.readyState === 'loading') {
192
+ document.addEventListener('DOMContentLoaded', autoInit);
193
+ } else {
194
+ autoInit();
195
+ }
196
+ }
197
+
198
+ // UMD export pattern
199
+ (function (root, factory) {
200
+ if (typeof define === 'function' && define.amd) {
201
+ // AMD
202
+ define([], factory);
203
+ } else if (typeof module === 'object' && module.exports) {
204
+ // CommonJS
205
+ module.exports = factory();
206
+ } else {
207
+ // Browser global
208
+ root.VisualifyDocsify = factory();
209
+ }
210
+ })(typeof self !== 'undefined' ? self : this, function () {
211
+ return VisualifyDocsifyBundle;
212
+ });
213
+
214
+ export default VisualifyDocsifyBundle;
215
+ export { init, mergeConfig, autoInit, DocsifyPlugin, processMarkdown };