volview 4.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/.browserslistrc +4 -0
- package/.editorconfig +6 -0
- package/.env +6 -0
- package/.eslintrc.js +109 -0
- package/.gitattributes +1 -0
- package/.github/workflows/checks.yml +16 -0
- package/.github/workflows/publish.yml +52 -0
- package/.prettierignore +5 -0
- package/CONTRIBUTING.md +29 -0
- package/LICENSE +202 -0
- package/README.md +44 -0
- package/babel.config.js +3 -0
- package/documentation/config.js +15 -0
- package/documentation/content/KWVolViewLogo.png +0 -0
- package/documentation/content/KWVolViewLogo.svg +35 -0
- package/documentation/content/VolViewLogo.png +0 -0
- package/documentation/content/VolViewLogo.svg +22 -0
- package/documentation/content/doc/index.md +64 -0
- package/documentation/content/doc/loading_data.md +30 -0
- package/documentation/content/doc/mouse_controls.md +34 -0
- package/documentation/content/doc/quick_start_guide.md +75 -0
- package/documentation/content/doc/rendering.md +27 -0
- package/documentation/content/doc/state_files.md +18 -0
- package/documentation/content/doc/toolbar.md +20 -0
- package/documentation/content/doc/welcome_screen.md +23 -0
- package/documentation/content/gallery/01-volview-welcome-notes.jpg +0 -0
- package/documentation/content/gallery/01-volview-welcome.jpg +0 -0
- package/documentation/content/gallery/02-volview-about.jpg +0 -0
- package/documentation/content/gallery/02-volview-notifications.jpg +0 -0
- package/documentation/content/gallery/02-volview-settings.jpg +0 -0
- package/documentation/content/gallery/03-volview-sample-datasets.jpg +0 -0
- package/documentation/content/gallery/04-volview-active-data.jpg +0 -0
- package/documentation/content/gallery/05-volview-select-data-to-delete.jpg +0 -0
- package/documentation/content/gallery/06-volview-corner-annotation.jpg +0 -0
- package/documentation/content/gallery/07-volview-layout-notes.jpg +0 -0
- package/documentation/content/gallery/07-volview-layout.jpg +0 -0
- package/documentation/content/gallery/09-volview-layout-3DPrimary.jpg +0 -0
- package/documentation/content/gallery/10-volview-wl-pan-zoom-notes.jpg +0 -0
- package/documentation/content/gallery/10-volview-wl-pan-zoom.jpg +0 -0
- package/documentation/content/gallery/11-volview-paint-notes.jpg +0 -0
- package/documentation/content/gallery/11-volview-paint.jpg +0 -0
- package/documentation/content/gallery/12-volview-paint-options.jpg +0 -0
- package/documentation/content/gallery/13-volview-crop-notes.jpg +0 -0
- package/documentation/content/gallery/13-volview-crop.jpg +0 -0
- package/documentation/content/gallery/14-volview-ruler.jpg +0 -0
- package/documentation/content/gallery/15-volview-crosshairs.jpg +0 -0
- package/documentation/content/gallery/16-volview-rendering.jpg +0 -0
- package/documentation/content/gallery/17-volview-colormap-notes.jpg +0 -0
- package/documentation/content/gallery/17-volview-colormap.jpg +0 -0
- package/documentation/content/gallery/17-volview-opacity-notes.jpg +0 -0
- package/documentation/content/gallery/17-volview-opacity.jpg +0 -0
- package/documentation/content/gallery/17-volview-opacity2.jpg +0 -0
- package/documentation/content/gallery/18-volview-presets.jpg +0 -0
- package/documentation/content/gallery/19-volview-color.jpg +0 -0
- package/documentation/content/gallery/19-volview-color2.jpg +0 -0
- package/documentation/content/gallery/20-volview-lightfollowcamera0.jpg +0 -0
- package/documentation/content/gallery/20-volview-lightfollowcamera1.jpg +0 -0
- package/documentation/content/gallery/20-volview-lightfollowcamera2.jpg +0 -0
- package/documentation/content/gallery/20-volview-lightfollowcamera3.jpg +0 -0
- package/documentation/content/gallery/21-volview-hybrid-final.jpg +0 -0
- package/documentation/content/gallery/21-volview-hybrid0.0.jpg +0 -0
- package/documentation/content/gallery/21-volview-hybrid0.5.jpg +0 -0
- package/documentation/content/gallery/21-volview-hybrid1.0.jpg +0 -0
- package/documentation/content/gallery/LocalAmbientOcclusion.jpg +0 -0
- package/documentation/content/gallery/Notes.pptx +0 -0
- package/documentation/content/gallery/VolView-Overview.jpg +0 -0
- package/documentation/content/gallery/index.md +53 -0
- package/documentation/content/icon/favicon-16x16.png +0 -0
- package/documentation/content/icon/favicon-196x196.png +0 -0
- package/documentation/content/icon/favicon-32x32.png +0 -0
- package/documentation/content/icon/favicon-96x96.png +0 -0
- package/documentation/content/index.pug +43 -0
- package/documentation/content/logo.png +0 -0
- package/documentation/content/logo.svg +20 -0
- package/documentation/data/menu.yml +3 -0
- package/documentation/themes/navy/layout/partial/footer.swig +22 -0
- package/documentation/tpl/__en__ +31 -0
- package/documentation/tpl/__sidebar__ +11 -0
- package/package.json +96 -0
- package/patches/jsdom-global+3.0.2.patch +12 -0
- package/patches/vue-toastification+1.7.14.patch +41 -0
- package/patches/vuetify+2.6.10.patch +13 -0
- package/prettier.config.js +9 -0
- package/public/favicon.ico +0 -0
- package/public/global.css +20 -0
- package/public/index.html +28 -0
- package/public/pvm-sample.png +0 -0
- package/server/helper.py +147 -0
- package/server/host.js +134 -0
- package/server/serialize.js +111 -0
- package/server/serialize.py +203 -0
- package/server/server.py +84 -0
- package/server/test.py +17 -0
- package/src/assets/KitwareHeadAndNeck.jpg +0 -0
- package/src/assets/logo.png +0 -0
- package/src/assets/logo.svg +20 -0
- package/src/assets/samples/3DUS-Fetus.jpg +0 -0
- package/src/assets/samples/CTA-Head_and_Neck.jpg +0 -0
- package/src/assets/samples/MRA-Head_and_Neck.jpg +0 -0
- package/src/assets/samples/MRI-Cardiac.jpg +0 -0
- package/src/assets/samples/MRI-PROSTATEx.jpg +0 -0
- package/src/components/AboutBox.vue +157 -0
- package/src/components/AiModule.vue +60 -0
- package/src/components/AnnotationsModule.vue +37 -0
- package/src/components/App.vue +539 -0
- package/src/components/ColorFunctionSlider.vue +181 -0
- package/src/components/DataBrowser.vue +173 -0
- package/src/components/DragAndDrop.vue +107 -0
- package/src/components/GroupableItem.vue +30 -0
- package/src/components/ImageDataBrowser.vue +186 -0
- package/src/components/ImageListCard.vue +114 -0
- package/src/components/ItemGroup.vue +74 -0
- package/src/components/LabelmapList.vue +36 -0
- package/src/components/LayoutGrid.vue +96 -0
- package/src/components/MeasurementsList.vue +134 -0
- package/src/components/MessageCenter.vue +189 -0
- package/src/components/MessageItem.vue +83 -0
- package/src/components/MessageNotificationContent.vue +20 -0
- package/src/components/MessageNotifications.vue +84 -0
- package/src/components/ModelBrowser.vue +83 -0
- package/src/components/ModulePanel.vue +137 -0
- package/src/components/PaintControls.vue +174 -0
- package/src/components/PatientBrowser.vue +280 -0
- package/src/components/PatientStudyVolumeBrowser.vue +325 -0
- package/src/components/RenderingModule.vue +49 -0
- package/src/components/ResizableNavDrawer.vue +158 -0
- package/src/components/SampleDataBrowser.vue +198 -0
- package/src/components/SaveSession.vue +57 -0
- package/src/components/Settings.vue +35 -0
- package/src/components/SliceSlider.vue +182 -0
- package/src/components/SpleenModule.vue +101 -0
- package/src/components/ToolButton.vue +58 -0
- package/src/components/ToolStrip.vue +186 -0
- package/src/components/ViewOverlayGrid.vue +84 -0
- package/src/components/VolumePresets.vue +165 -0
- package/src/components/VolumeProperties.vue +171 -0
- package/src/components/VolumeRendering.vue +365 -0
- package/src/components/VtkThreeView.vue +512 -0
- package/src/components/VtkTwoView.vue +665 -0
- package/src/components/__tests__/ResizableNavDrawer.spec.js +32 -0
- package/src/components/__tests__/ToolButton.spec.js +46 -0
- package/src/components/icons/KitwareLogoIcon.vue +54 -0
- package/src/components/icons/VolViewFullLogo.vue +139 -0
- package/src/components/icons/VolViewLogo.vue +78 -0
- package/src/components/styles/utils.css +16 -0
- package/src/components/styles/vtk-view.css +116 -0
- package/src/components/tools/CropTool.vue +61 -0
- package/src/components/tools/CrosshairsTool.vue +93 -0
- package/src/components/tools/MouseManipulatorTool.vue +108 -0
- package/src/components/tools/PaintTool.vue +54 -0
- package/src/components/tools/PanTool.vue +35 -0
- package/src/components/tools/RulerTool.vue +202 -0
- package/src/components/tools/SliceScrollTool.vue +123 -0
- package/src/components/tools/WindowLevelTool.vue +191 -0
- package/src/components/tools/ZoomTool.vue +35 -0
- package/src/components/tools/crop/Crop2D.vue +367 -0
- package/src/components/tools/crop/Crop2DLineHandle.vue +103 -0
- package/src/components/tools/crop/Crop3D.vue +192 -0
- package/src/components/tools/crop/CropControls.vue +38 -0
- package/src/components/tools/crop/types.ts +12 -0
- package/src/components/tools/crosshairs/CrosshairSVG2D.vue +125 -0
- package/src/components/tools/crosshairs/CrosshairsWidget2D.vue +100 -0
- package/src/components/tools/paint/PaintWidget2D.vue +192 -0
- package/src/components/tools/ruler/RulerSVG2D.vue +181 -0
- package/src/components/tools/ruler/RulerWidget2D.vue +154 -0
- package/src/composables/__tests__/useDoubleRecord.spec.ts +57 -0
- package/src/composables/__tests__/useOrientationLabels.spec.ts +29 -0
- package/src/composables/isViewAnimating.ts +25 -0
- package/src/composables/manageVTKSubscription.ts +6 -0
- package/src/composables/onProxyManagerEvent.ts +50 -0
- package/src/composables/proxyManager.ts +13 -0
- package/src/composables/sync/__tests__/createPrimitiveSyncContext.spec.ts +41 -0
- package/src/composables/sync/__tests__/useWindowingSync.spec.ts +51 -0
- package/src/composables/sync/createPrimitiveSyncContext.ts +83 -0
- package/src/composables/sync/useWindowingSync.ts +48 -0
- package/src/composables/useAppLoadingNotifications.ts +73 -0
- package/src/composables/useCameraOrientation.ts +34 -0
- package/src/composables/useCurrentImage.ts +74 -0
- package/src/composables/useCurrentSlice.ts +43 -0
- package/src/composables/useDoubleRecord.ts +77 -0
- package/src/composables/useEventListener.ts +26 -0
- package/src/composables/useGlobalErrorHook.ts +18 -0
- package/src/composables/useMultiSelection.ts +29 -0
- package/src/composables/useOrientationLabels.ts +62 -0
- package/src/composables/usePanels.ts +42 -0
- package/src/composables/usePersistCameraConfig.ts +138 -0
- package/src/composables/useResizeObserver.ts +37 -0
- package/src/composables/useResizeToFit.ts +50 -0
- package/src/composables/useSceneBuilder.ts +96 -0
- package/src/composables/useToast.js +11 -0
- package/src/composables/useVTKCallback.ts +33 -0
- package/src/composables/useVTKWorldToDisplay.ts +141 -0
- package/src/composables/useViewProxy.ts +87 -0
- package/src/composables/useVolumeThumbnailing.ts +173 -0
- package/src/composables/useWebGLWatchdog.ts +32 -0
- package/src/composables/useWidgetManager.ts +41 -0
- package/src/config.ts +182 -0
- package/src/constants.ts +38 -0
- package/src/core/id.ts +18 -0
- package/src/core/provider.ts +31 -0
- package/src/core/proxies.ts +90 -0
- package/src/core/thumbnailers/__tests__/vtk-image.spec.ts +58 -0
- package/src/core/thumbnailers/index.ts +5 -0
- package/src/core/thumbnailers/volume-thumbnailer.ts +130 -0
- package/src/core/thumbnailers/vtk-image.ts +142 -0
- package/src/core/tools/__tests__/paint.spec.ts +101 -0
- package/src/core/tools/__tests__/ruler.spec.ts +73 -0
- package/src/core/tools/paint/brush.ts +20 -0
- package/src/core/tools/paint/ellipse-brush.ts +96 -0
- package/src/core/tools/paint/index.ts +141 -0
- package/src/core/tools/ruler.ts +149 -0
- package/src/global.d.ts +24 -0
- package/src/io/__tests__/io.spec.ts +26 -0
- package/src/io/dicom.ts +187 -0
- package/src/io/index.ts +11 -0
- package/src/io/io.ts +157 -0
- package/src/io/itk/itkConfig.js +8 -0
- package/src/io/itk-dicom/dicom.cpp +327 -0
- package/src/io/itk-dicom/web-build/dicom.js +16 -0
- package/src/io/itk-dicom/web-build/dicom.umd.js +21 -0
- package/src/io/itk-dicom/web-build/dicom.umd.wasm +0 -0
- package/src/io/itk-dicom/web-build/dicom.wasm +0 -0
- package/src/io/manifest.ts +30 -0
- package/src/io/readers.ts +36 -0
- package/src/io/state-file/index.ts +170 -0
- package/src/io/state-file/schema.ts +277 -0
- package/src/io/state-file/utils.ts +33 -0
- package/src/io/types.ts +4 -0
- package/src/io/vtk/async.reader.worker.ts +50 -0
- package/src/io/vtk/async.ts +58 -0
- package/src/io/vtk/async.writer.worker.ts +46 -0
- package/src/io/vtk/common.ts +30 -0
- package/src/io/zip.ts +31 -0
- package/src/main.js +66 -0
- package/src/main.ts +1 -0
- package/src/plugins/vuetify.js +25 -0
- package/src/shims-itk.d.ts +67 -0
- package/src/shims-misc.d.ts +4 -0
- package/src/shims-tsx.d.ts +13 -0
- package/src/shims-vtk.d.ts +1042 -0
- package/src/shims-vue.d.ts +5 -0
- package/src/store/__tests__/datasets.spec.ts +75 -0
- package/src/store/__tests__/messages.spec.ts +74 -0
- package/src/store/__tests__/rulers.spec.ts +77 -0
- package/src/store/__tests__/view-configs.spec.ts +37 -0
- package/src/store/datasets-dicom.ts +398 -0
- package/src/store/datasets-files.ts +35 -0
- package/src/store/datasets-images.ts +118 -0
- package/src/store/datasets-labelmaps.ts +136 -0
- package/src/store/datasets-models.ts +25 -0
- package/src/store/datasets.ts +341 -0
- package/src/store/messages.ts +144 -0
- package/src/store/tools/crop.ts +136 -0
- package/src/store/tools/crosshairs.ts +131 -0
- package/src/store/tools/index.ts +95 -0
- package/src/store/tools/paint.ts +191 -0
- package/src/store/tools/rulers.ts +305 -0
- package/src/store/tools/types.ts +54 -0
- package/src/store/view-configs/camera.ts +51 -0
- package/src/store/view-configs/common.ts +61 -0
- package/src/store/view-configs/slicing.ts +86 -0
- package/src/store/view-configs/types.ts +39 -0
- package/src/store/view-configs/volume-coloring.ts +193 -0
- package/src/store/view-configs/windowing.ts +69 -0
- package/src/store/view-configs.ts +78 -0
- package/src/store/views.ts +130 -0
- package/src/types/index.ts +16 -0
- package/src/types/layout.ts +10 -0
- package/src/types/lps.ts +40 -0
- package/src/types/views.ts +65 -0
- package/src/types/vtk-types.ts +29 -0
- package/src/utils/__tests__/lps.spec.ts +102 -0
- package/src/utils/color.ts +23 -0
- package/src/utils/errors.js +3 -0
- package/src/utils/fetch.ts +101 -0
- package/src/utils/hacks.ts +14 -0
- package/src/utils/index.ts +83 -0
- package/src/utils/lps.ts +129 -0
- package/src/utils/manipulators.ts +35 -0
- package/src/utils/promise-worker.ts +45 -0
- package/src/utils/vtk-helpers.ts +215 -0
- package/src/utils/workerHandler.js +42 -0
- package/src/vtk/ColorMaps.ts +72 -0
- package/src/vtk/CrosshairsWidget/behavior.ts +112 -0
- package/src/vtk/CrosshairsWidget/index.d.ts +22 -0
- package/src/vtk/CrosshairsWidget/index.js +73 -0
- package/src/vtk/CrosshairsWidget/state.ts +51 -0
- package/src/vtk/IJKSliceRepresentationProxy/index.d.ts +9 -0
- package/src/vtk/IJKSliceRepresentationProxy/index.js +59 -0
- package/src/vtk/LPSView2DProxy/index.d.ts +18 -0
- package/src/vtk/LPSView2DProxy/index.js +89 -0
- package/src/vtk/LPSView3DProxy/index.d.ts +16 -0
- package/src/vtk/LPSView3DProxy/index.js +78 -0
- package/src/vtk/LabelMap/index.d.ts +16 -0
- package/src/vtk/LabelMap/index.js +49 -0
- package/src/vtk/LabelMapSliceRepProxy/index.d.ts +6 -0
- package/src/vtk/LabelMapSliceRepProxy/index.js +104 -0
- package/src/vtk/MedicalColorPresets.json +1448 -0
- package/src/vtk/PaintBrushContextRepresentation/index.js +191 -0
- package/src/vtk/PaintWidget/behavior.ts +101 -0
- package/src/vtk/PaintWidget/index.d.ts +28 -0
- package/src/vtk/PaintWidget/index.js +56 -0
- package/src/vtk/PaintWidget/state.ts +41 -0
- package/src/vtk/PiecewiseWidget/index.js +203 -0
- package/src/vtk/RulerWidget/behavior.ts +185 -0
- package/src/vtk/RulerWidget/index.d.ts +25 -0
- package/src/vtk/RulerWidget/index.js +79 -0
- package/src/vtk/RulerWidget/state.ts +63 -0
- package/src/vtk/TreJsonConverter/index.js +150 -0
- package/src/vtk/proxy.js +66 -0
- package/src/vtk/proxyUtils.js +16 -0
- package/src/vtk/webvr-empty.js +1 -0
- package/tests/testUtils.js +12 -0
- package/tsconfig.json +46 -0
- package/vue.config.js +86 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
menu:
|
|
2
|
+
documentation: Documentation
|
|
3
|
+
gallery: Gallery
|
|
4
|
+
app: Try VolView
|
|
5
|
+
nightly: Nightly
|
|
6
|
+
news: News
|
|
7
|
+
search: Search
|
|
8
|
+
|
|
9
|
+
index:
|
|
10
|
+
get_started: Get started
|
|
11
|
+
|
|
12
|
+
page:
|
|
13
|
+
contents: Contents
|
|
14
|
+
back_to_top: Back to Top
|
|
15
|
+
improve: Improve this doc
|
|
16
|
+
prev: Prev
|
|
17
|
+
next: Next
|
|
18
|
+
last_updated: "Last updated: %s"
|
|
19
|
+
|
|
20
|
+
sidebar:
|
|
21
|
+
doc:
|
|
22
|
+
introduction: Introduction
|
|
23
|
+
what_is_volview: What is VolView?
|
|
24
|
+
quick_start_guide: Quick Start Guide
|
|
25
|
+
details: Details
|
|
26
|
+
welcome_screen: Welcome Screen
|
|
27
|
+
loading_data: Loading Data
|
|
28
|
+
toolbar: Toolbar
|
|
29
|
+
mouse_controls: Mouse/Keyboard Controls
|
|
30
|
+
rendering: Cinematic Rendering
|
|
31
|
+
state_files: State Files
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
doc:
|
|
2
|
+
introduction:
|
|
3
|
+
what_is_volview: index.html
|
|
4
|
+
quick_start_guide: quick_start_guide.html
|
|
5
|
+
details:
|
|
6
|
+
welcome_screen: welcome_screen.html
|
|
7
|
+
loading_data: loading_data.html
|
|
8
|
+
toolbar: toolbar.html
|
|
9
|
+
mouse_controls: mouse_controls.html
|
|
10
|
+
rendering: rendering.html
|
|
11
|
+
state_files: state_files.html
|
package/package.json
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "volview",
|
|
3
|
+
"version": "4.0.0",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"serve": "vue-cli-service serve",
|
|
6
|
+
"build": "vue-cli-service build",
|
|
7
|
+
"test:unit": "vue-cli-service test:unit -- ./src/**/__tests__/*.spec.[jt]s",
|
|
8
|
+
"lint": "vue-cli-service lint",
|
|
9
|
+
"build:all": "npm run build:dicom && npm run build",
|
|
10
|
+
"build:dicom": "itk-wasm -s src/io/itk-dicom/ build ",
|
|
11
|
+
"build:dicom:debug": "itk-wasm -s src/io/itk-dicom/ build -- -DCMAKE_BUILD_TYPE=Debug",
|
|
12
|
+
"postinstall": "patch-package",
|
|
13
|
+
"prettify": "prettier --write src tests",
|
|
14
|
+
"doc": "kw-doc -c ./documentation/config.js",
|
|
15
|
+
"doc:www": "kw-doc -c ./documentation/config.js -s",
|
|
16
|
+
"doc:publish": "kw-doc -c ./documentation/config.js -mp"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@kitware/vtk.js": "^25.13.0",
|
|
20
|
+
"@vue/composition-api": "1.6.3",
|
|
21
|
+
"@vueuse/core": "^8.5.0",
|
|
22
|
+
"@vueuse/shared": "^9.2.0",
|
|
23
|
+
"core-js": "3.22.5",
|
|
24
|
+
"deep-equal": "^2.0.5",
|
|
25
|
+
"file-saver": "^2.0.5",
|
|
26
|
+
"gl-matrix": "3.4.3",
|
|
27
|
+
"itk-image-io": "1.0.0-b.19",
|
|
28
|
+
"itk-wasm": "1.0.0-b.19",
|
|
29
|
+
"jszip": "3.10.0",
|
|
30
|
+
"mitt": "^3.0.0",
|
|
31
|
+
"pinia": "^2.0.14",
|
|
32
|
+
"vue": "2.6.14",
|
|
33
|
+
"vue-toastification": "^1.7.14",
|
|
34
|
+
"vuetify": "2.6.10",
|
|
35
|
+
"wslink": "^1.6.4",
|
|
36
|
+
"zod": "^3.18.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@pinia/testing": "^0.0.12",
|
|
40
|
+
"@types/chai": "^4.3.1",
|
|
41
|
+
"@types/chai-almost": "^1.0.1",
|
|
42
|
+
"@types/chai-as-promised": "^7.1.5",
|
|
43
|
+
"@types/chai-subset": "^1.3.3",
|
|
44
|
+
"@types/deep-equal": "^1.0.1",
|
|
45
|
+
"@types/file-saver": "^2.0.5",
|
|
46
|
+
"@types/mocha": "^9.1.1",
|
|
47
|
+
"@types/sinon": "^10.0.11",
|
|
48
|
+
"@types/sinon-chai": "^3.2.8",
|
|
49
|
+
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
|
50
|
+
"@typescript-eslint/parser": "^5.4.0",
|
|
51
|
+
"@vue/cli-plugin-babel": "~5.0.4",
|
|
52
|
+
"@vue/cli-plugin-eslint": "~5.0.4",
|
|
53
|
+
"@vue/cli-plugin-typescript": "~5.0.4",
|
|
54
|
+
"@vue/cli-plugin-unit-mocha": "~5.0.4",
|
|
55
|
+
"@vue/cli-plugin-vuex": "~5.0.4",
|
|
56
|
+
"@vue/cli-service": "~5.0.4",
|
|
57
|
+
"@vue/eslint-config-airbnb": "^6.0.0",
|
|
58
|
+
"@vue/eslint-config-typescript": "^9.1.0",
|
|
59
|
+
"@vue/test-utils": "1.3.0",
|
|
60
|
+
"babel-eslint": "10.1.0",
|
|
61
|
+
"canvas": "^2.9.3",
|
|
62
|
+
"chai": "4.3.6",
|
|
63
|
+
"chai-almost": "^1.0.1",
|
|
64
|
+
"chai-as-promised": "7.1.1",
|
|
65
|
+
"chai-subset": "^1.6.0",
|
|
66
|
+
"eslint": "^7.32.0",
|
|
67
|
+
"eslint-config-prettier": "6.15.0",
|
|
68
|
+
"eslint-import-resolver-typescript": "^2.7.1",
|
|
69
|
+
"eslint-plugin-import": "2.26.0",
|
|
70
|
+
"eslint-plugin-vue": "^8.0.3",
|
|
71
|
+
"eslint-plugin-vuejs-accessibility": "^1.1.0",
|
|
72
|
+
"kw-doc": "3.1.2",
|
|
73
|
+
"lint-staged": "10.5.4",
|
|
74
|
+
"null-loader": "4.0.1",
|
|
75
|
+
"patch-package": "^6.4.7",
|
|
76
|
+
"prettier": "2.6.2",
|
|
77
|
+
"sass": "~1.32.0",
|
|
78
|
+
"sass-loader": "10.2.1",
|
|
79
|
+
"shader-loader": "1.3.1",
|
|
80
|
+
"sinon": "14.0.0",
|
|
81
|
+
"sinon-chai": "3.7.0",
|
|
82
|
+
"typescript": "~4.6.4",
|
|
83
|
+
"vue-cli-plugin-vuetify": "2.4.8",
|
|
84
|
+
"vue-template-compiler": "2.6.14",
|
|
85
|
+
"vuetify-loader": "1.7.3"
|
|
86
|
+
},
|
|
87
|
+
"gitHooks": {
|
|
88
|
+
"pre-commit": "lint-staged"
|
|
89
|
+
},
|
|
90
|
+
"lint-staged": {
|
|
91
|
+
"*.{js,jsx,ts,tsx,vue}": [
|
|
92
|
+
"vue-cli-service lint",
|
|
93
|
+
"git add"
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
diff --git a/node_modules/jsdom-global/keys.js b/node_modules/jsdom-global/keys.js
|
|
2
|
+
index 7777e32..6a56d5d 100644
|
|
3
|
+
--- a/node_modules/jsdom-global/keys.js
|
|
4
|
+
+++ b/node_modules/jsdom-global/keys.js
|
|
5
|
+
@@ -119,6 +119,7 @@ var LIVING_KEYS = [
|
|
6
|
+
'Blob',
|
|
7
|
+
'File',
|
|
8
|
+
'FileList',
|
|
9
|
+
+ 'FileReader',
|
|
10
|
+
'FormData',
|
|
11
|
+
'XMLHttpRequest',
|
|
12
|
+
'XMLHttpRequestEventTarget',
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
diff --git a/node_modules/vue-toastification/src/types/index.ts b/node_modules/vue-toastification/src/types/index.ts
|
|
2
|
+
index 1e27d73..4d9da87 100644
|
|
3
|
+
--- a/node_modules/vue-toastification/src/types/index.ts
|
|
4
|
+
+++ b/node_modules/vue-toastification/src/types/index.ts
|
|
5
|
+
@@ -236,16 +236,6 @@ export type ToastOptionsAndRequiredContent = ToastOptions & {
|
|
6
|
+
content: ToastContent;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
-export interface NuxtModuleOptions extends PluginOptions {
|
|
10
|
+
- /**
|
|
11
|
+
- * Path to the CSS file containing styles for the toasts.
|
|
12
|
+
- * By default it is original Vue Toastification CSS file.
|
|
13
|
+
- *
|
|
14
|
+
- * If set to false, no CSS file is injected.
|
|
15
|
+
- */
|
|
16
|
+
- cssFile?: string | false;
|
|
17
|
+
-}
|
|
18
|
+
-
|
|
19
|
+
declare module "vue/types/vue" {
|
|
20
|
+
interface Vue {
|
|
21
|
+
$toast: ReturnType<typeof ToastInterface>;
|
|
22
|
+
@@ -255,19 +245,3 @@ declare module "vue/types/vue" {
|
|
23
|
+
$toast: ReturnType<typeof ToastInterface>;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
-
|
|
27
|
+
-declare module "@nuxt/types" {
|
|
28
|
+
- interface NuxtAppOptions {
|
|
29
|
+
- $toast: ReturnType<typeof ToastInterface>;
|
|
30
|
+
- }
|
|
31
|
+
-
|
|
32
|
+
- interface NuxtOptions {
|
|
33
|
+
- toast?: NuxtModuleOptions;
|
|
34
|
+
- }
|
|
35
|
+
-}
|
|
36
|
+
-
|
|
37
|
+
-declare module "vuex/types/index" {
|
|
38
|
+
- interface Store<S> {
|
|
39
|
+
- $toast: ReturnType<typeof ToastInterface>;
|
|
40
|
+
- }
|
|
41
|
+
-}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
diff --git a/node_modules/vuetify/lib/directives/ripple/index.js b/node_modules/vuetify/lib/directives/ripple/index.js
|
|
2
|
+
index c895ae0..44249ae 100644
|
|
3
|
+
--- a/node_modules/vuetify/lib/directives/ripple/index.js
|
|
4
|
+
+++ b/node_modules/vuetify/lib/directives/ripple/index.js
|
|
5
|
+
@@ -120,7 +120,7 @@ const ripples = {
|
|
6
|
+
delete el.dataset.previousPosition;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
- animation.parentNode && el.removeChild(animation.parentNode);
|
|
10
|
+
+ animation.parentNode && animation.parentNode.parentNode.removeChild(animation.parentNode);
|
|
11
|
+
}, 300);
|
|
12
|
+
}, delay);
|
|
13
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
html {
|
|
2
|
+
overflow: hidden !important;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
body {
|
|
6
|
+
position: fixed;
|
|
7
|
+
width: 100%;
|
|
8
|
+
height: 100%;
|
|
9
|
+
user-select: none;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.no-select {
|
|
13
|
+
user-select: none;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.text-ellipsis {
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
text-overflow: ellipsis;
|
|
19
|
+
white-space: nowrap;
|
|
20
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<% if (htmlWebpackPlugin.options.ga) { %>
|
|
5
|
+
<script async src="https://www.googletagmanager.com/gtag/js?id=<%= htmlWebpackPlugin.options.ga %>"></script>
|
|
6
|
+
<script>
|
|
7
|
+
window.dataLayer = window.dataLayer || [];
|
|
8
|
+
function gtag(){dataLayer.push(arguments);}
|
|
9
|
+
gtag('js', new Date());
|
|
10
|
+
gtag('config', '<%= htmlWebpackPlugin.options.ga %>');
|
|
11
|
+
</script>
|
|
12
|
+
<% } %>
|
|
13
|
+
<meta charset="utf-8">
|
|
14
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
15
|
+
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
16
|
+
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
|
17
|
+
<title><%= htmlWebpackPlugin.options.title %></title>
|
|
18
|
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
|
|
19
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
|
|
20
|
+
</head>
|
|
21
|
+
<body>
|
|
22
|
+
<noscript>
|
|
23
|
+
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
|
24
|
+
</noscript>
|
|
25
|
+
<div id="app"></div>
|
|
26
|
+
<!-- built files will be auto injected -->
|
|
27
|
+
</body>
|
|
28
|
+
</html>
|
|
Binary file
|
package/server/helper.py
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import traceback
|
|
2
|
+
import wslink
|
|
3
|
+
from serialize import RpcDecoder, RpcEncoder, DEFAULT_DECODERS, DEFAULT_ENCODERS
|
|
4
|
+
from wslink.websocket import LinkProtocol
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
RPC_DEFERRED_TYPE = 'rpc.deferred'
|
|
8
|
+
RPC_RESULT_TYPE = 'rpc.result'
|
|
9
|
+
RPC_ERROR_TYPE = 'rpc.error'
|
|
10
|
+
DEFERRED_RESPONSE_TYPE = 'deferred.response'
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class FutureResult(object):
|
|
14
|
+
def __init__(self, id):
|
|
15
|
+
self._id = id
|
|
16
|
+
self._done = False
|
|
17
|
+
self._result = None
|
|
18
|
+
self._exception = None
|
|
19
|
+
self._callbacks = []
|
|
20
|
+
|
|
21
|
+
def id(self):
|
|
22
|
+
return self._id
|
|
23
|
+
|
|
24
|
+
def done(self):
|
|
25
|
+
return self._done
|
|
26
|
+
|
|
27
|
+
def result(self):
|
|
28
|
+
if not self._done:
|
|
29
|
+
raise Exception('Future is not done')
|
|
30
|
+
return self._result
|
|
31
|
+
|
|
32
|
+
def exception(self):
|
|
33
|
+
if not self._done:
|
|
34
|
+
raise Exception('Future is not done')
|
|
35
|
+
return self._exception
|
|
36
|
+
|
|
37
|
+
def has_result(self):
|
|
38
|
+
return self._done and bool(self._result)
|
|
39
|
+
|
|
40
|
+
def has_exception(self):
|
|
41
|
+
return self._done and bool(self._exception)
|
|
42
|
+
|
|
43
|
+
def add_done_callback(self, cb):
|
|
44
|
+
self._callbacks.append(cb)
|
|
45
|
+
|
|
46
|
+
def remove_done_callback(self, cb):
|
|
47
|
+
self._callbacks.remove(cb)
|
|
48
|
+
|
|
49
|
+
def set_result(self, result):
|
|
50
|
+
if not self._done:
|
|
51
|
+
self._done = True
|
|
52
|
+
self._result = result
|
|
53
|
+
self._trigger_callbacks()
|
|
54
|
+
|
|
55
|
+
def set_exception(self, exception):
|
|
56
|
+
if not self._done:
|
|
57
|
+
self._done = True
|
|
58
|
+
self._exception = exception
|
|
59
|
+
self._trigger_callbacks()
|
|
60
|
+
|
|
61
|
+
def _trigger_callbacks(self):
|
|
62
|
+
for cb in self._callbacks:
|
|
63
|
+
try:
|
|
64
|
+
cb(self)
|
|
65
|
+
except:
|
|
66
|
+
pass
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def make_deferred_response(future):
|
|
70
|
+
return {
|
|
71
|
+
'type': RPC_DEFERRED_TYPE,
|
|
72
|
+
'id': future.id(),
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def make_result_response(result):
|
|
77
|
+
return {
|
|
78
|
+
'type': RPC_RESULT_TYPE,
|
|
79
|
+
'result': result,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def make_error_response(exc):
|
|
84
|
+
return {
|
|
85
|
+
'type': RPC_ERROR_TYPE,
|
|
86
|
+
'error': str(exc),
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def deserialize(args, kwargs):
|
|
91
|
+
decoder = RpcDecoder(hooks=DEFAULT_DECODERS)
|
|
92
|
+
new_args = [decoder.decode(arg) for arg in args]
|
|
93
|
+
return new_args, kwargs
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def rpc(name):
|
|
97
|
+
def wrapper(fn):
|
|
98
|
+
def handler(self, *args, **kwargs):
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
args, kwargs = deserialize(args, kwargs)
|
|
102
|
+
result = fn(self, *args, **kwargs)
|
|
103
|
+
except Exception as e:
|
|
104
|
+
traceback.print_exc()
|
|
105
|
+
return make_error_response(e)
|
|
106
|
+
else:
|
|
107
|
+
if type(result) is FutureResult:
|
|
108
|
+
self._futures.append(result)
|
|
109
|
+
result.set_done_callback(self._handle_future_result)
|
|
110
|
+
return make_deferred_response(result.id())
|
|
111
|
+
|
|
112
|
+
return make_result_response(self.serialize(result))
|
|
113
|
+
|
|
114
|
+
return wslink.register(name)(handler)
|
|
115
|
+
return wrapper
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class RpcApi(LinkProtocol):
|
|
119
|
+
def __init__(self, *args, **kwargs):
|
|
120
|
+
super().__init__(*args, **kwargs)
|
|
121
|
+
self._futures = []
|
|
122
|
+
|
|
123
|
+
def _handle_future_result(self, future):
|
|
124
|
+
self._futures.remove(future)
|
|
125
|
+
self.publish('deferred.responses',
|
|
126
|
+
self._make_deferred_result_response(future))
|
|
127
|
+
|
|
128
|
+
def _make_deferred_result_response(self, future):
|
|
129
|
+
if future.has_exception():
|
|
130
|
+
return {
|
|
131
|
+
'type': DEFERRED_RESPONSE_TYPE,
|
|
132
|
+
'id': future.id(),
|
|
133
|
+
'rpcResponse': make_error_response(future.exception())
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
'type': DEFERRED_RESPONSE_TYPE,
|
|
137
|
+
'id': future.id(),
|
|
138
|
+
'rpcResponse': make_result_response(self.serialize(future.result()))
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
def serialize(self, obj):
|
|
142
|
+
try:
|
|
143
|
+
encoder = RpcEncoder(encoders=DEFAULT_ENCODERS,
|
|
144
|
+
extra_args=(self.addAttachment,))
|
|
145
|
+
return encoder.encode(obj)
|
|
146
|
+
except:
|
|
147
|
+
traceback.print_exc()
|
package/server/host.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/* eslint-disable-next-line max-classes-per-file */
|
|
2
|
+
import WebsocketConnection from 'wslink/src/WebsocketConnection';
|
|
3
|
+
import { defer } from '../src/utils/common';
|
|
4
|
+
|
|
5
|
+
import { deserialize, serialize } from './serialize';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Matches a response against valid type names
|
|
9
|
+
*/
|
|
10
|
+
function isValidResponse(response, types) {
|
|
11
|
+
const rtype = response?.type;
|
|
12
|
+
if (!types.includes(rtype)) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
switch (rtype) {
|
|
16
|
+
case 'rpc.result':
|
|
17
|
+
return 'result' in response;
|
|
18
|
+
case 'rpc.error':
|
|
19
|
+
return 'error' in response;
|
|
20
|
+
case 'rpc.deferred':
|
|
21
|
+
return 'id' in response;
|
|
22
|
+
case 'deferred.response':
|
|
23
|
+
return 'id' in response && 'rpcResponse' in response;
|
|
24
|
+
default:
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class RpcError extends Error {}
|
|
30
|
+
|
|
31
|
+
export default class HostConnection {
|
|
32
|
+
constructor(wsUrl) {
|
|
33
|
+
this.ws = null;
|
|
34
|
+
this.wsUrl = wsUrl;
|
|
35
|
+
this.connected = false;
|
|
36
|
+
this.deferredResponses = new Map();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async connect() {
|
|
40
|
+
return new Promise((resolve, reject) => {
|
|
41
|
+
if (!this.connected) {
|
|
42
|
+
this.ws = WebsocketConnection.newInstance({ urls: this.wsUrl });
|
|
43
|
+
|
|
44
|
+
this.ws.onConnectionReady(() => {
|
|
45
|
+
this.connected = true;
|
|
46
|
+
this.session = this.ws.getSession();
|
|
47
|
+
|
|
48
|
+
this.session.subscribe(
|
|
49
|
+
'deferred.responses',
|
|
50
|
+
this.handleDeferredResponse
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
resolve();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
this.ws.onConnectionClose(() => {
|
|
57
|
+
this.connected = false;
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
this.ws.onConnectionError(() => {
|
|
61
|
+
reject(new Error('Failed to connect to ws endpoint'));
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
this.ws.connect();
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async disconnect() {
|
|
70
|
+
if (this.connected) {
|
|
71
|
+
this.ws.destroy();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async call(endpoint, ...args) {
|
|
76
|
+
if (!this.connected) {
|
|
77
|
+
throw new Error('Not connected');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const attach = (obj) => {
|
|
81
|
+
if (ArrayBuffer.isView(obj) && !(obj instanceof DataView)) {
|
|
82
|
+
return this.session.addAttachment(obj.buffer);
|
|
83
|
+
}
|
|
84
|
+
return obj;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const preparedArgs = args.map((arg) => serialize(arg, attach));
|
|
88
|
+
|
|
89
|
+
const response = await this.session.call(endpoint, preparedArgs);
|
|
90
|
+
return this.handleRpcResponse(response);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async handleRpcResponse(response) {
|
|
94
|
+
if (
|
|
95
|
+
!isValidResponse(response, ['rpc.result', 'rpc.error', 'rpc.deferred'])
|
|
96
|
+
) {
|
|
97
|
+
throw new Error('Invalid response from rpc');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (response.type === 'rpc.deferred') {
|
|
101
|
+
const deferred = defer();
|
|
102
|
+
this.deferredResponses.set(response.id, deferred);
|
|
103
|
+
return deferred.promise;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (response.type === 'rpc.error') {
|
|
107
|
+
throw new RpcError(response.error);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const result = await deserialize(response.result);
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async handleDeferredResponse(response) {
|
|
115
|
+
if (!isValidResponse(response, ['deferred.result'])) {
|
|
116
|
+
throw new Error('Invalid deferred response');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const { id } = response;
|
|
120
|
+
if (!this.deferredResponses.has(id)) {
|
|
121
|
+
throw new Error('Received a deferred response for a nonexistent call');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const deferred = this.deferredResponses.get(id);
|
|
125
|
+
this.deferredResponses.delete(id);
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
const result = await this.handleRpcResponse(response.rpcResponse);
|
|
129
|
+
deferred.resolve(result);
|
|
130
|
+
} catch (e) {
|
|
131
|
+
deferred.reject(e);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import vtk from '@kitware/vtk.js/vtk';
|
|
2
|
+
|
|
3
|
+
export const BREAK = Symbol('Break');
|
|
4
|
+
|
|
5
|
+
export function vtkObjectReplacer(vo) {
|
|
6
|
+
if (vo?.isA?.('vtkObject')) {
|
|
7
|
+
return vo.getState();
|
|
8
|
+
}
|
|
9
|
+
return vo;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function vtkDataArrayJSONReplacer(da, attach) {
|
|
13
|
+
if (da?.classHierarchy?.includes?.('vtkDataArray')) {
|
|
14
|
+
const values = new globalThis[da.dataType](da.values);
|
|
15
|
+
return {
|
|
16
|
+
...da,
|
|
17
|
+
values: attach(values),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
return da;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Serializes typed arrays into regular arrays
|
|
25
|
+
*/
|
|
26
|
+
export function typedArrayReplacer(ta) {
|
|
27
|
+
if (ArrayBuffer.isView(ta) && !(ta instanceof DataView)) {
|
|
28
|
+
return Array.from(ta);
|
|
29
|
+
}
|
|
30
|
+
return ta;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function vtkDataArrayValueReviver(da) {
|
|
34
|
+
if (da?.vtkClass === 'vtkDataArray' && da?.values instanceof Blob) {
|
|
35
|
+
const ab = await da.values.arrayBuffer();
|
|
36
|
+
return {
|
|
37
|
+
...da,
|
|
38
|
+
values: new globalThis[da.dataType](ab),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return da;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function vtkObjectReviver(obj) {
|
|
45
|
+
if ('vtkClass' in obj) {
|
|
46
|
+
return vtk(obj);
|
|
47
|
+
}
|
|
48
|
+
return obj;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const REPLACERS = [
|
|
52
|
+
vtkObjectReplacer,
|
|
53
|
+
vtkDataArrayJSONReplacer,
|
|
54
|
+
typedArrayReplacer,
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
const REVIVERS = [
|
|
58
|
+
vtkDataArrayValueReviver,
|
|
59
|
+
// should be after the vtkDataArrayValueReviver
|
|
60
|
+
vtkObjectReviver,
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
export function serialize(obj, attach) {
|
|
64
|
+
return JSON.parse(
|
|
65
|
+
JSON.stringify(obj, (key, value) => {
|
|
66
|
+
let transformed = value;
|
|
67
|
+
for (let i = 0; i < REPLACERS.length; i += 1) {
|
|
68
|
+
const result = REPLACERS[i](transformed, attach);
|
|
69
|
+
if (result === BREAK) {
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
transformed = result;
|
|
73
|
+
}
|
|
74
|
+
return transformed;
|
|
75
|
+
})
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export async function deserialize(obj) {
|
|
80
|
+
async function revive(o) {
|
|
81
|
+
let transformed = o;
|
|
82
|
+
for (let i = 0; i < REVIVERS.length; i += 1) {
|
|
83
|
+
// eslint-disable-next-line no-await-in-loop
|
|
84
|
+
const result = await REVIVERS[i](transformed);
|
|
85
|
+
if (result === BREAK) {
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
transformed = result;
|
|
89
|
+
}
|
|
90
|
+
return transformed;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function recurseHelper(o) {
|
|
94
|
+
if (Array.isArray(o)) {
|
|
95
|
+
const newArray = await Promise.all(o.map((item) => recurseHelper(item)));
|
|
96
|
+
return revive(newArray);
|
|
97
|
+
}
|
|
98
|
+
if (o instanceof Object && o.constructor === Object) {
|
|
99
|
+
const newO = {};
|
|
100
|
+
await Promise.all(
|
|
101
|
+
Object.keys(o).map(async (k) => {
|
|
102
|
+
newO[k] = await recurseHelper(o[k]);
|
|
103
|
+
})
|
|
104
|
+
);
|
|
105
|
+
return revive(newO);
|
|
106
|
+
}
|
|
107
|
+
return o;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return recurseHelper(obj);
|
|
111
|
+
}
|