@walkthru-earth/objex 0.1.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/LICENSE +396 -0
- package/README.md +114 -0
- package/dist/assets/favicon.svg +17 -0
- package/dist/components/CLAUDE.md +44 -0
- package/dist/components/browser/Breadcrumb.svelte +50 -0
- package/dist/components/browser/Breadcrumb.svelte.d.ts +7 -0
- package/dist/components/browser/CreateFolderDialog.svelte +98 -0
- package/dist/components/browser/CreateFolderDialog.svelte.d.ts +6 -0
- package/dist/components/browser/DeleteConfirmDialog.svelte +90 -0
- package/dist/components/browser/DeleteConfirmDialog.svelte.d.ts +8 -0
- package/dist/components/browser/DropZone.svelte +83 -0
- package/dist/components/browser/DropZone.svelte.d.ts +7 -0
- package/dist/components/browser/FileBrowser.svelte +229 -0
- package/dist/components/browser/FileBrowser.svelte.d.ts +3 -0
- package/dist/components/browser/FileRow.svelte +112 -0
- package/dist/components/browser/FileRow.svelte.d.ts +9 -0
- package/dist/components/browser/FileTreeSidebar.svelte +559 -0
- package/dist/components/browser/FileTreeSidebar.svelte.d.ts +8 -0
- package/dist/components/browser/RenameDialog.svelte +101 -0
- package/dist/components/browser/RenameDialog.svelte.d.ts +8 -0
- package/dist/components/browser/SearchBar.svelte +40 -0
- package/dist/components/browser/SearchBar.svelte.d.ts +6 -0
- package/dist/components/browser/UploadButton.svelte +65 -0
- package/dist/components/browser/UploadButton.svelte.d.ts +3 -0
- package/dist/components/editor/CodeMirrorEditor.svelte +404 -0
- package/dist/components/editor/CodeMirrorEditor.svelte.d.ts +12 -0
- package/dist/components/editor/MilkdownEditor.svelte +98 -0
- package/dist/components/editor/MilkdownEditor.svelte.d.ts +9 -0
- package/dist/components/editor/SqlEditor.svelte +173 -0
- package/dist/components/editor/SqlEditor.svelte.d.ts +7 -0
- package/dist/components/editor/SqlResultBlock.svelte +199 -0
- package/dist/components/editor/SqlResultBlock.svelte.d.ts +9 -0
- package/dist/components/layout/ConnectionDialog.svelte +439 -0
- package/dist/components/layout/ConnectionDialog.svelte.d.ts +9 -0
- package/dist/components/layout/LocaleToggle.svelte +32 -0
- package/dist/components/layout/LocaleToggle.svelte.d.ts +3 -0
- package/dist/components/layout/SafeLockToggle.svelte +37 -0
- package/dist/components/layout/SafeLockToggle.svelte.d.ts +18 -0
- package/dist/components/layout/Sidebar.svelte +314 -0
- package/dist/components/layout/Sidebar.svelte.d.ts +3 -0
- package/dist/components/layout/StatusBar.svelte +73 -0
- package/dist/components/layout/StatusBar.svelte.d.ts +3 -0
- package/dist/components/layout/TabBar.svelte +102 -0
- package/dist/components/layout/TabBar.svelte.d.ts +7 -0
- package/dist/components/layout/ThemeToggle.svelte +52 -0
- package/dist/components/layout/ThemeToggle.svelte.d.ts +3 -0
- package/dist/components/ui/badge/badge.svelte +49 -0
- package/dist/components/ui/badge/badge.svelte.d.ts +32 -0
- package/dist/components/ui/badge/index.d.ts +1 -0
- package/dist/components/ui/badge/index.js +1 -0
- package/dist/components/ui/button/button.svelte +82 -0
- package/dist/components/ui/button/button.svelte.d.ts +64 -0
- package/dist/components/ui/button/index.d.ts +2 -0
- package/dist/components/ui/button/index.js +4 -0
- package/dist/components/ui/context-menu/context-menu-checkbox-item.svelte +40 -0
- package/dist/components/ui/context-menu/context-menu-checkbox-item.svelte.d.ts +9 -0
- package/dist/components/ui/context-menu/context-menu-content.svelte +28 -0
- package/dist/components/ui/context-menu/context-menu-content.svelte.d.ts +10 -0
- package/dist/components/ui/context-menu/context-menu-group-heading.svelte +21 -0
- package/dist/components/ui/context-menu/context-menu-group-heading.svelte.d.ts +7 -0
- package/dist/components/ui/context-menu/context-menu-group.svelte +7 -0
- package/dist/components/ui/context-menu/context-menu-group.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu-item.svelte +27 -0
- package/dist/components/ui/context-menu/context-menu-item.svelte.d.ts +8 -0
- package/dist/components/ui/context-menu/context-menu-label.svelte +24 -0
- package/dist/components/ui/context-menu/context-menu-label.svelte.d.ts +8 -0
- package/dist/components/ui/context-menu/context-menu-portal.svelte +7 -0
- package/dist/components/ui/context-menu/context-menu-portal.svelte.d.ts +3 -0
- package/dist/components/ui/context-menu/context-menu-radio-group.svelte +16 -0
- package/dist/components/ui/context-menu/context-menu-radio-group.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu-radio-item.svelte +33 -0
- package/dist/components/ui/context-menu/context-menu-radio-item.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu-separator.svelte +17 -0
- package/dist/components/ui/context-menu/context-menu-separator.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu-shortcut.svelte +20 -0
- package/dist/components/ui/context-menu/context-menu-shortcut.svelte.d.ts +5 -0
- package/dist/components/ui/context-menu/context-menu-sub-content.svelte +20 -0
- package/dist/components/ui/context-menu/context-menu-sub-content.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu-sub-trigger.svelte +29 -0
- package/dist/components/ui/context-menu/context-menu-sub-trigger.svelte.d.ts +8 -0
- package/dist/components/ui/context-menu/context-menu-sub.svelte +7 -0
- package/dist/components/ui/context-menu/context-menu-sub.svelte.d.ts +3 -0
- package/dist/components/ui/context-menu/context-menu-trigger.svelte +7 -0
- package/dist/components/ui/context-menu/context-menu-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/context-menu/context-menu.svelte +7 -0
- package/dist/components/ui/context-menu/context-menu.svelte.d.ts +3 -0
- package/dist/components/ui/context-menu/index.d.ts +17 -0
- package/dist/components/ui/context-menu/index.js +19 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +43 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +9 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +29 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte.d.ts +10 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte.d.ts +8 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +27 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +8 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +24 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte.d.ts +8 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-portal.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-portal.svelte.d.ts +3 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +33 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +17 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +20 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte.d.ts +5 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +20 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte.d.ts +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub.svelte.d.ts +3 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu.svelte.d.ts +3 -0
- package/dist/components/ui/dropdown-menu/index.d.ts +18 -0
- package/dist/components/ui/dropdown-menu/index.js +18 -0
- package/dist/components/ui/input/index.d.ts +2 -0
- package/dist/components/ui/input/index.js +4 -0
- package/dist/components/ui/input/input.svelte +52 -0
- package/dist/components/ui/input/input.svelte.d.ts +13 -0
- package/dist/components/ui/resizable/index.d.ts +4 -0
- package/dist/components/ui/resizable/index.js +6 -0
- package/dist/components/ui/resizable/resizable-handle.svelte +30 -0
- package/dist/components/ui/resizable/resizable-handle.svelte.d.ts +8 -0
- package/dist/components/ui/resizable/resizable-pane-group.svelte +20 -0
- package/dist/components/ui/resizable/resizable-pane-group.svelte.d.ts +7 -0
- package/dist/components/ui/scroll-area/index.d.ts +3 -0
- package/dist/components/ui/scroll-area/index.js +5 -0
- package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte +31 -0
- package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte.d.ts +4 -0
- package/dist/components/ui/scroll-area/scroll-area.svelte +47 -0
- package/dist/components/ui/scroll-area/scroll-area.svelte.d.ts +11 -0
- package/dist/components/ui/separator/index.d.ts +2 -0
- package/dist/components/ui/separator/index.js +4 -0
- package/dist/components/ui/separator/separator.svelte +21 -0
- package/dist/components/ui/separator/separator.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/index.d.ts +11 -0
- package/dist/components/ui/sheet/index.js +13 -0
- package/dist/components/ui/sheet/sheet-close.svelte +7 -0
- package/dist/components/ui/sheet/sheet-close.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-content.svelte +62 -0
- package/dist/components/ui/sheet/sheet-content.svelte.d.ts +37 -0
- package/dist/components/ui/sheet/sheet-description.svelte +17 -0
- package/dist/components/ui/sheet/sheet-description.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-footer.svelte +20 -0
- package/dist/components/ui/sheet/sheet-footer.svelte.d.ts +5 -0
- package/dist/components/ui/sheet/sheet-header.svelte +20 -0
- package/dist/components/ui/sheet/sheet-header.svelte.d.ts +5 -0
- package/dist/components/ui/sheet/sheet-overlay.svelte +20 -0
- package/dist/components/ui/sheet/sheet-overlay.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-portal.svelte +7 -0
- package/dist/components/ui/sheet/sheet-portal.svelte.d.ts +3 -0
- package/dist/components/ui/sheet/sheet-title.svelte +13 -0
- package/dist/components/ui/sheet/sheet-title.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet-trigger.svelte +7 -0
- package/dist/components/ui/sheet/sheet-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/sheet/sheet.svelte +7 -0
- package/dist/components/ui/sheet/sheet.svelte.d.ts +3 -0
- package/dist/components/ui/switch/index.d.ts +2 -0
- package/dist/components/ui/switch/index.js +4 -0
- package/dist/components/ui/switch/switch.svelte +28 -0
- package/dist/components/ui/switch/switch.svelte.d.ts +8 -0
- package/dist/components/ui/tabs/index.d.ts +5 -0
- package/dist/components/ui/tabs/index.js +7 -0
- package/dist/components/ui/tabs/tabs-content.svelte +17 -0
- package/dist/components/ui/tabs/tabs-content.svelte.d.ts +4 -0
- package/dist/components/ui/tabs/tabs-list.svelte +16 -0
- package/dist/components/ui/tabs/tabs-list.svelte.d.ts +4 -0
- package/dist/components/ui/tabs/tabs-trigger.svelte +20 -0
- package/dist/components/ui/tabs/tabs-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/tabs/tabs.svelte +19 -0
- package/dist/components/ui/tabs/tabs.svelte.d.ts +4 -0
- package/dist/components/ui/tooltip/index.d.ts +6 -0
- package/dist/components/ui/tooltip/index.js +8 -0
- package/dist/components/ui/tooltip/tooltip-content.svelte +52 -0
- package/dist/components/ui/tooltip/tooltip-content.svelte.d.ts +11 -0
- package/dist/components/ui/tooltip/tooltip-portal.svelte +7 -0
- package/dist/components/ui/tooltip/tooltip-portal.svelte.d.ts +4 -0
- package/dist/components/ui/tooltip/tooltip-provider.svelte +7 -0
- package/dist/components/ui/tooltip/tooltip-provider.svelte.d.ts +4 -0
- package/dist/components/ui/tooltip/tooltip-trigger.svelte +7 -0
- package/dist/components/ui/tooltip/tooltip-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/tooltip/tooltip.svelte +7 -0
- package/dist/components/ui/tooltip/tooltip.svelte.d.ts +4 -0
- package/dist/components/viewers/ArchiveViewer.svelte +586 -0
- package/dist/components/viewers/ArchiveViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/CLAUDE.md +60 -0
- package/dist/components/viewers/CodeViewer.svelte +553 -0
- package/dist/components/viewers/CodeViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/CogViewer.svelte +1345 -0
- package/dist/components/viewers/CogViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/CopcViewer.svelte +25 -0
- package/dist/components/viewers/CopcViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/DatabaseViewer.svelte +169 -0
- package/dist/components/viewers/DatabaseViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/FileInfo.svelte +174 -0
- package/dist/components/viewers/FileInfo.svelte.d.ts +10 -0
- package/dist/components/viewers/FlatGeobufViewer.svelte +755 -0
- package/dist/components/viewers/FlatGeobufViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/GeoParquetMapViewer.svelte +278 -0
- package/dist/components/viewers/GeoParquetMapViewer.svelte.d.ts +17 -0
- package/dist/components/viewers/ImageViewer.svelte +233 -0
- package/dist/components/viewers/ImageViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/LoadProgress.svelte +93 -0
- package/dist/components/viewers/LoadProgress.svelte.d.ts +15 -0
- package/dist/components/viewers/MapViewer.svelte +234 -0
- package/dist/components/viewers/MapViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/MarkdownViewer.svelte +478 -0
- package/dist/components/viewers/MarkdownViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/MediaViewer.svelte +121 -0
- package/dist/components/viewers/MediaViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/ModelViewer.svelte +164 -0
- package/dist/components/viewers/ModelViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/NotebookViewer.svelte +389 -0
- package/dist/components/viewers/NotebookViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/PdfViewer.svelte +278 -0
- package/dist/components/viewers/PdfViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/PmtilesViewer.svelte +191 -0
- package/dist/components/viewers/PmtilesViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/QueryHistoryPanel.svelte +159 -0
- package/dist/components/viewers/QueryHistoryPanel.svelte.d.ts +8 -0
- package/dist/components/viewers/RawViewer.svelte +117 -0
- package/dist/components/viewers/RawViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/StacMapViewer.svelte +20 -0
- package/dist/components/viewers/StacMapViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/StyleEditorOverlay.svelte +27 -0
- package/dist/components/viewers/StyleEditorOverlay.svelte.d.ts +7 -0
- package/dist/components/viewers/TableGrid.svelte +355 -0
- package/dist/components/viewers/TableGrid.svelte.d.ts +12 -0
- package/dist/components/viewers/TableStatusBar.svelte +92 -0
- package/dist/components/viewers/TableStatusBar.svelte.d.ts +11 -0
- package/dist/components/viewers/TableToolbar.svelte +382 -0
- package/dist/components/viewers/TableToolbar.svelte.d.ts +25 -0
- package/dist/components/viewers/TableViewer.svelte +923 -0
- package/dist/components/viewers/TableViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/ViewerRouter.svelte +70 -0
- package/dist/components/viewers/ViewerRouter.svelte.d.ts +7 -0
- package/dist/components/viewers/ZarrMapViewer.svelte +288 -0
- package/dist/components/viewers/ZarrMapViewer.svelte.d.ts +17 -0
- package/dist/components/viewers/ZarrViewer.svelte +256 -0
- package/dist/components/viewers/ZarrViewer.svelte.d.ts +7 -0
- package/dist/components/viewers/map/AttributeTable.svelte +52 -0
- package/dist/components/viewers/map/AttributeTable.svelte.d.ts +8 -0
- package/dist/components/viewers/map/MapContainer.svelte +158 -0
- package/dist/components/viewers/map/MapContainer.svelte.d.ts +12 -0
- package/dist/components/viewers/pmtiles/PmtilesArchiveView.svelte +389 -0
- package/dist/components/viewers/pmtiles/PmtilesArchiveView.svelte.d.ts +10 -0
- package/dist/components/viewers/pmtiles/PmtilesMapView.svelte +332 -0
- package/dist/components/viewers/pmtiles/PmtilesMapView.svelte.d.ts +11 -0
- package/dist/components/viewers/pmtiles/PmtilesTileInspector.svelte +373 -0
- package/dist/components/viewers/pmtiles/PmtilesTileInspector.svelte.d.ts +12 -0
- package/dist/components/viewers/pmtiles/SvgTileRenderer.svelte +112 -0
- package/dist/components/viewers/pmtiles/SvgTileRenderer.svelte.d.ts +10 -0
- package/dist/file-icons/CLAUDE.md +21 -0
- package/dist/file-icons/FileTypeIcon.svelte +74 -0
- package/dist/file-icons/FileTypeIcon.svelte.d.ts +9 -0
- package/dist/file-icons/index.d.ts +56 -0
- package/dist/file-icons/index.js +1070 -0
- package/dist/i18n/CLAUDE.md +19 -0
- package/dist/i18n/ar.d.ts +1 -0
- package/dist/i18n/ar.js +404 -0
- package/dist/i18n/en.d.ts +1 -0
- package/dist/i18n/en.js +404 -0
- package/dist/i18n/index.svelte.d.ts +9 -0
- package/dist/i18n/index.svelte.js +27 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +13 -0
- package/dist/query/CLAUDE.md +22 -0
- package/dist/query/engine.d.ts +56 -0
- package/dist/query/engine.js +6 -0
- package/dist/query/index.d.ts +4 -0
- package/dist/query/index.js +19 -0
- package/dist/query/wasm.d.ts +20 -0
- package/dist/query/wasm.js +890 -0
- package/dist/storage/CLAUDE.md +23 -0
- package/dist/storage/adapter.d.ts +21 -0
- package/dist/storage/adapter.js +1 -0
- package/dist/storage/browser-azure.d.ts +25 -0
- package/dist/storage/browser-azure.js +271 -0
- package/dist/storage/browser-cloud.d.ts +32 -0
- package/dist/storage/browser-cloud.js +293 -0
- package/dist/storage/index.d.ts +11 -0
- package/dist/storage/index.js +37 -0
- package/dist/storage/url-adapter.d.ts +19 -0
- package/dist/storage/url-adapter.js +51 -0
- package/dist/stores/CLAUDE.md +29 -0
- package/dist/stores/browser.svelte.d.ts +28 -0
- package/dist/stores/browser.svelte.js +160 -0
- package/dist/stores/connections.svelte.d.ts +56 -0
- package/dist/stores/connections.svelte.js +272 -0
- package/dist/stores/credentials.svelte.d.ts +56 -0
- package/dist/stores/credentials.svelte.js +79 -0
- package/dist/stores/files.svelte.d.ts +20 -0
- package/dist/stores/files.svelte.js +76 -0
- package/dist/stores/query-history.svelte.d.ts +16 -0
- package/dist/stores/query-history.svelte.js +57 -0
- package/dist/stores/safelock.svelte.d.ts +8 -0
- package/dist/stores/safelock.svelte.js +52 -0
- package/dist/stores/settings.svelte.d.ts +11 -0
- package/dist/stores/settings.svelte.js +101 -0
- package/dist/stores/tab-resources.svelte.d.ts +25 -0
- package/dist/stores/tab-resources.svelte.js +61 -0
- package/dist/stores/tabs.svelte.d.ts +17 -0
- package/dist/stores/tabs.svelte.js +110 -0
- package/dist/types/notebookjs.d.ts +14 -0
- package/dist/types.d.ts +47 -0
- package/dist/types.js +1 -0
- package/dist/utils/CLAUDE.md +54 -0
- package/dist/utils/analytics.d.ts +10 -0
- package/dist/utils/analytics.js +38 -0
- package/dist/utils/archive.d.ts +70 -0
- package/dist/utils/archive.js +333 -0
- package/dist/utils/column-types.d.ts +5 -0
- package/dist/utils/column-types.js +137 -0
- package/dist/utils/deck.d.ts +98 -0
- package/dist/utils/deck.js +208 -0
- package/dist/utils/evidence-context.d.ts +22 -0
- package/dist/utils/evidence-context.js +56 -0
- package/dist/utils/export.d.ts +2 -0
- package/dist/utils/export.js +51 -0
- package/dist/utils/format.d.ts +14 -0
- package/dist/utils/format.js +56 -0
- package/dist/utils/geoarrow.d.ts +32 -0
- package/dist/utils/geoarrow.js +672 -0
- package/dist/utils/hex.d.ts +10 -0
- package/dist/utils/hex.js +27 -0
- package/dist/utils/host-detection.d.ts +23 -0
- package/dist/utils/host-detection.js +289 -0
- package/dist/utils/map-selection.d.ts +12 -0
- package/dist/utils/map-selection.js +45 -0
- package/dist/utils/markdown-sql.d.ts +30 -0
- package/dist/utils/markdown-sql.js +73 -0
- package/dist/utils/markdown.d.ts +18 -0
- package/dist/utils/markdown.js +146 -0
- package/dist/utils/model3d.d.ts +13 -0
- package/dist/utils/model3d.js +62 -0
- package/dist/utils/parquet-metadata.d.ts +58 -0
- package/dist/utils/parquet-metadata.js +228 -0
- package/dist/utils/pdf.d.ts +8 -0
- package/dist/utils/pdf.js +28 -0
- package/dist/utils/pmtiles-tile.d.ts +38 -0
- package/dist/utils/pmtiles-tile.js +64 -0
- package/dist/utils/pmtiles.d.ts +46 -0
- package/dist/utils/pmtiles.js +135 -0
- package/dist/utils/shiki.d.ts +8 -0
- package/dist/utils/shiki.js +98 -0
- package/dist/utils/storage-url.d.ts +64 -0
- package/dist/utils/storage-url.js +374 -0
- package/dist/utils/url-state.d.ts +40 -0
- package/dist/utils/url-state.js +113 -0
- package/dist/utils/url.d.ts +27 -0
- package/dist/utils/url.js +115 -0
- package/dist/utils/wkb.d.ts +43 -0
- package/dist/utils/wkb.js +345 -0
- package/dist/utils/zarr.d.ts +39 -0
- package/dist/utils/zarr.js +204 -0
- package/dist/utils.d.ts +12 -0
- package/dist/utils.js +5 -0
- package/package.json +203 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface HexRow {
|
|
2
|
+
offset: string;
|
|
3
|
+
hex: string[];
|
|
4
|
+
ascii: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Generates a hex dump from binary data.
|
|
8
|
+
* Returns rows of offset | hex bytes | ASCII representation.
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateHexDump(data: Uint8Array, bytesPerRow?: number): HexRow[];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates a hex dump from binary data.
|
|
3
|
+
* Returns rows of offset | hex bytes | ASCII representation.
|
|
4
|
+
*/
|
|
5
|
+
export function generateHexDump(data, bytesPerRow = 16) {
|
|
6
|
+
const rows = [];
|
|
7
|
+
for (let i = 0; i < data.length; i += bytesPerRow) {
|
|
8
|
+
const slice = data.slice(i, i + bytesPerRow);
|
|
9
|
+
const offset = i.toString(16).padStart(8, '0');
|
|
10
|
+
const hex = [];
|
|
11
|
+
for (let j = 0; j < bytesPerRow; j++) {
|
|
12
|
+
if (j < slice.length) {
|
|
13
|
+
hex.push(slice[j].toString(16).padStart(2, '0'));
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
hex.push(' ');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
let ascii = '';
|
|
20
|
+
for (let j = 0; j < slice.length; j++) {
|
|
21
|
+
const byte = slice[j];
|
|
22
|
+
ascii += byte >= 0x20 && byte <= 0x7e ? String.fromCharCode(byte) : '.';
|
|
23
|
+
}
|
|
24
|
+
rows.push({ offset, hex, ascii });
|
|
25
|
+
}
|
|
26
|
+
return rows;
|
|
27
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-detect hosting bucket from URL search params and window.location.
|
|
3
|
+
*
|
|
4
|
+
* Detection priority:
|
|
5
|
+
* 1. `?url=<storage-url>` query parameter (highest priority)
|
|
6
|
+
* 2. `window.location.hostname` pattern matching (fallback)
|
|
7
|
+
*
|
|
8
|
+
* Also extracts `rootPrefix` when the app is hosted inside a subfolder.
|
|
9
|
+
*/
|
|
10
|
+
import type { StorageProvider } from './storage-url.js';
|
|
11
|
+
export interface DetectedHost {
|
|
12
|
+
provider: StorageProvider;
|
|
13
|
+
bucket: string;
|
|
14
|
+
region: string;
|
|
15
|
+
endpoint: string;
|
|
16
|
+
rootPrefix: string;
|
|
17
|
+
bucketUrl: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Detect hosting bucket from current URL.
|
|
21
|
+
* Returns null when no hosting bucket can be determined.
|
|
22
|
+
*/
|
|
23
|
+
export declare function detectHostBucket(): DetectedHost | null;
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-detect hosting bucket from URL search params and window.location.
|
|
3
|
+
*
|
|
4
|
+
* Detection priority:
|
|
5
|
+
* 1. `?url=<storage-url>` query parameter (highest priority)
|
|
6
|
+
* 2. `window.location.hostname` pattern matching (fallback)
|
|
7
|
+
*
|
|
8
|
+
* Also extracts `rootPrefix` when the app is hosted inside a subfolder.
|
|
9
|
+
*/
|
|
10
|
+
import { parseStorageUrl } from './storage-url.js';
|
|
11
|
+
/**
|
|
12
|
+
* Extract root prefix from pathname.
|
|
13
|
+
* When hosted at `/subfolder/index.html` or `/subfolder/`, returns `subfolder/`.
|
|
14
|
+
*/
|
|
15
|
+
function extractRootPrefix(pathname) {
|
|
16
|
+
// Strip trailing filename (index.html, etc.)
|
|
17
|
+
let clean = pathname.replace(/\/[^/]*\.[^/]*$/, '/');
|
|
18
|
+
// Remove leading slash
|
|
19
|
+
clean = clean.replace(/^\//, '');
|
|
20
|
+
// Empty or just '/' means no prefix
|
|
21
|
+
if (!clean || clean === '/')
|
|
22
|
+
return '';
|
|
23
|
+
// Ensure trailing slash
|
|
24
|
+
if (!clean.endsWith('/'))
|
|
25
|
+
clean += '/';
|
|
26
|
+
return clean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build a normalized API endpoint URL for a detected provider.
|
|
30
|
+
*/
|
|
31
|
+
function buildBucketUrl(provider, endpoint, bucket) {
|
|
32
|
+
if (endpoint) {
|
|
33
|
+
return `${endpoint.replace(/\/$/, '')}/${bucket}`;
|
|
34
|
+
}
|
|
35
|
+
switch (provider) {
|
|
36
|
+
case 'gcs':
|
|
37
|
+
return `https://storage.googleapis.com/${bucket}`;
|
|
38
|
+
case 'azure':
|
|
39
|
+
return `${endpoint}/${bucket}`;
|
|
40
|
+
case 'storj':
|
|
41
|
+
return `https://gateway.storjshare.io/${bucket}`;
|
|
42
|
+
default:
|
|
43
|
+
return `https://s3.us-east-1.amazonaws.com/${bucket}`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Detect hosting bucket from current URL.
|
|
48
|
+
* Returns null when no hosting bucket can be determined.
|
|
49
|
+
*/
|
|
50
|
+
export function detectHostBucket() {
|
|
51
|
+
if (typeof window === 'undefined')
|
|
52
|
+
return null;
|
|
53
|
+
const url = new URL(window.location.href);
|
|
54
|
+
const host = url.hostname;
|
|
55
|
+
// --- Priority 1: ?url= query parameter ---
|
|
56
|
+
const urlParam = url.searchParams.get('url');
|
|
57
|
+
if (urlParam) {
|
|
58
|
+
const parsed = parseStorageUrl(urlParam);
|
|
59
|
+
if (parsed.bucket) {
|
|
60
|
+
return {
|
|
61
|
+
provider: parsed.provider === 'unknown' ? 's3' : parsed.provider,
|
|
62
|
+
bucket: parsed.bucket,
|
|
63
|
+
region: parsed.region,
|
|
64
|
+
endpoint: parsed.endpoint,
|
|
65
|
+
rootPrefix: '',
|
|
66
|
+
bucketUrl: buildBucketUrl(parsed.provider, parsed.endpoint, parsed.bucket)
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// --- Priority 2: Hostname pattern matching ---
|
|
71
|
+
const pathname = url.pathname;
|
|
72
|
+
// AWS S3 virtual-hosted: <bucket>.s3.<region>.amazonaws.com
|
|
73
|
+
const awsVhost = host.match(/^(.+)\.s3[.-]([a-z0-9-]+)\.amazonaws\.com$/);
|
|
74
|
+
if (awsVhost) {
|
|
75
|
+
return {
|
|
76
|
+
provider: 's3',
|
|
77
|
+
bucket: awsVhost[1],
|
|
78
|
+
region: awsVhost[2],
|
|
79
|
+
endpoint: '',
|
|
80
|
+
rootPrefix: extractRootPrefix(pathname),
|
|
81
|
+
bucketUrl: `https://s3.${awsVhost[2]}.amazonaws.com/${awsVhost[1]}`
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// AWS S3 website hosting: <bucket>.s3-website-<region>.amazonaws.com or <bucket>.s3-website.<region>.amazonaws.com
|
|
85
|
+
const awsWebsite = host.match(/^(.+)\.s3-website[.-]([a-z0-9-]+)\.amazonaws\.com$/);
|
|
86
|
+
if (awsWebsite) {
|
|
87
|
+
return {
|
|
88
|
+
provider: 's3',
|
|
89
|
+
bucket: awsWebsite[1],
|
|
90
|
+
region: awsWebsite[2],
|
|
91
|
+
endpoint: '',
|
|
92
|
+
rootPrefix: extractRootPrefix(pathname),
|
|
93
|
+
bucketUrl: `https://s3.${awsWebsite[2]}.amazonaws.com/${awsWebsite[1]}`
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
// AWS S3 path-style: s3.<region>.amazonaws.com/<bucket>
|
|
97
|
+
const awsPath = host.match(/^s3[.-]([a-z0-9-]+)\.amazonaws\.com$/);
|
|
98
|
+
if (awsPath) {
|
|
99
|
+
const parts = pathname.replace(/^\//, '').split('/').filter(Boolean);
|
|
100
|
+
if (parts.length > 0) {
|
|
101
|
+
return {
|
|
102
|
+
provider: 's3',
|
|
103
|
+
bucket: parts[0],
|
|
104
|
+
region: awsPath[1],
|
|
105
|
+
endpoint: '',
|
|
106
|
+
rootPrefix: parts.length > 1 ? extractRootPrefix(`/${parts.slice(1).join('/')}`) : '',
|
|
107
|
+
bucketUrl: `https://s3.${awsPath[1]}.amazonaws.com/${parts[0]}`
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// GCS: storage.googleapis.com/<bucket>
|
|
112
|
+
if (host === 'storage.googleapis.com') {
|
|
113
|
+
const parts = pathname.replace(/^\//, '').split('/').filter(Boolean);
|
|
114
|
+
if (parts.length > 0) {
|
|
115
|
+
return {
|
|
116
|
+
provider: 'gcs',
|
|
117
|
+
bucket: parts[0],
|
|
118
|
+
region: 'us',
|
|
119
|
+
endpoint: '',
|
|
120
|
+
rootPrefix: parts.length > 1 ? extractRootPrefix(`/${parts.slice(1).join('/')}`) : '',
|
|
121
|
+
bucketUrl: `https://storage.googleapis.com/${parts[0]}`
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// GCS virtual-hosted: <bucket>.storage.googleapis.com
|
|
126
|
+
const gcsVhost = host.match(/^(.+)\.storage\.googleapis\.com$/);
|
|
127
|
+
if (gcsVhost) {
|
|
128
|
+
return {
|
|
129
|
+
provider: 'gcs',
|
|
130
|
+
bucket: gcsVhost[1],
|
|
131
|
+
region: 'us',
|
|
132
|
+
endpoint: '',
|
|
133
|
+
rootPrefix: extractRootPrefix(pathname),
|
|
134
|
+
bucketUrl: `https://storage.googleapis.com/${gcsVhost[1]}`
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
// Azure Static Website: <account>.z<N>.web.core.windows.net
|
|
138
|
+
const azureWeb = host.match(/^([a-z0-9]+)\.z\d+\.web\.core\.windows\.net$/);
|
|
139
|
+
if (azureWeb) {
|
|
140
|
+
return {
|
|
141
|
+
provider: 'azure',
|
|
142
|
+
bucket: '$web',
|
|
143
|
+
region: '',
|
|
144
|
+
endpoint: `https://${azureWeb[1]}.blob.core.windows.net`,
|
|
145
|
+
rootPrefix: extractRootPrefix(pathname),
|
|
146
|
+
bucketUrl: `https://${azureWeb[1]}.blob.core.windows.net/$web`
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
// Azure Blob: <account>.blob.core.windows.net/<container>
|
|
150
|
+
const azureBlob = host.match(/^([a-z0-9]+)\.blob\.core\.windows\.net$/);
|
|
151
|
+
if (azureBlob) {
|
|
152
|
+
const parts = pathname.replace(/^\//, '').split('/').filter(Boolean);
|
|
153
|
+
if (parts.length > 0) {
|
|
154
|
+
return {
|
|
155
|
+
provider: 'azure',
|
|
156
|
+
bucket: parts[0],
|
|
157
|
+
region: '',
|
|
158
|
+
endpoint: `https://${host}`,
|
|
159
|
+
rootPrefix: parts.length > 1 ? extractRootPrefix(`/${parts.slice(1).join('/')}`) : '',
|
|
160
|
+
bucketUrl: `https://${host}/${parts[0]}`
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// R2 public: pub-<id>.r2.dev
|
|
165
|
+
const r2Public = host.match(/^(pub-[a-z0-9]+)\.r2\.dev$/);
|
|
166
|
+
if (r2Public) {
|
|
167
|
+
const parts = pathname.replace(/^\//, '').split('/').filter(Boolean);
|
|
168
|
+
return {
|
|
169
|
+
provider: 'r2',
|
|
170
|
+
bucket: parts[0] || r2Public[1],
|
|
171
|
+
region: 'auto',
|
|
172
|
+
endpoint: `https://${host}`,
|
|
173
|
+
rootPrefix: parts.length > 1 ? extractRootPrefix(`/${parts.slice(1).join('/')}`) : '',
|
|
174
|
+
bucketUrl: `https://${host}`
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
// DigitalOcean Spaces: <bucket>.<region>.digitaloceanspaces.com
|
|
178
|
+
const doSpaces = host.match(/^(.+)\.([a-z0-9-]+)\.digitaloceanspaces\.com$/);
|
|
179
|
+
if (doSpaces) {
|
|
180
|
+
return {
|
|
181
|
+
provider: 's3',
|
|
182
|
+
bucket: doSpaces[1],
|
|
183
|
+
region: doSpaces[2],
|
|
184
|
+
endpoint: `https://${doSpaces[2]}.digitaloceanspaces.com`,
|
|
185
|
+
rootPrefix: extractRootPrefix(pathname),
|
|
186
|
+
bucketUrl: `https://${doSpaces[2]}.digitaloceanspaces.com/${doSpaces[1]}`
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
// DigitalOcean Spaces CDN: <bucket>.<region>.cdn.digitaloceanspaces.com
|
|
190
|
+
const doCdn = host.match(/^(.+)\.([a-z0-9-]+)\.cdn\.digitaloceanspaces\.com$/);
|
|
191
|
+
if (doCdn) {
|
|
192
|
+
return {
|
|
193
|
+
provider: 's3',
|
|
194
|
+
bucket: doCdn[1],
|
|
195
|
+
region: doCdn[2],
|
|
196
|
+
endpoint: `https://${doCdn[2]}.digitaloceanspaces.com`,
|
|
197
|
+
rootPrefix: extractRootPrefix(pathname),
|
|
198
|
+
bucketUrl: `https://${doCdn[2]}.digitaloceanspaces.com/${doCdn[1]}`
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
// Wasabi: s3.<region>.wasabisys.com/<bucket>
|
|
202
|
+
const wasabi = host.match(/^s3\.([a-z0-9-]+)\.wasabisys\.com$/);
|
|
203
|
+
if (wasabi) {
|
|
204
|
+
const parts = pathname.replace(/^\//, '').split('/').filter(Boolean);
|
|
205
|
+
if (parts.length > 0) {
|
|
206
|
+
return {
|
|
207
|
+
provider: 's3',
|
|
208
|
+
bucket: parts[0],
|
|
209
|
+
region: wasabi[1],
|
|
210
|
+
endpoint: `https://${host}`,
|
|
211
|
+
rootPrefix: parts.length > 1 ? extractRootPrefix(`/${parts.slice(1).join('/')}`) : '',
|
|
212
|
+
bucketUrl: `https://${host}/${parts[0]}`
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// B2 S3: <bucket>.s3.<region>.backblazeb2.com
|
|
217
|
+
const b2s3 = host.match(/^(.+)\.s3\.([a-z0-9-]+)\.backblazeb2\.com$/);
|
|
218
|
+
if (b2s3) {
|
|
219
|
+
return {
|
|
220
|
+
provider: 's3',
|
|
221
|
+
bucket: b2s3[1],
|
|
222
|
+
region: b2s3[2],
|
|
223
|
+
endpoint: `https://s3.${b2s3[2]}.backblazeb2.com`,
|
|
224
|
+
rootPrefix: extractRootPrefix(pathname),
|
|
225
|
+
bucketUrl: `https://s3.${b2s3[2]}.backblazeb2.com/${b2s3[1]}`
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
// IBM COS: <bucket>.s3-web.<region>.cloud-object-storage.appdomain.cloud
|
|
229
|
+
const ibmCos = host.match(/^(.+)\.s3-web\.([a-z0-9-]+)\.cloud-object-storage\.appdomain\.cloud$/);
|
|
230
|
+
if (ibmCos) {
|
|
231
|
+
return {
|
|
232
|
+
provider: 's3',
|
|
233
|
+
bucket: ibmCos[1],
|
|
234
|
+
region: ibmCos[2],
|
|
235
|
+
endpoint: `https://s3.${ibmCos[2]}.cloud-object-storage.appdomain.cloud`,
|
|
236
|
+
rootPrefix: extractRootPrefix(pathname),
|
|
237
|
+
bucketUrl: `https://s3.${ibmCos[2]}.cloud-object-storage.appdomain.cloud/${ibmCos[1]}`
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
// Storj S3 gateway: gateway.storjshare.io/<bucket> (or gateway.<region>.storjshare.io)
|
|
241
|
+
const storjGateway = host.match(/^gateway\.(?:([a-z0-9]+)\.)?storjshare\.io$/);
|
|
242
|
+
if (storjGateway) {
|
|
243
|
+
const parts = pathname.replace(/^\//, '').split('/').filter(Boolean);
|
|
244
|
+
if (parts.length > 0) {
|
|
245
|
+
return {
|
|
246
|
+
provider: 'storj',
|
|
247
|
+
bucket: parts[0],
|
|
248
|
+
region: storjGateway[1] || 'us1',
|
|
249
|
+
endpoint: `${url.protocol}//${url.host}`,
|
|
250
|
+
rootPrefix: parts.length > 1 ? extractRootPrefix(`/${parts.slice(1).join('/')}`) : '',
|
|
251
|
+
bucketUrl: `${url.protocol}//${url.host}/${parts[0]}`
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// Storj linksharing: link.storjshare.io/raw/<access>/<bucket>/...
|
|
256
|
+
const storjLink = host.match(/^link\.(?:([a-z0-9]+)\.)?storjshare\.io$/);
|
|
257
|
+
if (storjLink) {
|
|
258
|
+
const parts = pathname.replace(/^\//, '').split('/').filter(Boolean);
|
|
259
|
+
if (parts.length >= 3 && (parts[0] === 'raw' || parts[0] === 's')) {
|
|
260
|
+
return {
|
|
261
|
+
provider: 'storj',
|
|
262
|
+
bucket: parts[2],
|
|
263
|
+
region: storjLink[1] || 'us1',
|
|
264
|
+
endpoint: `${url.protocol}//${url.host}/${parts[0]}/${parts[1]}`,
|
|
265
|
+
rootPrefix: parts.length > 3 ? extractRootPrefix(`/${parts.slice(3).join('/')}`) : '',
|
|
266
|
+
bucketUrl: `${url.protocol}//${url.host}/${parts[0]}/${parts[1]}/${parts[2]}`
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// MinIO / localhost / private IPs
|
|
271
|
+
const isLocal = host === 'localhost' ||
|
|
272
|
+
host === '127.0.0.1' ||
|
|
273
|
+
host.startsWith('192.168.') ||
|
|
274
|
+
host.startsWith('10.');
|
|
275
|
+
if (isLocal) {
|
|
276
|
+
const parts = pathname.replace(/^\//, '').split('/').filter(Boolean);
|
|
277
|
+
if (parts.length > 0) {
|
|
278
|
+
return {
|
|
279
|
+
provider: 'minio',
|
|
280
|
+
bucket: parts[0],
|
|
281
|
+
region: 'us-east-1',
|
|
282
|
+
endpoint: `${url.protocol}//${url.host}`,
|
|
283
|
+
rootPrefix: parts.length > 1 ? extractRootPrefix(`/${parts.slice(1).join('/')}`) : '',
|
|
284
|
+
bucketUrl: `${url.protocol}//${url.host}/${parts[0]}`
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared selection highlight for all map viewers.
|
|
3
|
+
*
|
|
4
|
+
* Adds a MapLibre GeoJSON source + yellow outline layers that render
|
|
5
|
+
* on top of any data layer (deck.gl or native MapLibre).
|
|
6
|
+
* Works because every viewer uses MapLibre as its base map.
|
|
7
|
+
*/
|
|
8
|
+
import type maplibregl from 'maplibre-gl';
|
|
9
|
+
/** Add an empty GeoJSON source + outline layers to the map. Call once in onMapReady. */
|
|
10
|
+
export declare function setupSelectionLayer(map: maplibregl.Map): void;
|
|
11
|
+
/** Set or clear the selected feature. Pass null to clear. */
|
|
12
|
+
export declare function updateSelection(map: maplibregl.Map, feature: GeoJSON.Feature | null): void;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const SOURCE_ID = 'selection-highlight';
|
|
2
|
+
const SELECTION_COLOR = '#ffc800'; // QGIS-style yellow
|
|
3
|
+
/** Add an empty GeoJSON source + outline layers to the map. Call once in onMapReady. */
|
|
4
|
+
export function setupSelectionLayer(map) {
|
|
5
|
+
if (map.getSource(SOURCE_ID))
|
|
6
|
+
return; // idempotent
|
|
7
|
+
map.addSource(SOURCE_ID, {
|
|
8
|
+
type: 'geojson',
|
|
9
|
+
data: { type: 'FeatureCollection', features: [] }
|
|
10
|
+
});
|
|
11
|
+
// Polygon / line outline
|
|
12
|
+
map.addLayer({
|
|
13
|
+
id: 'selection-outline',
|
|
14
|
+
type: 'line',
|
|
15
|
+
source: SOURCE_ID,
|
|
16
|
+
paint: {
|
|
17
|
+
'line-color': SELECTION_COLOR,
|
|
18
|
+
'line-width': 3,
|
|
19
|
+
'line-opacity': 1
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
// Point halo
|
|
23
|
+
map.addLayer({
|
|
24
|
+
id: 'selection-point',
|
|
25
|
+
type: 'circle',
|
|
26
|
+
source: SOURCE_ID,
|
|
27
|
+
filter: ['==', '$type', 'Point'],
|
|
28
|
+
paint: {
|
|
29
|
+
'circle-radius': 10,
|
|
30
|
+
'circle-color': 'transparent',
|
|
31
|
+
'circle-stroke-color': SELECTION_COLOR,
|
|
32
|
+
'circle-stroke-width': 3
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/** Set or clear the selected feature. Pass null to clear. */
|
|
37
|
+
export function updateSelection(map, feature) {
|
|
38
|
+
const source = map.getSource(SOURCE_ID);
|
|
39
|
+
if (!source)
|
|
40
|
+
return;
|
|
41
|
+
source.setData({
|
|
42
|
+
type: 'FeatureCollection',
|
|
43
|
+
features: feature ? [feature] : []
|
|
44
|
+
});
|
|
45
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface SqlBlock {
|
|
2
|
+
name: string;
|
|
3
|
+
sql: string;
|
|
4
|
+
startLine: number;
|
|
5
|
+
endLine: number;
|
|
6
|
+
}
|
|
7
|
+
export interface ParsedMarkdownDocument {
|
|
8
|
+
frontmatter: Record<string, any>;
|
|
9
|
+
content: string;
|
|
10
|
+
sqlBlocks: SqlBlock[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Parse a markdown document with YAML frontmatter and SQL code blocks.
|
|
14
|
+
*
|
|
15
|
+
* Evidence-compatible syntax:
|
|
16
|
+
* ```sql query_name
|
|
17
|
+
* SELECT * FROM table
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseMarkdownDocument(markdown: string): ParsedMarkdownDocument;
|
|
21
|
+
/**
|
|
22
|
+
* Interpolate template variables in markdown text.
|
|
23
|
+
* Supports {queryName.rows[0].columnName} syntax.
|
|
24
|
+
*/
|
|
25
|
+
export declare function interpolateTemplates(text: string, queryResults: Map<string, Record<string, any>[]>): string;
|
|
26
|
+
/**
|
|
27
|
+
* Replace SQL blocks in markdown content with placeholder markers
|
|
28
|
+
* that can be replaced with rendered components.
|
|
29
|
+
*/
|
|
30
|
+
export declare function markSqlBlocks(content: string): string;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import YAML from 'yaml';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a markdown document with YAML frontmatter and SQL code blocks.
|
|
4
|
+
*
|
|
5
|
+
* Evidence-compatible syntax:
|
|
6
|
+
* ```sql query_name
|
|
7
|
+
* SELECT * FROM table
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
export function parseMarkdownDocument(markdown) {
|
|
11
|
+
let frontmatter = {};
|
|
12
|
+
let content = markdown;
|
|
13
|
+
// Extract YAML frontmatter
|
|
14
|
+
const fmMatch = markdown.match(/^---\n([\s\S]*?)\n---\n/);
|
|
15
|
+
if (fmMatch) {
|
|
16
|
+
try {
|
|
17
|
+
frontmatter = YAML.parse(fmMatch[1]) || {};
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
// Invalid YAML — ignore
|
|
21
|
+
}
|
|
22
|
+
content = markdown.slice(fmMatch[0].length);
|
|
23
|
+
}
|
|
24
|
+
// Extract SQL blocks
|
|
25
|
+
const sqlBlocks = [];
|
|
26
|
+
const lines = content.split('\n');
|
|
27
|
+
let i = 0;
|
|
28
|
+
while (i < lines.length) {
|
|
29
|
+
const line = lines[i];
|
|
30
|
+
const match = line.match(/^```sql\s+(\w[\w-]*)\s*$/);
|
|
31
|
+
if (match) {
|
|
32
|
+
const name = match[1];
|
|
33
|
+
const startLine = i;
|
|
34
|
+
const sqlLines = [];
|
|
35
|
+
i++;
|
|
36
|
+
while (i < lines.length && lines[i] !== '```') {
|
|
37
|
+
sqlLines.push(lines[i]);
|
|
38
|
+
i++;
|
|
39
|
+
}
|
|
40
|
+
sqlBlocks.push({
|
|
41
|
+
name,
|
|
42
|
+
sql: sqlLines.join('\n'),
|
|
43
|
+
startLine,
|
|
44
|
+
endLine: i
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
i++;
|
|
48
|
+
}
|
|
49
|
+
return { frontmatter, content, sqlBlocks };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Interpolate template variables in markdown text.
|
|
53
|
+
* Supports {queryName.rows[0].columnName} syntax.
|
|
54
|
+
*/
|
|
55
|
+
export function interpolateTemplates(text, queryResults) {
|
|
56
|
+
return text.replace(/\{(\w+)\.rows\[(\d+)\]\.(\w+)\}/g, (match, queryName, rowIdx, colName) => {
|
|
57
|
+
const rows = queryResults.get(queryName);
|
|
58
|
+
if (!rows)
|
|
59
|
+
return match;
|
|
60
|
+
const row = rows[parseInt(rowIdx, 10)];
|
|
61
|
+
if (!row)
|
|
62
|
+
return match;
|
|
63
|
+
const value = row[colName];
|
|
64
|
+
return value !== undefined ? String(value) : match;
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Replace SQL blocks in markdown content with placeholder markers
|
|
69
|
+
* that can be replaced with rendered components.
|
|
70
|
+
*/
|
|
71
|
+
export function markSqlBlocks(content) {
|
|
72
|
+
return content.replace(/```sql\s+(\w[\w-]*)\s*\n([\s\S]*?)```/g, (_, name) => `<div data-sql-block="${name}"></div>`);
|
|
73
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders markdown to HTML with GFM support.
|
|
3
|
+
* Code blocks use reversed Shiki theme (dark on light, light on dark)
|
|
4
|
+
* and include a copy button.
|
|
5
|
+
*/
|
|
6
|
+
export declare function renderMarkdown(markdown: string): Promise<string>;
|
|
7
|
+
/**
|
|
8
|
+
* Detect whether text is primarily RTL by sampling the first 1000 characters.
|
|
9
|
+
*/
|
|
10
|
+
export declare function detectRTL(text: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Post-process rendered HTML for RTL/LTR direction.
|
|
13
|
+
* Uses DOM-based approach for reliable mixed content handling.
|
|
14
|
+
* Code blocks always get LTR. In RTL docs, individual block elements
|
|
15
|
+
* get direction based on their content language.
|
|
16
|
+
* Western digits (0-9) are LTR, Arabic-Indic digits (٠-٩) are RTL.
|
|
17
|
+
*/
|
|
18
|
+
export declare function processDirection(html: string, isRTL: boolean): string;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { Marked } from 'marked';
|
|
2
|
+
import { extensionToShikiLang, highlightCodeReversed } from './shiki';
|
|
3
|
+
let markedInstance = null;
|
|
4
|
+
function getMarked() {
|
|
5
|
+
if (markedInstance)
|
|
6
|
+
return markedInstance;
|
|
7
|
+
markedInstance = new Marked({
|
|
8
|
+
async: true,
|
|
9
|
+
gfm: true,
|
|
10
|
+
breaks: false
|
|
11
|
+
});
|
|
12
|
+
markedInstance.use({
|
|
13
|
+
renderer: {
|
|
14
|
+
code({ text, lang }) {
|
|
15
|
+
const escaped = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
16
|
+
if (lang === 'mermaid') {
|
|
17
|
+
return `<div class="mermaid">${escaped}</div>`;
|
|
18
|
+
}
|
|
19
|
+
return `<pre class="shiki-pending" data-lang="${lang || ''}" data-code="${encodeURIComponent(text)}"><code>${escaped}</code></pre>`;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
return markedInstance;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Renders markdown to HTML with GFM support.
|
|
27
|
+
* Code blocks use reversed Shiki theme (dark on light, light on dark)
|
|
28
|
+
* and include a copy button.
|
|
29
|
+
*/
|
|
30
|
+
export async function renderMarkdown(markdown) {
|
|
31
|
+
const marked = getMarked();
|
|
32
|
+
let html = await marked.parse(markdown);
|
|
33
|
+
// Post-process: highlight code blocks with Shiki (reversed theme)
|
|
34
|
+
const codeBlockRegex = /<pre class="shiki-pending" data-lang="([^"]*)" data-code="([^"]*)"><code>[\s\S]*?<\/code><\/pre>/g;
|
|
35
|
+
const matches = [...html.matchAll(codeBlockRegex)];
|
|
36
|
+
for (const match of matches) {
|
|
37
|
+
const lang = match[1];
|
|
38
|
+
const code = decodeURIComponent(match[2]);
|
|
39
|
+
const shikiLang = lang ? (extensionToShikiLang(`.${lang}`) ?? lang) : undefined;
|
|
40
|
+
try {
|
|
41
|
+
const highlighted = await highlightCodeReversed(code, shikiLang);
|
|
42
|
+
// Wrap in a container with copy button
|
|
43
|
+
const langLabel = lang ? `<span class="code-lang">${lang}</span>` : '';
|
|
44
|
+
const copyBtn = `<button class="code-copy-btn" data-code="${encodeURIComponent(code)}" title="Copy">${langLabel}<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button>`;
|
|
45
|
+
const wrapped = `<div class="code-block-wrapper">${copyBtn}${highlighted}</div>`;
|
|
46
|
+
html = html.replace(match[0], wrapped);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// If highlighting fails, keep the escaped version
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return html;
|
|
53
|
+
}
|
|
54
|
+
// RTL unicode ranges: Arabic, Hebrew, Arabic Supplement, Arabic Extended
|
|
55
|
+
const RTL_CHAR_REGEX = /[\u0590-\u05FF\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]/;
|
|
56
|
+
// Arabic-Indic digits: ٠١٢٣٤٥٦٧٨٩ and Extended Arabic-Indic: ۰۱۲۳۴۵۶۷۸۹
|
|
57
|
+
const ARABIC_DIGIT_REGEX = /[\u0660-\u0669\u06F0-\u06F9]/;
|
|
58
|
+
// Western digits
|
|
59
|
+
const WESTERN_DIGIT_REGEX = /[0-9]/;
|
|
60
|
+
/**
|
|
61
|
+
* Detect whether text is primarily RTL by sampling the first 1000 characters.
|
|
62
|
+
*/
|
|
63
|
+
export function detectRTL(text) {
|
|
64
|
+
const sample = text.slice(0, 1000);
|
|
65
|
+
let rtlCount = 0;
|
|
66
|
+
for (const char of sample) {
|
|
67
|
+
if (RTL_CHAR_REGEX.test(char))
|
|
68
|
+
rtlCount++;
|
|
69
|
+
}
|
|
70
|
+
return rtlCount > 5;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Determine if a text segment should be LTR.
|
|
74
|
+
* - Text with Latin first strong char and more Latin than Arabic → LTR
|
|
75
|
+
* - Text with only Western digits (0-9) and no Arabic chars → LTR
|
|
76
|
+
* - Text with Arabic-Indic digits (٠-٩) → RTL
|
|
77
|
+
* - Text with Arabic first strong char → RTL
|
|
78
|
+
*/
|
|
79
|
+
function shouldBeLTR(text) {
|
|
80
|
+
if (!text)
|
|
81
|
+
return false;
|
|
82
|
+
// Find the first strong directional character (Arabic or Latin)
|
|
83
|
+
const match = text.match(/[\u0600-\u06FFa-zA-Z]/);
|
|
84
|
+
if (match) {
|
|
85
|
+
// Has strong directional characters
|
|
86
|
+
if (/[a-zA-Z]/.test(match[0])) {
|
|
87
|
+
// First strong char is Latin — confirm with count
|
|
88
|
+
const arabicCount = (text.match(/[\u0600-\u06FF]/g) || []).length;
|
|
89
|
+
const englishCount = (text.match(/[a-zA-Z]/g) || []).length;
|
|
90
|
+
return englishCount > arabicCount;
|
|
91
|
+
}
|
|
92
|
+
// First strong char is Arabic → RTL
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
// No strong directional chars — check digits
|
|
96
|
+
const hasWesternDigits = WESTERN_DIGIT_REGEX.test(text);
|
|
97
|
+
const hasArabicDigits = ARABIC_DIGIT_REGEX.test(text);
|
|
98
|
+
if (hasArabicDigits)
|
|
99
|
+
return false; // Arabic-Indic digits → RTL
|
|
100
|
+
if (hasWesternDigits)
|
|
101
|
+
return true; // Western digits → LTR
|
|
102
|
+
// No directional content at all — inherit parent direction
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Post-process rendered HTML for RTL/LTR direction.
|
|
107
|
+
* Uses DOM-based approach for reliable mixed content handling.
|
|
108
|
+
* Code blocks always get LTR. In RTL docs, individual block elements
|
|
109
|
+
* get direction based on their content language.
|
|
110
|
+
* Western digits (0-9) are LTR, Arabic-Indic digits (٠-٩) are RTL.
|
|
111
|
+
*/
|
|
112
|
+
export function processDirection(html, isRTL) {
|
|
113
|
+
if (typeof document === 'undefined')
|
|
114
|
+
return html;
|
|
115
|
+
if (!isRTL)
|
|
116
|
+
return html;
|
|
117
|
+
const container = document.createElement('div');
|
|
118
|
+
container.innerHTML = html;
|
|
119
|
+
// Code blocks are always LTR
|
|
120
|
+
for (const el of container.querySelectorAll('pre, code')) {
|
|
121
|
+
el.style.direction = 'ltr';
|
|
122
|
+
el.style.textAlign = 'left';
|
|
123
|
+
}
|
|
124
|
+
// Process each block element for mixed content
|
|
125
|
+
for (const el of container.querySelectorAll('p, li, h1, h2, h3, h4, h5, h6, td, th')) {
|
|
126
|
+
const text = el.textContent || '';
|
|
127
|
+
if (shouldBeLTR(text)) {
|
|
128
|
+
el.style.direction = 'ltr';
|
|
129
|
+
el.style.textAlign = 'left';
|
|
130
|
+
// For lists in RTL context with LTR content, swap padding
|
|
131
|
+
if (el.tagName === 'LI') {
|
|
132
|
+
const parent = el.parentElement;
|
|
133
|
+
if (parent && (parent.tagName === 'UL' || parent.tagName === 'OL')) {
|
|
134
|
+
parent.style.paddingLeft = '2em';
|
|
135
|
+
parent.style.paddingRight = '0';
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
// Explicitly set RTL direction on Arabic content
|
|
141
|
+
el.style.direction = 'rtl';
|
|
142
|
+
el.style.textAlign = 'right';
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return container.innerHTML;
|
|
146
|
+
}
|