@ifc-lite/viewer 1.1.7 → 1.6.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 +373 -0
- package/dist/apple-touch-icon.png +0 -0
- package/dist/assets/Arrow.dom-BjDQoB2M.js +20 -0
- package/dist/assets/arrow2-bb-jcVEo.js +2 -0
- package/dist/assets/arrow2_bg-4Y7xYo54.wasm +0 -0
- package/dist/assets/arrow2_bg-BlXl-cSQ.js +1 -0
- package/dist/assets/arrow2_bg-BoXCojjR.wasm +0 -0
- package/dist/assets/desktop-cache-oPzaWXYE.js +1 -0
- package/dist/assets/event-DIOks52T.js +1 -0
- package/dist/assets/ifc-cache-BAN4vcd4.js +1 -0
- package/dist/assets/ifc-lite_bg-C6kblxf9.wasm +0 -0
- package/dist/assets/index-YBtrHPu3.js +65252 -0
- package/dist/assets/index-v3mcCUPN.css +1 -0
- package/dist/assets/native-bridge-CULtTDX3.js +111 -0
- package/dist/assets/wasm-bridge-CjL-lSak.js +1 -0
- package/dist/favicon-16x16-cropped.png +0 -0
- package/dist/favicon-16x16.png +0 -0
- package/dist/favicon-192x192-cropped.png +0 -0
- package/dist/favicon-192x192.png +0 -0
- package/dist/favicon-32x32-cropped.png +0 -0
- package/dist/favicon-32x32.png +0 -0
- package/dist/favicon-48x48-cropped.png +0 -0
- package/dist/favicon-48x48.png +0 -0
- package/dist/favicon-512x512-cropped.png +0 -0
- package/dist/favicon-512x512.png +0 -0
- package/dist/favicon-64x64-cropped.png +0 -0
- package/dist/favicon-64x64.png +0 -0
- package/dist/favicon-96x96-cropped.png +0 -0
- package/dist/favicon-96x96.png +0 -0
- package/dist/favicon-square-512.png +0 -0
- package/dist/favicon.ico +0 -0
- package/dist/favicon.png +0 -0
- package/dist/favicon.svg +3 -0
- package/dist/index.html +44 -0
- package/dist/logo.png +0 -0
- package/dist/manifest.json +48 -0
- package/index.html +33 -2
- package/package.json +34 -17
- package/public/apple-touch-icon.png +0 -0
- package/public/favicon-16x16-cropped.png +0 -0
- package/public/favicon-16x16.png +0 -0
- package/public/favicon-192x192-cropped.png +0 -0
- package/public/favicon-192x192.png +0 -0
- package/public/favicon-32x32-cropped.png +0 -0
- package/public/favicon-32x32.png +0 -0
- package/public/favicon-48x48-cropped.png +0 -0
- package/public/favicon-48x48.png +0 -0
- package/public/favicon-512x512-cropped.png +0 -0
- package/public/favicon-512x512.png +0 -0
- package/public/favicon-64x64-cropped.png +0 -0
- package/public/favicon-64x64.png +0 -0
- package/public/favicon-96x96-cropped.png +0 -0
- package/public/favicon-96x96.png +0 -0
- package/public/favicon-square-512.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/favicon.png +0 -0
- package/public/favicon.svg +3 -0
- package/public/logo.png +0 -0
- package/public/manifest.json +48 -0
- package/src/App.tsx +2 -0
- package/src/components/ui/alert.tsx +62 -0
- package/src/components/ui/badge.tsx +39 -0
- package/src/components/ui/dialog.tsx +120 -0
- package/src/components/ui/label.tsx +27 -0
- package/src/components/ui/select.tsx +151 -0
- package/src/components/ui/switch.tsx +30 -0
- package/src/components/ui/table.tsx +120 -0
- package/src/components/ui/tabs.tsx +1 -1
- package/src/components/viewer/BCFPanel.tsx +1164 -0
- package/src/components/viewer/BulkPropertyEditor.tsx +875 -0
- package/src/components/viewer/DataConnector.tsx +840 -0
- package/src/components/viewer/DrawingSettingsPanel.tsx +536 -0
- package/src/components/viewer/EntityContextMenu.tsx +45 -17
- package/src/components/viewer/ExportChangesButton.tsx +195 -0
- package/src/components/viewer/ExportDialog.tsx +402 -0
- package/src/components/viewer/HierarchyPanel.tsx +1132 -218
- package/src/components/viewer/IDSPanel.tsx +661 -0
- package/src/components/viewer/KeyboardShortcutsDialog.tsx +245 -39
- package/src/components/viewer/MainToolbar.tsx +418 -94
- package/src/components/viewer/PropertiesPanel.tsx +1355 -91
- package/src/components/viewer/PropertyEditor.tsx +611 -0
- package/src/components/viewer/Section2DPanel.tsx +3313 -0
- package/src/components/viewer/SheetSetupPanel.tsx +502 -0
- package/src/components/viewer/StatusBar.tsx +27 -16
- package/src/components/viewer/TitleBlockEditor.tsx +437 -0
- package/src/components/viewer/ToolOverlays.tsx +935 -127
- package/src/components/viewer/ViewerLayout.tsx +40 -11
- package/src/components/viewer/Viewport.tsx +1276 -336
- package/src/components/viewer/ViewportContainer.tsx +554 -18
- package/src/components/viewer/ViewportOverlays.tsx +24 -7
- package/src/hooks/useBCF.ts +504 -0
- package/src/hooks/useIDS.ts +1065 -0
- package/src/hooks/useIfc.ts +1534 -205
- package/src/hooks/useIfcCache.ts +279 -0
- package/src/hooks/useKeyboardShortcuts.ts +50 -8
- package/src/hooks/useModelSelection.ts +61 -0
- package/src/hooks/useViewerSelectors.ts +218 -0
- package/src/hooks/useWebGPU.ts +80 -0
- package/src/index.css +265 -27
- package/src/lib/platform.ts +23 -0
- package/src/services/cacheService.ts +142 -0
- package/src/services/desktop-cache.ts +143 -0
- package/src/services/fs-cache.ts +212 -0
- package/src/services/ifc-cache.ts +14 -6
- package/src/store/constants.ts +85 -0
- package/src/store/index.ts +214 -0
- package/src/store/slices/bcfSlice.ts +372 -0
- package/src/store/slices/cameraSlice.ts +63 -0
- package/src/store/slices/dataSlice.test.ts +226 -0
- package/src/store/slices/dataSlice.ts +112 -0
- package/src/store/slices/drawing2DSlice.ts +340 -0
- package/src/store/slices/hoverSlice.ts +40 -0
- package/src/store/slices/idsSlice.ts +310 -0
- package/src/store/slices/loadingSlice.ts +33 -0
- package/src/store/slices/measurementSlice.test.ts +217 -0
- package/src/store/slices/measurementSlice.ts +293 -0
- package/src/store/slices/modelSlice.test.ts +271 -0
- package/src/store/slices/modelSlice.ts +211 -0
- package/src/store/slices/mutationSlice.ts +502 -0
- package/src/store/slices/sectionSlice.test.ts +125 -0
- package/src/store/slices/sectionSlice.ts +58 -0
- package/src/store/slices/selectionSlice.test.ts +286 -0
- package/src/store/slices/selectionSlice.ts +263 -0
- package/src/store/slices/sheetSlice.ts +565 -0
- package/src/store/slices/uiSlice.ts +58 -0
- package/src/store/slices/visibilitySlice.test.ts +304 -0
- package/src/store/slices/visibilitySlice.ts +277 -0
- package/src/store/types.test.ts +135 -0
- package/src/store/types.ts +248 -0
- package/src/store.ts +40 -515
- package/src/utils/ifcConfig.ts +82 -0
- package/src/utils/localParsingUtils.ts +287 -0
- package/src/utils/serverDataModel.ts +783 -0
- package/src/utils/spatialHierarchy.ts +283 -0
- package/src/utils/viewportUtils.ts +334 -0
- package/src/vite-env.d.ts +23 -0
- package/src/webgpu-types.d.ts +128 -0
- package/src-tauri/Cargo.toml +29 -0
- package/src-tauri/build.rs +7 -0
- package/src-tauri/capabilities/default.json +18 -0
- package/src-tauri/icons/128x128.png +0 -0
- package/src-tauri/icons/128x128@2x.png +0 -0
- package/src-tauri/icons/32x32.png +0 -0
- package/src-tauri/icons/Square107x107Logo.png +0 -0
- package/src-tauri/icons/Square142x142Logo.png +0 -0
- package/src-tauri/icons/Square150x150Logo.png +0 -0
- package/src-tauri/icons/Square284x284Logo.png +0 -0
- package/src-tauri/icons/Square30x30Logo.png +0 -0
- package/src-tauri/icons/Square310x310Logo.png +0 -0
- package/src-tauri/icons/Square44x44Logo.png +0 -0
- package/src-tauri/icons/Square71x71Logo.png +0 -0
- package/src-tauri/icons/Square89x89Logo.png +0 -0
- package/src-tauri/icons/StoreLogo.png +0 -0
- package/src-tauri/icons/icon.icns +0 -0
- package/src-tauri/icons/icon.ico +0 -0
- package/src-tauri/icons/icon.png +0 -0
- package/src-tauri/src/lib.rs +21 -0
- package/src-tauri/src/main.rs +10 -0
- package/src-tauri/tauri.conf.json +39 -0
- package/vite.config.ts +174 -26
- package/public/ifc-lite_bg.wasm +0 -0
- package/public/web-ifc.wasm +0 -0
- package/src/components/Viewport.tsx +0 -723
- package/src/components/viewer/BoxSelectionOverlay.tsx +0 -53
package/src/webgpu-types.d.ts
CHANGED
|
@@ -6,6 +6,134 @@
|
|
|
6
6
|
* WebGPU type definitions for TypeScript
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
// Extend Navigator interface with WebGPU support
|
|
10
|
+
interface Navigator {
|
|
11
|
+
readonly gpu?: GPU;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// GPU interface for WebGPU API
|
|
15
|
+
interface GPU {
|
|
16
|
+
requestAdapter(options?: GPURequestAdapterOptions): Promise<GPUAdapter | null>;
|
|
17
|
+
getPreferredCanvasFormat(): GPUTextureFormat;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface GPURequestAdapterOptions {
|
|
21
|
+
powerPreference?: 'low-power' | 'high-performance';
|
|
22
|
+
forceFallbackAdapter?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface GPUAdapter {
|
|
26
|
+
readonly features: GPUSupportedFeatures;
|
|
27
|
+
readonly limits: GPUSupportedLimits;
|
|
28
|
+
readonly isFallbackAdapter: boolean;
|
|
29
|
+
requestDevice(descriptor?: GPUDeviceDescriptor): Promise<GPUDevice>;
|
|
30
|
+
requestAdapterInfo(): Promise<GPUAdapterInfo>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface GPUSupportedFeatures extends ReadonlySet<string> {}
|
|
34
|
+
|
|
35
|
+
interface GPUSupportedLimits {
|
|
36
|
+
readonly maxTextureDimension1D: number;
|
|
37
|
+
readonly maxTextureDimension2D: number;
|
|
38
|
+
readonly maxTextureDimension3D: number;
|
|
39
|
+
readonly maxTextureArrayLayers: number;
|
|
40
|
+
readonly maxBindGroups: number;
|
|
41
|
+
readonly maxBindingsPerBindGroup: number;
|
|
42
|
+
readonly maxDynamicUniformBuffersPerPipelineLayout: number;
|
|
43
|
+
readonly maxDynamicStorageBuffersPerPipelineLayout: number;
|
|
44
|
+
readonly maxSampledTexturesPerShaderStage: number;
|
|
45
|
+
readonly maxSamplersPerShaderStage: number;
|
|
46
|
+
readonly maxStorageBuffersPerShaderStage: number;
|
|
47
|
+
readonly maxStorageTexturesPerShaderStage: number;
|
|
48
|
+
readonly maxUniformBuffersPerShaderStage: number;
|
|
49
|
+
readonly maxUniformBufferBindingSize: number;
|
|
50
|
+
readonly maxStorageBufferBindingSize: number;
|
|
51
|
+
readonly minUniformBufferOffsetAlignment: number;
|
|
52
|
+
readonly minStorageBufferOffsetAlignment: number;
|
|
53
|
+
readonly maxVertexBuffers: number;
|
|
54
|
+
readonly maxBufferSize: number;
|
|
55
|
+
readonly maxVertexAttributes: number;
|
|
56
|
+
readonly maxVertexBufferArrayStride: number;
|
|
57
|
+
readonly maxInterStageShaderComponents: number;
|
|
58
|
+
readonly maxColorAttachments: number;
|
|
59
|
+
readonly maxColorAttachmentBytesPerSample: number;
|
|
60
|
+
readonly maxComputeWorkgroupStorageSize: number;
|
|
61
|
+
readonly maxComputeInvocationsPerWorkgroup: number;
|
|
62
|
+
readonly maxComputeWorkgroupSizeX: number;
|
|
63
|
+
readonly maxComputeWorkgroupSizeY: number;
|
|
64
|
+
readonly maxComputeWorkgroupSizeZ: number;
|
|
65
|
+
readonly maxComputeWorkgroupsPerDimension: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
interface GPUDeviceDescriptor {
|
|
69
|
+
requiredFeatures?: Iterable<string>;
|
|
70
|
+
requiredLimits?: Record<string, number>;
|
|
71
|
+
label?: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface GPUDevice extends EventTarget {
|
|
75
|
+
readonly features: GPUSupportedFeatures;
|
|
76
|
+
readonly limits: GPUSupportedLimits;
|
|
77
|
+
readonly queue: GPUQueue;
|
|
78
|
+
readonly lost: Promise<GPUDeviceLostInfo>;
|
|
79
|
+
destroy(): void;
|
|
80
|
+
createBuffer(descriptor: GPUBufferDescriptor): GPUBuffer;
|
|
81
|
+
createTexture(descriptor: GPUTextureDescriptor): GPUTexture;
|
|
82
|
+
createSampler(descriptor?: GPUSamplerDescriptor): GPUSampler;
|
|
83
|
+
createBindGroupLayout(descriptor: GPUBindGroupLayoutDescriptor): GPUBindGroupLayout;
|
|
84
|
+
createPipelineLayout(descriptor: GPUPipelineLayoutDescriptor): GPUPipelineLayout;
|
|
85
|
+
createBindGroup(descriptor: GPUBindGroupDescriptor): GPUBindGroup;
|
|
86
|
+
createShaderModule(descriptor: GPUShaderModuleDescriptor): GPUShaderModule;
|
|
87
|
+
createComputePipeline(descriptor: GPUComputePipelineDescriptor): GPUComputePipeline;
|
|
88
|
+
createRenderPipeline(descriptor: GPURenderPipelineDescriptor): GPURenderPipeline;
|
|
89
|
+
createComputePipelineAsync(descriptor: GPUComputePipelineDescriptor): Promise<GPUComputePipeline>;
|
|
90
|
+
createRenderPipelineAsync(descriptor: GPURenderPipelineDescriptor): Promise<GPURenderPipeline>;
|
|
91
|
+
createCommandEncoder(descriptor?: GPUCommandEncoderDescriptor): GPUCommandEncoder;
|
|
92
|
+
createRenderBundleEncoder(descriptor: GPURenderBundleEncoderDescriptor): GPURenderBundleEncoder;
|
|
93
|
+
createQuerySet(descriptor: GPUQuerySetDescriptor): GPUQuerySet;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
interface GPUAdapterInfo {
|
|
97
|
+
readonly vendor: string;
|
|
98
|
+
readonly architecture: string;
|
|
99
|
+
readonly device: string;
|
|
100
|
+
readonly description: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
interface GPUDeviceLostInfo {
|
|
104
|
+
readonly reason: 'unknown' | 'destroyed';
|
|
105
|
+
readonly message: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
type GPUTextureFormat = string;
|
|
109
|
+
|
|
110
|
+
// Minimal interfaces for other GPU types (as placeholders)
|
|
111
|
+
interface GPUQueue {}
|
|
112
|
+
interface GPUBuffer {}
|
|
113
|
+
interface GPUTexture {}
|
|
114
|
+
interface GPUSampler {}
|
|
115
|
+
interface GPUBindGroupLayout {}
|
|
116
|
+
interface GPUPipelineLayout {}
|
|
117
|
+
interface GPUBindGroup {}
|
|
118
|
+
interface GPUShaderModule {}
|
|
119
|
+
interface GPUComputePipeline {}
|
|
120
|
+
interface GPURenderPipeline {}
|
|
121
|
+
interface GPUCommandEncoder {}
|
|
122
|
+
interface GPURenderBundleEncoder {}
|
|
123
|
+
interface GPUQuerySet {}
|
|
124
|
+
interface GPUBufferDescriptor {}
|
|
125
|
+
interface GPUTextureDescriptor {}
|
|
126
|
+
interface GPUSamplerDescriptor {}
|
|
127
|
+
interface GPUBindGroupLayoutDescriptor {}
|
|
128
|
+
interface GPUPipelineLayoutDescriptor {}
|
|
129
|
+
interface GPUBindGroupDescriptor {}
|
|
130
|
+
interface GPUShaderModuleDescriptor {}
|
|
131
|
+
interface GPUComputePipelineDescriptor {}
|
|
132
|
+
interface GPURenderPipelineDescriptor {}
|
|
133
|
+
interface GPUCommandEncoderDescriptor {}
|
|
134
|
+
interface GPURenderBundleEncoderDescriptor {}
|
|
135
|
+
interface GPUQuerySetDescriptor {}
|
|
136
|
+
|
|
9
137
|
declare const GPUBufferUsage: {
|
|
10
138
|
readonly MAP_READ: number;
|
|
11
139
|
readonly MAP_WRITE: number;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "app"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A Tauri App"
|
|
5
|
+
authors = ["you"]
|
|
6
|
+
license = ""
|
|
7
|
+
repository = ""
|
|
8
|
+
edition = "2021"
|
|
9
|
+
rust-version = "1.77.2"
|
|
10
|
+
|
|
11
|
+
# Exclude from parent workspace
|
|
12
|
+
[workspace]
|
|
13
|
+
|
|
14
|
+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
15
|
+
|
|
16
|
+
[lib]
|
|
17
|
+
name = "app_lib"
|
|
18
|
+
crate-type = ["staticlib", "cdylib", "rlib"]
|
|
19
|
+
|
|
20
|
+
[build-dependencies]
|
|
21
|
+
tauri-build = { version = "2.5.3", features = [] }
|
|
22
|
+
|
|
23
|
+
[dependencies]
|
|
24
|
+
serde_json = "1.0"
|
|
25
|
+
serde = { version = "1.0", features = ["derive"] }
|
|
26
|
+
log = "0.4"
|
|
27
|
+
tauri = { version = "2.9.5", features = [] }
|
|
28
|
+
tauri-plugin-log = "2"
|
|
29
|
+
tauri-plugin-fs = "2"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../gen/schemas/desktop-schema.json",
|
|
3
|
+
"identifier": "default",
|
|
4
|
+
"description": "enables the default permissions",
|
|
5
|
+
"windows": [
|
|
6
|
+
"main"
|
|
7
|
+
],
|
|
8
|
+
"permissions": [
|
|
9
|
+
"core:default",
|
|
10
|
+
"fs:allow-read-file",
|
|
11
|
+
"fs:allow-write-file",
|
|
12
|
+
"fs:allow-read-dir",
|
|
13
|
+
"fs:allow-create",
|
|
14
|
+
"fs:allow-exists",
|
|
15
|
+
"fs:allow-remove",
|
|
16
|
+
"fs:scope-appdata"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
|
|
5
|
+
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
|
6
|
+
pub fn run() {
|
|
7
|
+
tauri::Builder::default()
|
|
8
|
+
.plugin(tauri_plugin_fs::init())
|
|
9
|
+
.setup(|app| {
|
|
10
|
+
if cfg!(debug_assertions) {
|
|
11
|
+
app.handle().plugin(
|
|
12
|
+
tauri_plugin_log::Builder::default()
|
|
13
|
+
.level(log::LevelFilter::Info)
|
|
14
|
+
.build(),
|
|
15
|
+
)?;
|
|
16
|
+
}
|
|
17
|
+
Ok(())
|
|
18
|
+
})
|
|
19
|
+
.run(tauri::generate_context!())
|
|
20
|
+
.expect("error while running tauri application");
|
|
21
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
|
|
5
|
+
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
|
6
|
+
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
|
7
|
+
|
|
8
|
+
fn main() {
|
|
9
|
+
app_lib::run();
|
|
10
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../../../node_modules/@tauri-apps/cli/config.schema.json",
|
|
3
|
+
"productName": "IFC-Lite",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"identifier": "com.tauri.dev",
|
|
6
|
+
"build": {
|
|
7
|
+
"frontendDist": "../dist",
|
|
8
|
+
"devUrl": "http://127.0.0.1:3000",
|
|
9
|
+
"beforeDevCommand": "pnpm dev",
|
|
10
|
+
"beforeBuildCommand": "pnpm build"
|
|
11
|
+
},
|
|
12
|
+
"app": {
|
|
13
|
+
"windows": [
|
|
14
|
+
{
|
|
15
|
+
"title": "IFC-Lite Viewer",
|
|
16
|
+
"width": 1400,
|
|
17
|
+
"height": 900,
|
|
18
|
+
"resizable": true,
|
|
19
|
+
"fullscreen": false,
|
|
20
|
+
"minWidth": 800,
|
|
21
|
+
"minHeight": 600
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"security": {
|
|
25
|
+
"csp": null
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"bundle": {
|
|
29
|
+
"active": true,
|
|
30
|
+
"targets": "all",
|
|
31
|
+
"icon": [
|
|
32
|
+
"icons/32x32.png",
|
|
33
|
+
"icons/128x128.png",
|
|
34
|
+
"icons/128x128@2x.png",
|
|
35
|
+
"icons/icon.icns",
|
|
36
|
+
"icons/icon.ico"
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
}
|
package/vite.config.ts
CHANGED
|
@@ -1,9 +1,173 @@
|
|
|
1
1
|
import { defineConfig } from 'vite';
|
|
2
2
|
import react from '@vitejs/plugin-react';
|
|
3
|
+
import wasm from 'vite-plugin-wasm';
|
|
4
|
+
import topLevelAwait from 'vite-plugin-top-level-await';
|
|
3
5
|
import path from 'path';
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
|
|
8
|
+
// --- Build-time changelog parser ---
|
|
9
|
+
|
|
10
|
+
interface ReleaseHighlight {
|
|
11
|
+
type: 'feature' | 'fix' | 'perf';
|
|
12
|
+
text: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface Release {
|
|
16
|
+
version: string;
|
|
17
|
+
highlights: ReleaseHighlight[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const SKIP_BOLD_LOWER = new Set([
|
|
21
|
+
'bug fixes', 'new features', 'performance improvements', 'technical details',
|
|
22
|
+
'renderer fixes', 'parser fixes', 'viewer integration', 'fixes', 'features',
|
|
23
|
+
'breaking', 'minor changes', 'patch changes', 'dependencies',
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
function isInternalName(text: string): boolean {
|
|
27
|
+
// Skip PascalCase single-word class names like "PolygonalFaceSetProcessor"
|
|
28
|
+
return /^[A-Z][a-zA-Z]+$/.test(text) && !text.includes(' ');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function categorizeHighlight(text: string): 'feature' | 'fix' | 'perf' {
|
|
32
|
+
const lower = text.toLowerCase();
|
|
33
|
+
if (lower.startsWith('fixed ') || lower.startsWith('fix ')) return 'fix';
|
|
34
|
+
if (
|
|
35
|
+
lower.includes('performance') || lower.includes('optimiz') ||
|
|
36
|
+
lower.includes('zero-copy') || lower.includes('faster') ||
|
|
37
|
+
lower.includes('batch siz')
|
|
38
|
+
) return 'perf';
|
|
39
|
+
return 'feature';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function extractBulletDescription(line: string): string | null {
|
|
43
|
+
let text = line.replace(/^-\s+/, '');
|
|
44
|
+
|
|
45
|
+
// Pattern: "HASH: ### Header" -> skip inline section headers
|
|
46
|
+
if (/^[a-f0-9]{7,}:\s*###/.test(text)) return null;
|
|
47
|
+
|
|
48
|
+
// Pattern: "HASH: feat/fix/perf: DESCRIPTION"
|
|
49
|
+
const hashPrefixed = text.match(/^[a-f0-9]{7,}:\s*(?:feat|fix|perf|refactor|chore):\s*(.+)$/i);
|
|
50
|
+
if (hashPrefixed) return hashPrefixed[1].trim();
|
|
51
|
+
|
|
52
|
+
// Pattern: "HASH: DESCRIPTION" (without conventional commit prefix)
|
|
53
|
+
const hashOnly = text.match(/^[a-f0-9]{7,}:\s*(.+)$/);
|
|
54
|
+
if (hashOnly) return hashOnly[1].trim();
|
|
55
|
+
|
|
56
|
+
// Pattern: "[#PR](url) [`hash`](url) Thanks @user! - DESCRIPTION"
|
|
57
|
+
const prPattern = text.match(/Thanks\s+\[@[^\]]+\]\([^)]+\)!\s*-\s*(.+)$/);
|
|
58
|
+
if (prPattern) return prPattern[1].trim();
|
|
59
|
+
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function compareSemver(a: string, b: string): number {
|
|
64
|
+
const pa = a.split('.').map(Number);
|
|
65
|
+
const pb = b.split('.').map(Number);
|
|
66
|
+
for (let i = 0; i < 3; i++) {
|
|
67
|
+
if (pa[i] !== pb[i]) return pa[i] - pb[i];
|
|
68
|
+
}
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function parseChangelogs(): Release[] {
|
|
73
|
+
const packagesDir = path.resolve(__dirname, '../../packages');
|
|
74
|
+
let dirs: string[];
|
|
75
|
+
try {
|
|
76
|
+
dirs = fs.readdirSync(packagesDir);
|
|
77
|
+
} catch {
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const versionMap = new Map<string, Map<string, ReleaseHighlight>>();
|
|
82
|
+
const seenVersionsPerFile = new Map<string, Set<string>>();
|
|
83
|
+
|
|
84
|
+
for (const dir of dirs) {
|
|
85
|
+
const changelogPath = path.join(packagesDir, dir, 'CHANGELOG.md');
|
|
86
|
+
if (!fs.existsSync(changelogPath)) continue;
|
|
87
|
+
|
|
88
|
+
const content = fs.readFileSync(changelogPath, 'utf-8');
|
|
89
|
+
const fileKey = dir;
|
|
90
|
+
seenVersionsPerFile.set(fileKey, new Set());
|
|
91
|
+
|
|
92
|
+
// Split into version blocks
|
|
93
|
+
const versionBlocks = content.split(/^## /m).slice(1);
|
|
94
|
+
|
|
95
|
+
for (const block of versionBlocks) {
|
|
96
|
+
const versionMatch = block.match(/^(\d+\.\d+\.\d+)/);
|
|
97
|
+
if (!versionMatch) continue;
|
|
98
|
+
const version = versionMatch[1];
|
|
99
|
+
|
|
100
|
+
// Skip duplicate version sections within same file
|
|
101
|
+
if (seenVersionsPerFile.get(fileKey)!.has(version)) continue;
|
|
102
|
+
seenVersionsPerFile.get(fileKey)!.add(version);
|
|
103
|
+
|
|
104
|
+
if (!versionMap.has(version)) {
|
|
105
|
+
versionMap.set(version, new Map());
|
|
106
|
+
}
|
|
107
|
+
const highlights = versionMap.get(version)!;
|
|
108
|
+
|
|
109
|
+
const lines = block.split('\n');
|
|
110
|
+
|
|
111
|
+
// 1) Extract top-level bullet descriptions (lines starting with "- " at root indent)
|
|
112
|
+
for (const line of lines) {
|
|
113
|
+
if (!line.startsWith('- ')) continue;
|
|
114
|
+
if (line.startsWith('- Updated dependencies')) continue;
|
|
115
|
+
|
|
116
|
+
const desc = extractBulletDescription(line);
|
|
117
|
+
if (desc && desc.length >= 10) {
|
|
118
|
+
const key = desc.toLowerCase().substring(0, 60);
|
|
119
|
+
if (!highlights.has(key)) {
|
|
120
|
+
highlights.set(key, { type: categorizeHighlight(desc), text: desc });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 2) Extract bold items as highlights (nested feature names)
|
|
126
|
+
const boldRegex = /\*\*([^*]+)\*\*/g;
|
|
127
|
+
let match;
|
|
128
|
+
while ((match = boldRegex.exec(block)) !== null) {
|
|
129
|
+
let text = match[1].trim();
|
|
130
|
+
if (text.endsWith(':')) text = text.slice(0, -1);
|
|
131
|
+
if (text.includes('@ifc-lite/')) continue;
|
|
132
|
+
if (SKIP_BOLD_LOWER.has(text.toLowerCase())) continue;
|
|
133
|
+
if (text.length < 10) continue;
|
|
134
|
+
if (isInternalName(text)) continue;
|
|
135
|
+
|
|
136
|
+
const key = text.toLowerCase().substring(0, 60);
|
|
137
|
+
if (!highlights.has(key)) {
|
|
138
|
+
highlights.set(key, { type: categorizeHighlight(text), text });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const MAX_HIGHLIGHTS_PER_VERSION = 12;
|
|
145
|
+
|
|
146
|
+
return Array.from(versionMap.entries())
|
|
147
|
+
.sort((a, b) => compareSemver(b[0], a[0]))
|
|
148
|
+
.map(([version, highlights]) => ({
|
|
149
|
+
version,
|
|
150
|
+
highlights: Array.from(highlights.values()).slice(0, MAX_HIGHLIGHTS_PER_VERSION),
|
|
151
|
+
}))
|
|
152
|
+
.filter((r) => r.highlights.length > 0);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Read version from root package.json
|
|
156
|
+
const rootPkg = JSON.parse(
|
|
157
|
+
fs.readFileSync(path.resolve(__dirname, '../../package.json'), 'utf-8')
|
|
158
|
+
);
|
|
4
159
|
|
|
5
160
|
export default defineConfig({
|
|
6
|
-
plugins: [
|
|
161
|
+
plugins: [
|
|
162
|
+
react(),
|
|
163
|
+
wasm(),
|
|
164
|
+
topLevelAwait(),
|
|
165
|
+
],
|
|
166
|
+
define: {
|
|
167
|
+
__APP_VERSION__: JSON.stringify(rootPkg.version),
|
|
168
|
+
__BUILD_DATE__: JSON.stringify(new Date().toISOString()),
|
|
169
|
+
__RELEASE_HISTORY__: JSON.stringify(parseChangelogs()),
|
|
170
|
+
},
|
|
7
171
|
resolve: {
|
|
8
172
|
alias: {
|
|
9
173
|
'@': path.resolve(__dirname, './src'),
|
|
@@ -11,49 +175,33 @@ export default defineConfig({
|
|
|
11
175
|
'@ifc-lite/geometry': path.resolve(__dirname, '../../packages/geometry/src'),
|
|
12
176
|
'@ifc-lite/renderer': path.resolve(__dirname, '../../packages/renderer/src'),
|
|
13
177
|
'@ifc-lite/query': path.resolve(__dirname, '../../packages/query/src'),
|
|
178
|
+
'@ifc-lite/server-client': path.resolve(__dirname, '../../packages/server-client/src'),
|
|
14
179
|
'@ifc-lite/spatial': path.resolve(__dirname, '../../packages/spatial/src'),
|
|
15
180
|
'@ifc-lite/data': path.resolve(__dirname, '../../packages/data/src'),
|
|
16
181
|
'@ifc-lite/export': path.resolve(__dirname, '../../packages/export/src'),
|
|
17
182
|
'@ifc-lite/cache': path.resolve(__dirname, '../../packages/cache/src'),
|
|
183
|
+
'@ifc-lite/ifcx': path.resolve(__dirname, '../../packages/ifcx/src'),
|
|
18
184
|
'@ifc-lite/wasm': path.resolve(__dirname, '../../packages/wasm/pkg/ifc-lite.js'),
|
|
19
185
|
},
|
|
20
186
|
},
|
|
21
187
|
server: {
|
|
22
188
|
port: 3000,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
189
|
+
headers: {
|
|
190
|
+
'Cross-Origin-Opener-Policy': 'same-origin',
|
|
191
|
+
'Cross-Origin-Embedder-Policy': 'require-corp',
|
|
26
192
|
},
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
ignored: ['**/node_modules/**', '**/dist/**', '**/target/**', '**/pkg/**'],
|
|
193
|
+
fs: {
|
|
194
|
+
allow: ['../..'],
|
|
30
195
|
},
|
|
31
196
|
},
|
|
32
197
|
build: {
|
|
33
198
|
target: 'esnext',
|
|
34
199
|
},
|
|
35
200
|
optimizeDeps: {
|
|
36
|
-
exclude: ['@duckdb/duckdb-wasm'
|
|
201
|
+
exclude: ['@duckdb/duckdb-wasm', '@ifc-lite/wasm', 'parquet-wasm'],
|
|
37
202
|
},
|
|
38
|
-
assetsInclude: ['**/*.wasm'],
|
|
39
203
|
worker: {
|
|
40
204
|
format: 'es',
|
|
41
|
-
plugins: () => [
|
|
42
|
-
react(),
|
|
43
|
-
// Resolve aliases in worker context
|
|
44
|
-
{
|
|
45
|
-
name: 'worker-alias-resolver',
|
|
46
|
-
resolveId(id) {
|
|
47
|
-
if (id.startsWith('@ifc-lite/')) {
|
|
48
|
-
const packageName = id.split('/')[1];
|
|
49
|
-
// WASM package doesn't have src folder - use pkg
|
|
50
|
-
if (packageName === 'wasm') {
|
|
51
|
-
return path.resolve(__dirname, `../../packages/wasm/pkg/ifc-lite.js`);
|
|
52
|
-
}
|
|
53
|
-
return path.resolve(__dirname, `../../packages/${packageName}/src`);
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
],
|
|
205
|
+
plugins: () => [wasm(), topLevelAwait()],
|
|
58
206
|
},
|
|
59
207
|
});
|
package/public/ifc-lite_bg.wasm
DELETED
|
Binary file
|
package/public/web-ifc.wasm
DELETED
|
Binary file
|