matterviz 0.3.1 → 0.3.3
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/dist/EmptyState.svelte +10 -2
- package/dist/FilePicker.svelte +154 -96
- package/dist/Icon.svelte +20 -14
- package/dist/MillerIndexInput.svelte +27 -21
- package/dist/api/optimade.js +6 -6
- package/dist/app.css +216 -178
- package/dist/brillouin/BrillouinZone.svelte +299 -198
- package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneControls.svelte +32 -5
- package/dist/brillouin/BrillouinZoneExportPane.svelte +74 -55
- package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +99 -68
- package/dist/brillouin/BrillouinZoneScene.svelte +277 -165
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneTooltip.svelte +17 -7
- package/dist/brillouin/compute.js +11 -6
- package/dist/chempot-diagram/ChemPotDiagram.svelte +327 -0
- package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +13 -0
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +847 -0
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +16 -0
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +3194 -0
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +16 -0
- package/dist/chempot-diagram/ChemPotScene3D.svelte +11 -0
- package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +7 -0
- package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
- package/dist/chempot-diagram/async-compute.svelte.js +77 -0
- package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
- package/dist/chempot-diagram/chempot-worker.js +11 -0
- package/dist/chempot-diagram/color.d.ts +10 -0
- package/dist/chempot-diagram/color.js +32 -0
- package/dist/chempot-diagram/compute.d.ts +48 -0
- package/dist/chempot-diagram/compute.js +812 -0
- package/dist/chempot-diagram/index.d.ts +6 -0
- package/dist/chempot-diagram/index.js +6 -0
- package/dist/chempot-diagram/pointer.d.ts +16 -0
- package/dist/chempot-diagram/pointer.js +40 -0
- package/dist/chempot-diagram/temperature.d.ts +15 -0
- package/dist/chempot-diagram/temperature.js +36 -0
- package/dist/chempot-diagram/types.d.ts +86 -0
- package/dist/chempot-diagram/types.js +28 -0
- package/dist/colors/index.d.ts +3 -1
- package/dist/colors/index.js +9 -3
- package/dist/composition/BarChart.svelte +141 -77
- package/dist/composition/BubbleChart.svelte +107 -52
- package/dist/composition/Composition.svelte +100 -79
- package/dist/composition/Formula.svelte +108 -62
- package/dist/composition/FormulaFilter.svelte +973 -353
- package/dist/composition/FormulaFilter.svelte.d.ts +35 -1
- package/dist/composition/PieChart.svelte +199 -99
- package/dist/composition/PieChart.svelte.d.ts +1 -1
- package/dist/composition/format.d.ts +5 -0
- package/dist/composition/format.js +20 -3
- package/dist/composition/parse.js +14 -9
- package/dist/convex-hull/ConvexHull.svelte +93 -38
- package/dist/convex-hull/ConvexHull2D.svelte +551 -393
- package/dist/convex-hull/ConvexHull3D.svelte +1303 -825
- package/dist/convex-hull/ConvexHull4D.svelte +1012 -686
- package/dist/convex-hull/ConvexHullControls.svelte +115 -28
- package/dist/convex-hull/ConvexHullInfoPane.svelte +29 -3
- package/dist/convex-hull/ConvexHullStats.svelte +821 -249
- package/dist/convex-hull/ConvexHullStats.svelte.d.ts +6 -1
- package/dist/convex-hull/ConvexHullTooltip.svelte +41 -16
- package/dist/convex-hull/GasPressureControls.svelte +104 -61
- package/dist/convex-hull/StructurePopup.svelte +25 -4
- package/dist/convex-hull/TemperatureSlider.svelte +45 -25
- package/dist/convex-hull/barycentric-coords.js +13 -7
- package/dist/convex-hull/demo-temperature.d.ts +6 -0
- package/dist/convex-hull/demo-temperature.js +40 -0
- package/dist/convex-hull/gas-thermodynamics.js +17 -12
- package/dist/convex-hull/helpers.d.ts +10 -1
- package/dist/convex-hull/helpers.js +79 -38
- package/dist/convex-hull/index.d.ts +1 -0
- package/dist/convex-hull/index.js +1 -0
- package/dist/convex-hull/thermodynamics.d.ts +8 -21
- package/dist/convex-hull/thermodynamics.js +163 -69
- package/dist/convex-hull/types.d.ts +12 -12
- package/dist/convex-hull/types.js +0 -12
- package/dist/coordination/CoordinationBarPlot.svelte +232 -176
- package/dist/element/BohrAtom.svelte +56 -13
- package/dist/element/ElementHeading.svelte +7 -2
- package/dist/element/ElementPhoto.svelte +15 -9
- package/dist/element/ElementStats.svelte +10 -4
- package/dist/element/ElementTile.svelte +137 -73
- package/dist/element/Nucleus.svelte +39 -11
- package/dist/element/data.js +2 -14
- package/dist/element/data.json.gz +0 -0
- package/dist/element/types.d.ts +1 -0
- package/dist/feedback/ClickFeedback.svelte +16 -5
- package/dist/feedback/DragOverlay.svelte +10 -2
- package/dist/feedback/Spinner.svelte +4 -2
- package/dist/feedback/StatusMessage.svelte +8 -2
- package/dist/fermi-surface/FermiSlice.svelte +118 -88
- package/dist/fermi-surface/FermiSurface.svelte +336 -239
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceControls.svelte +113 -46
- package/dist/fermi-surface/FermiSurfaceScene.svelte +536 -343
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +14 -5
- package/dist/fermi-surface/compute.js +16 -20
- package/dist/fermi-surface/parse.js +37 -33
- package/dist/fermi-surface/symmetry.js +2 -7
- package/dist/fermi-surface/types.d.ts +3 -5
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +1527 -0
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +110 -0
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +225 -0
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +30 -0
- package/dist/heatmap-matrix/index.d.ts +53 -0
- package/dist/heatmap-matrix/index.js +100 -0
- package/dist/heatmap-matrix/shared.d.ts +2 -0
- package/dist/heatmap-matrix/shared.js +4 -0
- package/dist/icons.d.ts +111 -0
- package/dist/icons.js +158 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +5 -2
- package/dist/io/decompress.js +1 -1
- package/dist/io/export.d.ts +3 -0
- package/dist/io/export.js +138 -140
- package/dist/io/file-drop.d.ts +7 -0
- package/dist/io/file-drop.js +43 -0
- package/dist/io/index.d.ts +2 -2
- package/dist/io/index.js +2 -112
- package/dist/io/is-binary.js +2 -3
- package/dist/io/types.d.ts +1 -0
- package/dist/io/url-drop.d.ts +2 -0
- package/dist/io/url-drop.js +117 -0
- package/dist/isosurface/Isosurface.svelte +220 -110
- package/dist/isosurface/IsosurfaceControls.svelte +65 -28
- package/dist/isosurface/parse.js +104 -56
- package/dist/isosurface/slice.d.ts +2 -1
- package/dist/isosurface/slice.js +8 -13
- package/dist/isosurface/types.d.ts +14 -1
- package/dist/isosurface/types.js +152 -5
- package/dist/labels.d.ts +2 -1
- package/dist/labels.js +12 -8
- package/dist/layout/FullscreenToggle.svelte +11 -2
- package/dist/layout/InfoCard.svelte +38 -6
- package/dist/layout/InfoTag.svelte +125 -94
- package/dist/layout/PropertyFilter.svelte +82 -37
- package/dist/layout/SettingsSection.svelte +85 -55
- package/dist/layout/SubpageGrid.svelte +82 -0
- package/dist/layout/SubpageGrid.svelte.d.ts +14 -0
- package/dist/layout/index.d.ts +1 -0
- package/dist/layout/index.js +1 -0
- package/dist/layout/json-tree/JsonNode.svelte +266 -223
- package/dist/layout/json-tree/JsonTree.svelte +516 -429
- package/dist/layout/json-tree/JsonTree.svelte.d.ts +1 -1
- package/dist/layout/json-tree/JsonValue.svelte +281 -173
- package/dist/layout/json-tree/types.d.ts +10 -2
- package/dist/layout/json-tree/utils.d.ts +2 -0
- package/dist/layout/json-tree/utils.js +37 -2
- package/dist/marching-cubes.js +25 -2
- package/dist/math.d.ts +20 -17
- package/dist/math.js +474 -57
- package/dist/overlays/ContextMenu.svelte +66 -40
- package/dist/overlays/DraggablePane.svelte +331 -154
- package/dist/overlays/DraggablePane.svelte.d.ts +2 -0
- package/dist/periodic-table/PeriodicTable.svelte +278 -145
- package/dist/periodic-table/PeriodicTableControls.svelte +178 -128
- package/dist/periodic-table/PropertySelect.svelte +25 -7
- package/dist/periodic-table/TableInset.svelte +8 -3
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +559 -267
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -2
- package/dist/phase-diagram/PhaseDiagramControls.svelte +131 -51
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +3 -2
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +126 -0
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +15 -0
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +160 -110
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +8 -1
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +217 -86
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +6 -3
- package/dist/phase-diagram/TdbInfoPanel.svelte +28 -4
- package/dist/phase-diagram/build-diagram.js +9 -9
- package/dist/phase-diagram/colors.js +1 -3
- package/dist/phase-diagram/index.d.ts +2 -0
- package/dist/phase-diagram/index.js +2 -0
- package/dist/phase-diagram/parse.js +10 -9
- package/dist/phase-diagram/svg-to-diagram.d.ts +2 -0
- package/dist/phase-diagram/svg-to-diagram.js +869 -0
- package/dist/phase-diagram/types.d.ts +10 -0
- package/dist/phase-diagram/utils.d.ts +8 -4
- package/dist/phase-diagram/utils.js +219 -74
- package/dist/plot/AxisLabel.svelte +51 -0
- package/dist/plot/AxisLabel.svelte.d.ts +16 -0
- package/dist/plot/BarPlot.svelte +1461 -768
- package/dist/plot/BarPlot.svelte.d.ts +3 -3
- package/dist/plot/BarPlotControls.svelte +33 -6
- package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ColorBar.svelte +533 -383
- package/dist/plot/ColorBar.svelte.d.ts +1 -1
- package/dist/plot/ColorScaleSelect.svelte +28 -7
- package/dist/plot/ElementScatter.svelte +38 -16
- package/dist/plot/FillArea.svelte +152 -92
- package/dist/plot/Histogram.svelte +1162 -709
- package/dist/plot/Histogram.svelte.d.ts +1 -1
- package/dist/plot/HistogramControls.svelte +81 -18
- package/dist/plot/HistogramControls.svelte.d.ts +6 -2
- package/dist/plot/InteractiveAxisLabel.svelte +34 -11
- package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
- package/dist/plot/Line.svelte +63 -28
- package/dist/plot/PlotControls.svelte +221 -96
- package/dist/plot/PlotControls.svelte.d.ts +1 -1
- package/dist/plot/PlotLegend.svelte +174 -91
- package/dist/plot/PlotTooltip.svelte +45 -6
- package/dist/plot/PortalSelect.svelte +175 -146
- package/dist/plot/ReferenceLine.svelte +77 -22
- package/dist/plot/ReferenceLine.svelte.d.ts +1 -0
- package/dist/plot/ReferenceLine3D.svelte +132 -107
- package/dist/plot/ReferencePlane.svelte +146 -123
- package/dist/plot/ScatterPlot.svelte +1880 -1156
- package/dist/plot/ScatterPlot.svelte.d.ts +3 -3
- package/dist/plot/ScatterPlot3D.svelte +256 -131
- package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlot3DControls.svelte +300 -297
- package/dist/plot/ScatterPlot3DControls.svelte.d.ts +2 -1
- package/dist/plot/ScatterPlot3DScene.svelte +608 -406
- package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlotControls.svelte +150 -70
- package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ScatterPoint.svelte +98 -26
- package/dist/plot/ScatterPoint.svelte.d.ts +1 -0
- package/dist/plot/SpacegroupBarPlot.svelte +142 -85
- package/dist/plot/Surface3D.svelte +159 -108
- package/dist/plot/ZeroLines.svelte +96 -0
- package/dist/plot/ZeroLines.svelte.d.ts +32 -0
- package/dist/plot/ZoomRect.svelte +23 -0
- package/dist/plot/ZoomRect.svelte.d.ts +8 -0
- package/dist/plot/axis-utils.d.ts +1 -1
- package/dist/plot/axis-utils.js +1 -3
- package/dist/plot/data-cleaning.js +12 -28
- package/dist/plot/data-transform.js +2 -1
- package/dist/plot/fill-utils.js +2 -0
- package/dist/plot/index.d.ts +6 -2
- package/dist/plot/index.js +6 -2
- package/dist/plot/interactions.d.ts +8 -10
- package/dist/plot/interactions.js +2 -3
- package/dist/plot/layout.d.ts +11 -2
- package/dist/plot/layout.js +44 -17
- package/dist/plot/reference-line.d.ts +5 -22
- package/dist/plot/reference-line.js +12 -84
- package/dist/plot/scales.js +24 -36
- package/dist/plot/types.d.ts +53 -40
- package/dist/plot/types.js +12 -7
- package/dist/plot/utils/label-placement.d.ts +32 -15
- package/dist/plot/utils/label-placement.js +227 -63
- package/dist/plot/utils/series-visibility.js +2 -3
- package/dist/plot/utils.d.ts +1 -0
- package/dist/plot/utils.js +14 -0
- package/dist/rdf/RdfPlot.svelte +173 -132
- package/dist/rdf/calc-rdf.js +4 -5
- package/dist/sanitize.d.ts +4 -0
- package/dist/sanitize.js +107 -0
- package/dist/settings.d.ts +21 -6
- package/dist/settings.js +63 -19
- package/dist/spectral/Bands.svelte +963 -412
- package/dist/spectral/Bands.svelte.d.ts +22 -2
- package/dist/spectral/BandsAndDos.svelte +90 -49
- package/dist/spectral/BrillouinBandsDos.svelte +151 -93
- package/dist/spectral/Dos.svelte +389 -258
- package/dist/spectral/helpers.d.ts +23 -1
- package/dist/spectral/helpers.js +119 -51
- package/dist/spectral/types.d.ts +2 -0
- package/dist/state.svelte.d.ts +1 -1
- package/dist/state.svelte.js +3 -2
- package/dist/structure/Arrow.svelte +59 -20
- package/dist/structure/AtomLegend.svelte +231 -129
- package/dist/structure/AtomLegend.svelte.d.ts +1 -1
- package/dist/structure/Bond.svelte +73 -47
- package/dist/structure/CanvasTooltip.svelte +10 -2
- package/dist/structure/CellSelect.svelte +148 -51
- package/dist/structure/Cylinder.svelte +33 -17
- package/dist/structure/Lattice.svelte +88 -33
- package/dist/structure/Structure.svelte +1077 -821
- package/dist/structure/Structure.svelte.d.ts +1 -1
- package/dist/structure/StructureControls.svelte +373 -139
- package/dist/structure/StructureControls.svelte.d.ts +1 -1
- package/dist/structure/StructureExportPane.svelte +124 -89
- package/dist/structure/StructureExportPane.svelte.d.ts +1 -1
- package/dist/structure/StructureInfoPane.svelte +304 -231
- package/dist/structure/StructureScene.svelte +919 -445
- package/dist/structure/StructureScene.svelte.d.ts +16 -7
- package/dist/structure/atom-properties.d.ts +6 -2
- package/dist/structure/atom-properties.js +42 -29
- package/dist/structure/bonding.js +6 -7
- package/dist/structure/export.js +22 -34
- package/dist/structure/ferrox-wasm-types.d.ts +3 -2
- package/dist/structure/ferrox-wasm-types.js +0 -3
- package/dist/structure/ferrox-wasm.d.ts +3 -2
- package/dist/structure/ferrox-wasm.js +2 -3
- package/dist/structure/index.d.ts +16 -0
- package/dist/structure/index.js +88 -6
- package/dist/structure/measure.d.ts +2 -2
- package/dist/structure/measure.js +4 -44
- package/dist/structure/parse.js +130 -155
- package/dist/structure/partial-occupancy.d.ts +25 -0
- package/dist/structure/partial-occupancy.js +99 -0
- package/dist/structure/pbc.d.ts +1 -0
- package/dist/structure/pbc.js +16 -6
- package/dist/structure/supercell.d.ts +2 -2
- package/dist/structure/supercell.js +12 -22
- package/dist/structure/validation.js +5 -3
- package/dist/symmetry/SymmetryStats.svelte +94 -37
- package/dist/symmetry/WyckoffTable.svelte +42 -14
- package/dist/symmetry/cell-transform.js +5 -3
- package/dist/symmetry/index.d.ts +7 -4
- package/dist/symmetry/index.js +87 -21
- package/dist/symmetry/spacegroups.js +148 -148
- package/dist/table/HeatmapTable.svelte +1112 -516
- package/dist/table/HeatmapTable.svelte.d.ts +12 -1
- package/dist/table/ToggleMenu.svelte +125 -90
- package/dist/table/index.d.ts +2 -0
- package/dist/table/index.js +2 -4
- package/dist/theme/ThemeControl.svelte +21 -12
- package/dist/time.js +4 -1
- package/dist/tooltip/TooltipContent.svelte +33 -8
- package/dist/trajectory/Trajectory.svelte +889 -687
- package/dist/trajectory/TrajectoryError.svelte +14 -3
- package/dist/trajectory/TrajectoryExportPane.svelte +148 -90
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +1 -1
- package/dist/trajectory/TrajectoryInfoPane.svelte +272 -143
- package/dist/trajectory/constants.d.ts +6 -0
- package/dist/trajectory/constants.js +7 -0
- package/dist/trajectory/extract.js +13 -31
- package/dist/trajectory/format-detect.d.ts +9 -0
- package/dist/trajectory/format-detect.js +76 -0
- package/dist/trajectory/frame-reader.d.ts +17 -0
- package/dist/trajectory/frame-reader.js +332 -0
- package/dist/trajectory/helpers.d.ts +14 -0
- package/dist/trajectory/helpers.js +172 -0
- package/dist/trajectory/index.d.ts +1 -0
- package/dist/trajectory/index.js +23 -14
- package/dist/trajectory/parse/ase.d.ts +2 -0
- package/dist/trajectory/parse/ase.js +77 -0
- package/dist/trajectory/parse/hdf5.d.ts +2 -0
- package/dist/trajectory/parse/hdf5.js +129 -0
- package/dist/trajectory/parse/index.d.ts +12 -0
- package/dist/trajectory/parse/index.js +299 -0
- package/dist/trajectory/parse/lammps.d.ts +5 -0
- package/dist/trajectory/parse/lammps.js +179 -0
- package/dist/trajectory/parse/vasp.d.ts +2 -0
- package/dist/trajectory/parse/vasp.js +68 -0
- package/dist/trajectory/parse/xyz.d.ts +2 -0
- package/dist/trajectory/parse/xyz.js +110 -0
- package/dist/trajectory/plotting.js +13 -8
- package/dist/trajectory/types.d.ts +11 -0
- package/dist/trajectory/types.js +1 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +17 -0
- package/dist/xrd/XrdPlot.svelte +337 -245
- package/dist/xrd/broadening.js +14 -9
- package/dist/xrd/calc-xrd.js +12 -19
- package/dist/xrd/parse.d.ts +1 -1
- package/dist/xrd/parse.js +17 -17
- package/package.json +103 -101
- package/readme.md +4 -4
- package/dist/trajectory/parse.d.ts +0 -42
- package/dist/trajectory/parse.js +0 -1267
- /package/dist/element/{data.json.d.ts → data.json.gz.d.ts} +0 -0
- /package/dist/theme/{themes.js → themes.mjs} +0 -0
package/dist/io/export.js
CHANGED
|
@@ -1,171 +1,161 @@
|
|
|
1
1
|
import { download } from './fetch';
|
|
2
2
|
import { create_structure_filename } from '../structure/export';
|
|
3
3
|
import { Vector2 } from 'three';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
// Convert DPI to multiplier (72 DPI is baseline web resolution)
|
|
26
|
-
// Cap to a reasonable upper bound to avoid excessive memory use
|
|
27
|
-
const resolution_multiplier = Math.min(png_dpi / 72, 10);
|
|
28
|
-
const renderer = canvas.__renderer;
|
|
29
|
-
// Force render to populate buffer
|
|
4
|
+
function is_webgl_renderer_like(value) {
|
|
5
|
+
if (typeof value !== `object` || !value)
|
|
6
|
+
return false;
|
|
7
|
+
const renderer_obj = value;
|
|
8
|
+
return (typeof renderer_obj.render === `function` &&
|
|
9
|
+
typeof renderer_obj.getPixelRatio === `function` &&
|
|
10
|
+
typeof renderer_obj.setPixelRatio === `function` &&
|
|
11
|
+
typeof renderer_obj.getSize === `function` &&
|
|
12
|
+
typeof renderer_obj.setSize === `function`);
|
|
13
|
+
}
|
|
14
|
+
// Capture a WebGL canvas as a PNG Blob at the given DPI.
|
|
15
|
+
// Temporarily adjusts renderer pixel ratio for high-res capture, then restores.
|
|
16
|
+
// Returns data directly (no browser download), suitable for programmatic capture
|
|
17
|
+
// in test suites, server-side rendering, or Python widget integration via anywidget.
|
|
18
|
+
// DPI is converted to a resolution multiplier relative to 72 DPI baseline, capped at 10x.
|
|
19
|
+
export function canvas_to_png_blob(canvas, png_dpi = 150, scene = null, camera = null) {
|
|
20
|
+
const resolution_multiplier = Math.min(png_dpi / 72, 10);
|
|
21
|
+
const renderer_val = canvas.__renderer;
|
|
22
|
+
const renderer = is_webgl_renderer_like(renderer_val) ? renderer_val : undefined;
|
|
23
|
+
if (resolution_multiplier <= 1.1 || !renderer) {
|
|
30
24
|
if (renderer && scene && camera)
|
|
31
25
|
renderer.render(scene, camera);
|
|
32
|
-
|
|
33
|
-
// Direct capture at current resolution (if DPI is close to 72 or renderer not available)
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
34
27
|
try {
|
|
35
28
|
canvas.toBlob((blob) => {
|
|
36
|
-
if (blob)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (typeof window !== `undefined`) {
|
|
41
|
-
console.warn(`Failed to generate PNG - canvas may be empty`);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
29
|
+
if (blob)
|
|
30
|
+
resolve(blob);
|
|
31
|
+
else
|
|
32
|
+
reject(new Error(`Failed to generate PNG - canvas may be empty`));
|
|
44
33
|
}, `image/png`);
|
|
45
34
|
}
|
|
46
35
|
catch (error) {
|
|
47
|
-
|
|
36
|
+
reject(error);
|
|
48
37
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
// Temporarily modify the renderer's pixel ratio for high-res capture
|
|
41
|
+
const orig_pixel_ratio = renderer.getPixelRatio();
|
|
42
|
+
const orig_size = renderer.getSize(new Vector2());
|
|
43
|
+
const restore = () => {
|
|
44
|
+
renderer.setPixelRatio(orig_pixel_ratio);
|
|
45
|
+
renderer.setSize(orig_size.width, orig_size.height, false);
|
|
46
|
+
};
|
|
47
|
+
renderer.setPixelRatio(resolution_multiplier);
|
|
48
|
+
renderer.setSize(orig_size.width, orig_size.height, false);
|
|
49
|
+
if (scene && camera)
|
|
50
|
+
renderer.render(scene, camera);
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
54
52
|
try {
|
|
55
|
-
// Set higher pixel ratio to increase rendering resolution
|
|
56
|
-
renderer.setPixelRatio(resolution_multiplier);
|
|
57
|
-
// Force the canvas to update its resolution
|
|
58
|
-
renderer.setSize(orig_size.width, orig_size.height, false);
|
|
59
|
-
if (scene && camera) {
|
|
60
|
-
renderer.render(scene, camera);
|
|
61
|
-
}
|
|
62
|
-
// Capture the high-resolution render after paint completion
|
|
63
53
|
canvas.toBlob((blob) => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
if (typeof window !== `undefined`) {
|
|
72
|
-
console.warn(`Failed to generate high-resolution PNG`);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
54
|
+
restore();
|
|
55
|
+
if (blob)
|
|
56
|
+
resolve(blob);
|
|
57
|
+
else
|
|
58
|
+
reject(new Error(`Failed to generate high-resolution PNG`));
|
|
75
59
|
}, `image/png`);
|
|
76
60
|
}
|
|
77
61
|
catch (error) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
renderer.setPixelRatio(orig_pixel_ratio);
|
|
81
|
-
renderer.setSize(orig_size.width, orig_size.height, false);
|
|
82
|
-
if (typeof window !== `undefined`) {
|
|
83
|
-
console.warn(`Failed to render at high resolution: ${error instanceof Error ? error.message : String(error)}`);
|
|
84
|
-
}
|
|
62
|
+
restore();
|
|
63
|
+
reject(error);
|
|
85
64
|
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
// Export structure as PNG image from canvas (triggers browser download)
|
|
68
|
+
export function export_canvas_as_png(canvas, structure_or_filename, png_dpi = 150, scene = null, camera = null) {
|
|
69
|
+
if (!canvas) {
|
|
70
|
+
if (typeof window !== `undefined`)
|
|
71
|
+
console.warn(`Canvas not found for PNG export`);
|
|
72
|
+
return;
|
|
86
73
|
}
|
|
87
|
-
|
|
88
|
-
|
|
74
|
+
let filename = typeof structure_or_filename === `string`
|
|
75
|
+
? structure_or_filename
|
|
76
|
+
: create_structure_filename(structure_or_filename, `png`);
|
|
77
|
+
const suffix = `-${Math.round(png_dpi)}dpi`;
|
|
78
|
+
if (filename.toLowerCase().endsWith(`.png`)) {
|
|
79
|
+
filename = filename.replace(/\.png$/i, `${suffix}.png`);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
filename = `${filename}${suffix}.png`;
|
|
89
83
|
}
|
|
84
|
+
canvas_to_png_blob(canvas, png_dpi, scene, camera)
|
|
85
|
+
.then((blob) => download(blob, filename, `image/png`))
|
|
86
|
+
.catch((error) => console.error(`Error exporting PNG:`, error));
|
|
90
87
|
}
|
|
91
88
|
// Helper to ensure font-family is set on SVG root
|
|
92
89
|
function set_svg_font_family(svg) {
|
|
93
90
|
const style = svg.getAttribute(`style`) || ``;
|
|
94
91
|
if (!/font-family/.test(style)) {
|
|
95
|
-
svg.setAttribute(`style`, `${style}
|
|
92
|
+
svg.setAttribute(`style`, `${style}${style ? `;` : ``}font-family:sans-serif;`);
|
|
96
93
|
}
|
|
97
94
|
// Also set as attribute for extra robustness
|
|
98
95
|
svg.setAttribute(`font-family`, `sans-serif`);
|
|
99
96
|
}
|
|
100
|
-
//
|
|
97
|
+
// Serialize an SVG element to a standalone SVG string with proper XML headers.
|
|
98
|
+
// Clones the element to avoid mutation, sets font-family/xmlns, and
|
|
99
|
+
// prepends XML declaration + SVG DOCTYPE. Returns a complete SVG document string
|
|
100
|
+
// suitable for saving to file or further processing.
|
|
101
|
+
export function svg_to_svg_string(svg_element) {
|
|
102
|
+
const cloned_svg = svg_element.cloneNode(true);
|
|
103
|
+
set_svg_font_family(cloned_svg);
|
|
104
|
+
if (!cloned_svg.hasAttribute(`xmlns`)) {
|
|
105
|
+
cloned_svg.setAttribute(`xmlns`, `http://www.w3.org/2000/svg`);
|
|
106
|
+
}
|
|
107
|
+
const svg_string = new XMLSerializer().serializeToString(cloned_svg);
|
|
108
|
+
return `<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n${svg_string}`;
|
|
109
|
+
}
|
|
110
|
+
// Export SVG element as SVG file (triggers browser download)
|
|
101
111
|
export function export_svg_as_svg(svg_element, filename) {
|
|
112
|
+
if (!svg_element) {
|
|
113
|
+
console.warn(`SVG element not found for export`);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
102
116
|
try {
|
|
103
|
-
|
|
104
|
-
console.warn(`SVG element not found for export`);
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
// Clone the SVG to avoid modifying the original
|
|
108
|
-
const cloned_svg = svg_element.cloneNode(true);
|
|
109
|
-
// Ensure the SVG has proper dimensions and viewBox
|
|
110
|
-
const viewBox = svg_element.getAttribute(`viewBox`);
|
|
111
|
-
if (viewBox)
|
|
112
|
-
cloned_svg.setAttribute(`viewBox`, viewBox);
|
|
113
|
-
// Ensure font-family is set
|
|
114
|
-
set_svg_font_family(cloned_svg);
|
|
115
|
-
// Ensure xmlns is set
|
|
116
|
-
if (!cloned_svg.hasAttribute(`xmlns`)) {
|
|
117
|
-
cloned_svg.setAttribute(`xmlns`, `http://www.w3.org/2000/svg`);
|
|
118
|
-
}
|
|
119
|
-
// Convert SVG to string
|
|
120
|
-
const svg_string = new XMLSerializer().serializeToString(cloned_svg);
|
|
121
|
-
// Add XML declaration and DOCTYPE for proper SVG format
|
|
122
|
-
const svg_content = `<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n${svg_string}`;
|
|
117
|
+
const svg_content = svg_to_svg_string(svg_element);
|
|
123
118
|
download(svg_content, filename, `image/svg+xml;charset=utf-8`);
|
|
124
119
|
}
|
|
125
120
|
catch (error) {
|
|
126
121
|
console.error(`Error exporting SVG:`, error);
|
|
127
122
|
}
|
|
128
123
|
}
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
// Create an object URL from SVG Blob
|
|
165
|
-
const svg_string = new XMLSerializer().serializeToString(cloned_svg);
|
|
166
|
-
const svg_blob = new Blob([svg_string], { type: `image/svg+xml;charset=utf-8` });
|
|
167
|
-
const svg_data_url = URL.createObjectURL(svg_blob);
|
|
168
|
-
// Create an image element to load the SVG
|
|
124
|
+
// Rasterize an SVG element to a PNG Blob at the given DPI.
|
|
125
|
+
// Creates an offscreen canvas at the scaled resolution, draws the SVG via an
|
|
126
|
+
// Image element, and returns the resulting PNG Blob. Rejects if viewBox is
|
|
127
|
+
// missing or dimensions are invalid (zero width/height).
|
|
128
|
+
// DPI is converted to a resolution multiplier relative to 72 DPI baseline, capped at 10x.
|
|
129
|
+
export function svg_to_png_blob(svg_element, png_dpi = 150) {
|
|
130
|
+
const viewBox = svg_element.getAttribute(`viewBox`)?.trim();
|
|
131
|
+
if (!viewBox)
|
|
132
|
+
return Promise.reject(new Error(`SVG viewBox not found for PNG export`));
|
|
133
|
+
const parts = viewBox.split(/[\s,]+/).map(Number);
|
|
134
|
+
if (parts.length < 4 || !parts.every(Number.isFinite)) {
|
|
135
|
+
return Promise.reject(new Error(`Invalid SVG dimensions for PNG export`));
|
|
136
|
+
}
|
|
137
|
+
const [, , width, height] = parts;
|
|
138
|
+
if (!(width > 0) || !(height > 0)) {
|
|
139
|
+
return Promise.reject(new Error(`Invalid SVG dimensions for PNG export`));
|
|
140
|
+
}
|
|
141
|
+
if (!Number.isFinite(png_dpi) || png_dpi <= 0) {
|
|
142
|
+
return Promise.reject(new Error(`Invalid PNG DPI for export`));
|
|
143
|
+
}
|
|
144
|
+
const resolution_multiplier = Math.min(png_dpi / 72, 10);
|
|
145
|
+
const pixel_width = Math.round(width * resolution_multiplier);
|
|
146
|
+
const pixel_height = Math.round(height * resolution_multiplier);
|
|
147
|
+
const canvas = document.createElement(`canvas`);
|
|
148
|
+
const ctx = canvas.getContext(`2d`);
|
|
149
|
+
if (!ctx)
|
|
150
|
+
return Promise.reject(new Error(`Canvas 2D context not available`));
|
|
151
|
+
canvas.width = pixel_width;
|
|
152
|
+
canvas.height = pixel_height;
|
|
153
|
+
const cloned_svg = svg_element.cloneNode(true);
|
|
154
|
+
set_svg_font_family(cloned_svg);
|
|
155
|
+
const serialized = new XMLSerializer().serializeToString(cloned_svg);
|
|
156
|
+
const svg_blob = new Blob([serialized], { type: `image/svg+xml;charset=utf-8` });
|
|
157
|
+
const svg_data_url = URL.createObjectURL(svg_blob);
|
|
158
|
+
return new Promise((resolve, reject) => {
|
|
169
159
|
const img = new Image();
|
|
170
160
|
img.onload = () => {
|
|
171
161
|
try {
|
|
@@ -173,27 +163,34 @@ export function export_svg_as_png(svg_element, filename, png_dpi = 150) {
|
|
|
173
163
|
ctx.drawImage(img, 0, 0, pixel_width, pixel_height);
|
|
174
164
|
canvas.toBlob((blob) => {
|
|
175
165
|
if (blob)
|
|
176
|
-
|
|
166
|
+
resolve(blob);
|
|
177
167
|
else
|
|
178
|
-
|
|
168
|
+
reject(new Error(`Failed to generate PNG blob`));
|
|
179
169
|
}, `image/png`, 1);
|
|
180
170
|
}
|
|
181
171
|
catch (error) {
|
|
182
|
-
|
|
172
|
+
reject(error);
|
|
183
173
|
}
|
|
184
174
|
finally {
|
|
185
175
|
URL.revokeObjectURL(svg_data_url);
|
|
186
176
|
}
|
|
187
177
|
};
|
|
188
178
|
img.onerror = () => {
|
|
189
|
-
console.error(`Failed to load SVG for PNG export`);
|
|
190
179
|
URL.revokeObjectURL(svg_data_url);
|
|
180
|
+
reject(new Error(`Failed to load SVG for PNG export`));
|
|
191
181
|
};
|
|
192
182
|
img.src = svg_data_url;
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
// Export SVG element as PNG (triggers browser download)
|
|
186
|
+
export function export_svg_as_png(svg_element, filename, png_dpi = 150) {
|
|
187
|
+
if (!svg_element) {
|
|
188
|
+
console.warn(`SVG element not found for PNG export`);
|
|
189
|
+
return;
|
|
193
190
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
191
|
+
svg_to_png_blob(svg_element, png_dpi)
|
|
192
|
+
.then((blob) => download(blob, filename, `image/png`))
|
|
193
|
+
.catch((error) => console.error(`Error exporting PNG:`, error));
|
|
197
194
|
}
|
|
198
195
|
// Generate FFmpeg command for WebM to MP4 conversion
|
|
199
196
|
export function get_ffmpeg_conversion_command(input_filename) {
|
|
@@ -208,7 +205,8 @@ export async function export_trajectory_video(canvas, filename, options = {}) {
|
|
|
208
205
|
typeof MediaRecorder === `undefined` ||
|
|
209
206
|
!MediaRecorder.isTypeSupported(`video/webm;codecs=vp9`))
|
|
210
207
|
throw new Error(`WebM video recording not supported in this browser`);
|
|
211
|
-
const
|
|
208
|
+
const renderer_val = canvas.__renderer;
|
|
209
|
+
const renderer = is_webgl_renderer_like(renderer_val) ? renderer_val : undefined;
|
|
212
210
|
// Store original renderer settings if changing resolution
|
|
213
211
|
let orig_pixel_ratio;
|
|
214
212
|
let orig_size;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface FileDropOptions {
|
|
2
|
+
allow: () => boolean;
|
|
3
|
+
on_drop: (content: string | ArrayBuffer, filename: string) => void | Promise<void>;
|
|
4
|
+
on_error?: (msg: string) => void;
|
|
5
|
+
set_loading?: (loading: boolean) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function create_file_drop_handler(opts: FileDropOptions): (event: DragEvent) => Promise<void>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Shared file-drop handler composable for drag-and-drop file loading.
|
|
2
|
+
import { decompress_file } from './decompress';
|
|
3
|
+
import { handle_url_drop } from './url-drop';
|
|
4
|
+
// Handles URL drops (from FilePicker), direct file drops with decompression,
|
|
5
|
+
// loading state, and error reporting.
|
|
6
|
+
export function create_file_drop_handler(opts) {
|
|
7
|
+
return async (event) => {
|
|
8
|
+
event.preventDefault();
|
|
9
|
+
if (!opts.allow())
|
|
10
|
+
return;
|
|
11
|
+
opts.set_loading?.(true);
|
|
12
|
+
let drop_filename = ``;
|
|
13
|
+
try {
|
|
14
|
+
let url_error;
|
|
15
|
+
const handled = await handle_url_drop(event, opts.on_drop).catch((exc) => {
|
|
16
|
+
url_error = exc instanceof Error ? exc.message : String(exc);
|
|
17
|
+
return false;
|
|
18
|
+
});
|
|
19
|
+
if (handled)
|
|
20
|
+
return;
|
|
21
|
+
const file = event.dataTransfer?.files[0];
|
|
22
|
+
if (!file) {
|
|
23
|
+
if (url_error)
|
|
24
|
+
opts.on_error?.(`Failed to load from URL: ${url_error}`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
drop_filename = file.name;
|
|
28
|
+
const { content, filename } = await decompress_file(file);
|
|
29
|
+
if (content)
|
|
30
|
+
await opts.on_drop(content, filename);
|
|
31
|
+
}
|
|
32
|
+
catch (exc) {
|
|
33
|
+
const detail = exc instanceof Error ? exc.message : String(exc);
|
|
34
|
+
const msg = drop_filename
|
|
35
|
+
? `Failed to load file ${drop_filename}: ${detail}`
|
|
36
|
+
: `Failed to load file: ${detail}`;
|
|
37
|
+
opts.on_error?.(msg);
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
opts.set_loading?.(false);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
package/dist/io/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from './decompress';
|
|
2
2
|
export * from './export';
|
|
3
3
|
export * from './fetch';
|
|
4
|
+
export * from './file-drop';
|
|
4
5
|
export * from './is-binary';
|
|
5
6
|
export * from './types';
|
|
6
|
-
export
|
|
7
|
-
export declare function load_from_url(url: string, callback: (content: string | ArrayBuffer, filename: string) => Promise<void> | void): Promise<void>;
|
|
7
|
+
export * from './url-drop';
|
package/dist/io/index.js
CHANGED
|
@@ -1,117 +1,7 @@
|
|
|
1
|
-
import { load_binary_traj } from '../trajectory/parse';
|
|
2
1
|
export * from './decompress';
|
|
3
2
|
export * from './export';
|
|
4
3
|
export * from './fetch';
|
|
4
|
+
export * from './file-drop';
|
|
5
5
|
export * from './is-binary';
|
|
6
6
|
export * from './types';
|
|
7
|
-
|
|
8
|
-
export async function handle_url_drop(drag_event, callback) {
|
|
9
|
-
const json_data = drag_event.dataTransfer?.getData(`application/json`);
|
|
10
|
-
if (!json_data)
|
|
11
|
-
return false;
|
|
12
|
-
const file_info = JSON.parse(json_data);
|
|
13
|
-
if (!file_info.url)
|
|
14
|
-
return false;
|
|
15
|
-
await load_from_url(file_info.url, callback);
|
|
16
|
-
return true;
|
|
17
|
-
}
|
|
18
|
-
export async function load_from_url(url, callback) {
|
|
19
|
-
const url_basename = url.split(`/`).pop() || url;
|
|
20
|
-
const ext = url_basename.split(`.`).pop()?.toLowerCase() || ``;
|
|
21
|
-
const extract_filename = (headers) => {
|
|
22
|
-
const fallback = url_basename;
|
|
23
|
-
if (!headers)
|
|
24
|
-
return fallback;
|
|
25
|
-
const content_disposition_str = headers.get(`content-disposition`);
|
|
26
|
-
if (!content_disposition_str)
|
|
27
|
-
return fallback;
|
|
28
|
-
const star_match = /filename\*=(?:UTF-8''|)([^;]+)/i.exec(content_disposition_str);
|
|
29
|
-
if (star_match?.[1]) {
|
|
30
|
-
const raw = star_match[1].trim().replace(/^"|"$/g, ``);
|
|
31
|
-
try {
|
|
32
|
-
return decodeURIComponent(raw);
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
return raw;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
const plain_match = /filename\s*=\s*"?([^";]+)"?/i.exec(content_disposition_str);
|
|
39
|
-
return plain_match?.[1]?.trim() || fallback;
|
|
40
|
-
};
|
|
41
|
-
// Check for known binary file extensions
|
|
42
|
-
const known_bin_extensions = `h5 hdf5 traj npz pkl dat gz gzip zip bz2 xz brml`.split(` `);
|
|
43
|
-
if (known_bin_extensions.includes(ext)) {
|
|
44
|
-
// Force binary mode for known binary files to handle GitHub Pages content-type issues
|
|
45
|
-
const resp = await fetch(url);
|
|
46
|
-
if (!resp.ok)
|
|
47
|
-
throw new Error(`Fetch failed: ${resp.status}`);
|
|
48
|
-
const filename = extract_filename(resp.headers);
|
|
49
|
-
// Handle gzipped files with proper content-encoding detection
|
|
50
|
-
if (ext === `gz` || ext === `gzip`) {
|
|
51
|
-
if (resp.headers.get(`content-encoding`) === `gzip`) {
|
|
52
|
-
// Browser automatically decompressed it, so it's text
|
|
53
|
-
return callback(await resp.text(), filename);
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
// Need to decompress manually
|
|
57
|
-
const { decompress_data } = await import(`./decompress`);
|
|
58
|
-
const buffer = await resp.arrayBuffer();
|
|
59
|
-
const content = await decompress_data(buffer, `gzip`);
|
|
60
|
-
// Remove .gz extension when manually decompressing
|
|
61
|
-
return callback(content, filename.replace(/\.gz$/, ``));
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
// For H5 files, always load as binary regardless of signature
|
|
65
|
-
// to handle files that have .h5/.hdf5 extensions but may not have the proper HDF5 signature
|
|
66
|
-
if ([`h5`, `hdf5`].includes(ext)) {
|
|
67
|
-
const result = await load_binary_traj(resp, `H5`, true);
|
|
68
|
-
// Log warning if signature doesn't match (only for ArrayBuffer results)
|
|
69
|
-
if (result instanceof ArrayBuffer && result.byteLength >= 8) {
|
|
70
|
-
const view = new Uint8Array(result.slice(0, 8));
|
|
71
|
-
const hdf5_signature = [0x89, 0x48, 0x44, 0x46, 0x0d, 0x0a, 0x1a, 0x0a];
|
|
72
|
-
if (!hdf5_signature.every((byte, idx) => view[idx] === byte)) {
|
|
73
|
-
console.warn(`File has .h5/.hdf5 extension but missing HDF5 signature`);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return callback(result, extract_filename(resp.headers));
|
|
77
|
-
}
|
|
78
|
-
// For .traj files, ensure we always get ArrayBuffer for proper ASE parsing
|
|
79
|
-
if (ext === `traj`) {
|
|
80
|
-
const buffer = await load_binary_traj(resp, `.traj`);
|
|
81
|
-
return callback(buffer, extract_filename(resp.headers));
|
|
82
|
-
}
|
|
83
|
-
if (resp.headers.get(`content-encoding`) === `gzip`) {
|
|
84
|
-
return callback(await resp.text(), extract_filename(resp.headers));
|
|
85
|
-
}
|
|
86
|
-
return callback(await resp.arrayBuffer(), extract_filename(resp.headers));
|
|
87
|
-
}
|
|
88
|
-
// Skip Range requests for known text formats to avoid production server issues
|
|
89
|
-
const known_text_extensions = `xyz extxyz json cif poscar yaml yml txt md py js ts css html xml`.split(` `);
|
|
90
|
-
// Include VASP files that don't have extensions (POSCAR, XDATCAR, CONTCAR)
|
|
91
|
-
const is_known_text = known_text_extensions.includes(ext) ||
|
|
92
|
-
url_basename.toLowerCase().match(/^(poscar|xdatcar|contcar)$/i);
|
|
93
|
-
if (!is_known_text) {
|
|
94
|
-
try { // Check for magic bytes only for unknown formats
|
|
95
|
-
const head = await fetch(url, { headers: { Range: `bytes=0-15` } });
|
|
96
|
-
if (head.ok) {
|
|
97
|
-
const buf = new Uint8Array(await head.arrayBuffer());
|
|
98
|
-
const is_gzip = buf[0] === 0x1f && buf[1] === 0x8b;
|
|
99
|
-
const is_hdf5 = buf[0] === 0x89 && buf[1] === 0x48 && buf[2] === 0x44 &&
|
|
100
|
-
buf[3] === 0x46;
|
|
101
|
-
if (is_gzip || is_hdf5) {
|
|
102
|
-
const resp = await fetch(url);
|
|
103
|
-
if (!resp.ok)
|
|
104
|
-
throw new Error(`Fetch failed: ${resp.status}`);
|
|
105
|
-
return callback(await resp.arrayBuffer(), extract_filename(resp.headers));
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
catch {
|
|
110
|
-
// Fall through to text fetch if HEAD request fails
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
const resp = await fetch(url);
|
|
114
|
-
if (!resp.ok)
|
|
115
|
-
throw new Error(`Fetch failed: ${resp.status}`);
|
|
116
|
-
return callback(await resp.text(), extract_filename(resp.headers));
|
|
117
|
-
}
|
|
7
|
+
export * from './url-drop';
|
package/dist/io/is-binary.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// Simplified binary detection
|
|
2
2
|
export const is_binary = (content) => content.includes(`\0`) ||
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
content.length > 0.1 ||
|
|
3
|
+
(content.match(/[\u0000-\u0008\u000E-\u001F\u007F-\u00FF]/g) || []).length / content.length >
|
|
4
|
+
0.1 ||
|
|
6
5
|
(content.match(/[\u0020-\u007E]/g) || []).length / content.length < 0.7;
|
package/dist/io/types.d.ts
CHANGED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare function handle_url_drop(drag_event: DragEvent, callback: (content: string | ArrayBuffer, filename: string) => Promise<void> | void): Promise<boolean>;
|
|
2
|
+
export declare function load_from_url(url: string, callback: (content: string | ArrayBuffer, filename: string) => Promise<void> | void): Promise<void>;
|