@flyfish-dev/cad-viewer 0.5.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/LICENSE +661 -0
- package/NOTICE +11 -0
- package/README.md +411 -0
- package/README.zh-CN.md +411 -0
- package/dist/assets/DwgWorker-CuZJ5EUe.js +349 -0
- package/dist/assets/DwgWorker-CuZJ5EUe.js.map +1 -0
- package/dist/assets/index-C365l3i9.js +4161 -0
- package/dist/assets/index-C365l3i9.js.map +1 -0
- package/dist/cad-viewer.es.js +2992 -0
- package/dist/cad-viewer.es.js.map +1 -0
- package/dist/cad-viewer.umd.cjs +30 -0
- package/dist/cad-viewer.umd.cjs.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/style.css +1 -0
- package/dist/types/core/color.d.ts +21 -0
- package/dist/types/core/color.d.ts.map +1 -0
- package/dist/types/core/entity.d.ts +34 -0
- package/dist/types/core/entity.d.ts.map +1 -0
- package/dist/types/core/format.d.ts +8 -0
- package/dist/types/core/format.d.ts.map +1 -0
- package/dist/types/core/geometry.d.ts +17 -0
- package/dist/types/core/geometry.d.ts.map +1 -0
- package/dist/types/core/transform.d.ts +20 -0
- package/dist/types/core/transform.d.ts.map +1 -0
- package/dist/types/core/types.d.ts +195 -0
- package/dist/types/core/types.d.ts.map +1 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/loaders/CadLoaderRegistry.d.ts +15 -0
- package/dist/types/loaders/CadLoaderRegistry.d.ts.map +1 -0
- package/dist/types/loaders/dwf/DwfLoader.d.ts +15 -0
- package/dist/types/loaders/dwf/DwfLoader.d.ts.map +1 -0
- package/dist/types/loaders/dwg/DwgLoader.d.ts +15 -0
- package/dist/types/loaders/dwg/DwgLoader.d.ts.map +1 -0
- package/dist/types/loaders/dwg/DwgParser.d.ts +24 -0
- package/dist/types/loaders/dwg/DwgParser.d.ts.map +1 -0
- package/dist/types/loaders/dwg/DwgWorker.d.ts +2 -0
- package/dist/types/loaders/dwg/DwgWorker.d.ts.map +1 -0
- package/dist/types/loaders/dwg/DwgWorkerClient.d.ts +18 -0
- package/dist/types/loaders/dwg/DwgWorkerClient.d.ts.map +1 -0
- package/dist/types/loaders/dwg/dwgVersion.d.ts +9 -0
- package/dist/types/loaders/dwg/dwgVersion.d.ts.map +1 -0
- package/dist/types/loaders/dwg/libredwgWasmModuleProxy.d.ts +14 -0
- package/dist/types/loaders/dwg/libredwgWasmModuleProxy.d.ts.map +1 -0
- package/dist/types/loaders/dxf/DxfLoader.d.ts +12 -0
- package/dist/types/loaders/dxf/DxfLoader.d.ts.map +1 -0
- package/dist/types/loaders/index.d.ts +8 -0
- package/dist/types/loaders/index.d.ts.map +1 -0
- package/dist/types/viewer/CadCanvasRenderer.d.ts +142 -0
- package/dist/types/viewer/CadCanvasRenderer.d.ts.map +1 -0
- package/dist/types/viewer/CadViewer.d.ts +55 -0
- package/dist/types/viewer/CadViewer.d.ts.map +1 -0
- package/dist/types/viewer/CadWebGLRenderer.d.ts +69 -0
- package/dist/types/viewer/CadWebGLRenderer.d.ts.map +1 -0
- package/dist/wasm/libredwg-web.js +15 -0
- package/dist/wasm/libredwg-web.wasm +0 -0
- package/package.json +103 -0
package/README.md
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
# @flyfish-dev/cad-viewer
|
|
2
|
+
|
|
3
|
+
A professional, lightweight, extensible **frontend CAD viewer** for modern browsers.
|
|
4
|
+
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://www.npmjs.com/package/@flyfish-dev/cad-viewer)
|
|
7
|
+
|
|
8
|
+
**Live demo:** [cad-viewer-iys.pages.dev](https://cad-viewer-iys.pages.dev)
|
|
9
|
+
**Source:** [github.com/flyfish-dev/cad-viewer](https://github.com/flyfish-dev/cad-viewer)
|
|
10
|
+
|
|
11
|
+
The project provides a clean loader architecture for **DWG**, **DXF** and **DWFx/XPS-compatible DWF preview**, normalizes format-specific data into a common `CadDocument`, and renders it through a retained WebGL pipeline with a lightweight Canvas overlay for text and images. Files are read locally in the browser; the viewer does not upload drawings to a backend.
|
|
12
|
+
|
|
13
|
+
> DWG support uses `@mlightcad/libredwg-web` / LibreDWG WebAssembly. DXF support uses JavaScript parsing plus a built-in fallback parser. DWFx support parses XPS `FixedPage` vector pages. Classic `.dwf` WHIP/W2D/W3D streams are detected and reported clearly, but full classic DWF decoding still requires a dedicated WHIP decoder or DWF Toolkit/WASM implementation.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## What changed in 0.5.3
|
|
17
|
+
|
|
18
|
+
- Fixed DWG color fidelity for layer-indexed drawings. Indexed LibreDWG layers now resolve from ACI instead of the converter placeholder `0xffffff`, preventing monochrome-white output.
|
|
19
|
+
- Preserved DWG true-color values even when the RGB integer is in the ACI range, such as `0x0000ff`.
|
|
20
|
+
- Added BYBLOCK color inheritance for expanded INSERT/block entities.
|
|
21
|
+
|
|
22
|
+
## What changed in 0.5.2
|
|
23
|
+
|
|
24
|
+
- Fixed the noisy Vite build output where `@mlightcad/libredwg-web` printed a multi-megabyte `data:application/wasm;base64,...` warning.
|
|
25
|
+
- DWG worker builds now use the lean LibreDWG ESM wrapper and load `/wasm/libredwg-web.js` + `/wasm/libredwg-web.wasm` at runtime, avoiding duplicated inline wasm assets.
|
|
26
|
+
- `build:lib` now creates `dist/index.js` as a compatibility re-export for integrations that still request `/dist/index.js`.
|
|
27
|
+
- Vite dev mode now serves a small `/dist/index.js` compatibility shim that forwards stale demo pages to `/demo/main.ts`.
|
|
28
|
+
- `npm run preview` now builds the demo first, so clean checkouts do not fail because `dist-demo` is missing.
|
|
29
|
+
|
|
30
|
+
## What changed in 0.5
|
|
31
|
+
|
|
32
|
+
- The default rendering backend is now a **retained WebGL renderer**. CAD primitives are flattened once and uploaded to GPU buffers; pan/zoom updates only view uniforms.
|
|
33
|
+
- Added spatial indexing and viewport culling. Line, triangle and point batches are bucketed across the drawing bounds, so zoomed-in views submit only visible batches.
|
|
34
|
+
- Added large-drawing memory controls: coordinates are stored relative to the drawing center in `Float32Array`, colors are stored in `Uint8Array`, and temporary CPU arrays are released after upload.
|
|
35
|
+
- Text and images render in a separate overlay with minimum screen-height and maximum visible-label limits.
|
|
36
|
+
- `CadViewer` now supports `renderer: 'auto' | 'webgl' | 'canvas2d'`; `auto` prefers WebGL and falls back to Canvas2D.
|
|
37
|
+
- Demo now reports renderer backend, visible primitives and estimated GPU memory.
|
|
38
|
+
|
|
39
|
+
## What changed in 0.4
|
|
40
|
+
|
|
41
|
+
- DWG parsing now runs in a **dedicated Web Worker by default**, so LibreDWG WASM initialization and binary decoding no longer block pan/zoom/UI interactions.
|
|
42
|
+
- The worker keeps the LibreDWG WASM instance warm and reuses it across DWG loads.
|
|
43
|
+
- Added cancellable loading through `AbortSignal`, worker timeout support, progress events, and explicit worker asset configuration.
|
|
44
|
+
- Reduced DWG memory pressure by stripping raw parser objects from worker payloads unless `keepRaw: true` is explicitly enabled.
|
|
45
|
+
- Demo now includes a loading overlay, progress bar, cancel action and loader mode indicator.
|
|
46
|
+
- `viewer.destroy()` disposes canvas listeners and terminates owned DWG workers, which is safe for SPA route changes.
|
|
47
|
+
- Library exports `supportsDwgWorker` and `DwgWorkerClient` for advanced integrations.
|
|
48
|
+
|
|
49
|
+
## Features
|
|
50
|
+
|
|
51
|
+
- **Pure frontend viewer component**: `new CadViewer({ container })` or `new CadViewer({ canvas })`.
|
|
52
|
+
- **Loader registry**: DWG, DXF and DWF loaders are independent and replaceable.
|
|
53
|
+
- **DWG preview**: browser-local parsing through LibreDWG WebAssembly, executed in a Web Worker by default.
|
|
54
|
+
- **DXF preview**: JavaScript parser path with fallback support for common ASCII DXF `ENTITIES`.
|
|
55
|
+
- **DWF/DWFx preview**: DWFx/XPS 2D `FixedPage` rendering for paths, glyphs and images.
|
|
56
|
+
- **CAD color handling**: ACI, BYLAYER, BYBLOCK inheritance, DWG layer colors, true color, fill color, opacity and adaptive contrast.
|
|
57
|
+
- **High-performance WebGL viewport controls**: retained GPU buffers, spatial culling, zoom, pan, fit-to-view, cursor world coordinates and zoom percentage.
|
|
58
|
+
- **Professional demo UI**: drag-and-drop, compact toolbar, status strip, parse/render timing, entity summary and warnings.
|
|
59
|
+
- **Library + demo builds**: publishable npm package and Cloudflare Pages demo.
|
|
60
|
+
|
|
61
|
+
## Install
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npm install @flyfish-dev/cad-viewer
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
For local development from this repository:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npm install
|
|
71
|
+
npm run dev
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The DWG loader needs LibreDWG WASM assets in a public directory. This repository copies and validates them for the demo:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm run copy:wasm
|
|
78
|
+
npm run check:wasm
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The demo resolves `wasmPath` to an absolute URL before sending it to the worker. In your own app, prefer an absolute path or URL, for example `/wasm` or `new URL('wasm/', document.baseURI).href`. Avoid passing a worker-relative path such as `./wasm` unless it is resolved on the UI thread first.
|
|
82
|
+
|
|
83
|
+
When publishing the npm package, `build:lib` also copies these files into `dist/wasm` and exposes them as package subpaths. Applications still need to serve the `.wasm` from a public URL and pass that directory as `wasmPath`.
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
## Demo startup notes
|
|
87
|
+
|
|
88
|
+
Use Vite for the source demo:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npm install
|
|
92
|
+
npm run dev
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
For a production preview, use:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npm run preview
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Do not serve the source directory with a plain static server and expect TypeScript entries to run. If a stale page requests `/dist/index.js`, run `npm run build:lib` to create the compatibility entry, or use the Vite dev server above.
|
|
102
|
+
|
|
103
|
+
## Basic usage
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
import { CadViewer } from '@flyfish-dev/cad-viewer';
|
|
107
|
+
import '@flyfish-dev/cad-viewer/style.css';
|
|
108
|
+
|
|
109
|
+
const viewer = new CadViewer({
|
|
110
|
+
container: document.querySelector('#viewer')!,
|
|
111
|
+
renderer: 'auto', // WebGL first, Canvas2D fallback
|
|
112
|
+
wasmPath: new URL('wasm/', document.baseURI).href,
|
|
113
|
+
canvasOptions: {
|
|
114
|
+
background: '#05070d',
|
|
115
|
+
foreground: '#f8fafc',
|
|
116
|
+
contrastMode: 'adaptive',
|
|
117
|
+
minColorContrast: 2.45
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const input = document.querySelector<HTMLInputElement>('input[type=file]')!;
|
|
122
|
+
input.addEventListener('change', async () => {
|
|
123
|
+
const file = input.files?.[0];
|
|
124
|
+
if (!file) return;
|
|
125
|
+
await viewer.loadFile(file);
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
## WebGL rendering and performance model
|
|
131
|
+
|
|
132
|
+
The default `renderer: 'auto'` path attempts to create `CadWebGLRenderer` first. Instead of traversing every entity and rebuilding Canvas2D paths on every zoom, the renderer builds a retained scene once in `setDocument()`:
|
|
133
|
+
|
|
134
|
+
```text
|
|
135
|
+
CadDocument
|
|
136
|
+
↓
|
|
137
|
+
flatten blocks / curves / fills
|
|
138
|
+
↓
|
|
139
|
+
Float32Array positions + Uint8Array colors
|
|
140
|
+
↓
|
|
141
|
+
spatial GPU batches
|
|
142
|
+
↓
|
|
143
|
+
WebGL drawArrays with viewport culling
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Tunable options:
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
new CadViewer({
|
|
150
|
+
container,
|
|
151
|
+
renderer: 'auto', // force 'webgl' or 'canvas2d' when needed
|
|
152
|
+
canvasOptions: {
|
|
153
|
+
enableSpatialIndex: true,
|
|
154
|
+
spatialIndexCellCount: 96,
|
|
155
|
+
maxVerticesPerBatch: 32768,
|
|
156
|
+
maxCurveSegments: 72,
|
|
157
|
+
textMinPixelHeight: 4,
|
|
158
|
+
maxVisibleTextLabels: 2400,
|
|
159
|
+
powerPreference: 'high-performance',
|
|
160
|
+
preserveDrawingBuffer: false
|
|
161
|
+
},
|
|
162
|
+
onRenderStats(stats) {
|
|
163
|
+
console.log(stats.backend, stats.visiblePrimitiveCount, stats.gpuMemoryBytes);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
For very large drawings, lower `maxCurveSegments`, increase `spatialIndexCellCount`, and cap `maxVisibleTextLabels`.
|
|
169
|
+
|
|
170
|
+
## Worker-backed DWG parsing
|
|
171
|
+
|
|
172
|
+
`DwgLoader` uses a module Web Worker by default in browsers. The worker imports `@mlightcad/libredwg-web`, initializes LibreDWG WASM inside the worker thread, caches that WASM instance, decodes DWG bytes, normalizes the result into a structured-clone-safe `CadDocument`, and sends only the normalized scene back to the UI thread. Canvas rendering remains on the main thread.
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
const controller = new AbortController();
|
|
176
|
+
|
|
177
|
+
const viewer = new CadViewer({
|
|
178
|
+
container,
|
|
179
|
+
wasmPath: new URL('wasm/', document.baseURI).href,
|
|
180
|
+
useWorker: true,
|
|
181
|
+
workerTimeoutMs: 120_000,
|
|
182
|
+
onLoadProgress(progress) {
|
|
183
|
+
console.log(progress.phase, progress.message, progress.percent);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
await viewer.preloadDwg(); // optional: warm the worker before the first file
|
|
188
|
+
await viewer.loadFile(file, { signal: controller.signal });
|
|
189
|
+
|
|
190
|
+
// cancel a large DWG load
|
|
191
|
+
controller.abort();
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Advanced deployments can override the worker constructor when the bundler or CDN has a custom asset layout:
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
new CadViewer({
|
|
198
|
+
container,
|
|
199
|
+
wasmPath: new URL('wasm/', document.baseURI).href,
|
|
200
|
+
workerUrl: new URL('/assets/dwg-worker.js', window.location.origin)
|
|
201
|
+
});
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
The default package is worker-first. For non-browser runtimes, register a custom DWG loader instead of disabling workers.
|
|
205
|
+
|
|
206
|
+
## Component API
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
const viewer = new CadViewer({
|
|
210
|
+
container, // HTMLElement; creates a canvas inside
|
|
211
|
+
canvas, // optional existing HTMLCanvasElement
|
|
212
|
+
renderer: 'auto', // 'auto' | 'webgl' | 'canvas2d'
|
|
213
|
+
wasmPath: '/wasm', // LibreDWG WebAssembly asset path. Absolute URL/path recommended for workers
|
|
214
|
+
autoFit: true,
|
|
215
|
+
canvasOptions: {
|
|
216
|
+
background: '#05070d',
|
|
217
|
+
foreground: '#ffffff',
|
|
218
|
+
contrastMode: 'adaptive', // 'adaptive' | 'preserve'
|
|
219
|
+
minColorContrast: 2.45,
|
|
220
|
+
showPageBounds: true,
|
|
221
|
+
showUnsupportedMarkers: false,
|
|
222
|
+
trueColorByteOrder: 'rgb',
|
|
223
|
+
enableSpatialIndex: true,
|
|
224
|
+
spatialIndexCellCount: 96,
|
|
225
|
+
maxVerticesPerBatch: 32768,
|
|
226
|
+
maxCurveSegments: 72,
|
|
227
|
+
textMinPixelHeight: 4,
|
|
228
|
+
maxVisibleTextLabels: 2400
|
|
229
|
+
},
|
|
230
|
+
useWorker: true, // default for DWG
|
|
231
|
+
workerTimeoutMs: 0, // 0 = disabled
|
|
232
|
+
onLoadProgress(progress) {},
|
|
233
|
+
onLoad(result) {},
|
|
234
|
+
onError(error) {},
|
|
235
|
+
onRenderStats(stats) {},
|
|
236
|
+
onViewChange(event) {}
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
await viewer.loadFile(file);
|
|
240
|
+
await viewer.loadBuffer(arrayBuffer, 'drawing.dxf');
|
|
241
|
+
viewer.fit();
|
|
242
|
+
viewer.zoomIn();
|
|
243
|
+
viewer.zoomOut();
|
|
244
|
+
await viewer.preloadDwg(); // optional DWG worker/WASM warmup
|
|
245
|
+
viewer.setCanvasOptions({ background: '#f7f8fb', foreground: '#111827' });
|
|
246
|
+
viewer.clear();
|
|
247
|
+
viewer.destroy();
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Loader architecture
|
|
251
|
+
|
|
252
|
+
```text
|
|
253
|
+
File / ArrayBuffer
|
|
254
|
+
↓
|
|
255
|
+
CadLoaderRegistry
|
|
256
|
+
↓
|
|
257
|
+
DwgLoader | DxfLoader | DwfLoader | custom loader
|
|
258
|
+
↓
|
|
259
|
+
CadDocument
|
|
260
|
+
↓
|
|
261
|
+
CadWebGLRenderer | CadCanvasRenderer fallback
|
|
262
|
+
↓
|
|
263
|
+
WebGL preview + Canvas overlay
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Each loader returns a normalized `CadDocument`:
|
|
267
|
+
|
|
268
|
+
```ts
|
|
269
|
+
interface CadDocument {
|
|
270
|
+
format: 'dwg' | 'dxf' | 'dwf' | 'dwfx' | 'xps' | 'unknown';
|
|
271
|
+
layers: Record<string, CadLayer>;
|
|
272
|
+
blocks: Record<string, CadBlock>;
|
|
273
|
+
entities: CadEntity[];
|
|
274
|
+
pages?: CadPage[];
|
|
275
|
+
warnings: string[];
|
|
276
|
+
raw?: unknown;
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Register a custom loader:
|
|
281
|
+
|
|
282
|
+
```ts
|
|
283
|
+
viewer.registerLoader({
|
|
284
|
+
id: 'my-cad-format',
|
|
285
|
+
label: 'My CAD Format',
|
|
286
|
+
formats: ['unknown'],
|
|
287
|
+
accepts(input) {
|
|
288
|
+
return input.fileName?.endsWith('.cad') ?? false;
|
|
289
|
+
},
|
|
290
|
+
async load(input) {
|
|
291
|
+
return {
|
|
292
|
+
document: {
|
|
293
|
+
format: 'unknown',
|
|
294
|
+
layers: {},
|
|
295
|
+
blocks: {},
|
|
296
|
+
entities: [],
|
|
297
|
+
metadata: {},
|
|
298
|
+
warnings: []
|
|
299
|
+
},
|
|
300
|
+
bytes: input.buffer instanceof Uint8Array ? input.buffer.byteLength : 0,
|
|
301
|
+
elapsedMs: 0,
|
|
302
|
+
format: 'unknown',
|
|
303
|
+
warnings: []
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Format support
|
|
310
|
+
|
|
311
|
+
| Format | Loader | Coverage |
|
|
312
|
+
|---|---|---|
|
|
313
|
+
| DWG | `DwgLoader` | Uses LibreDWG WebAssembly. Rendering coverage depends on the entities exposed by LibreDWG conversion. |
|
|
314
|
+
| DXF | `DxfLoader` | Uses `dxf-parser` plus fallback parsing. Supports core entities, blocks/inserts, colors/layers, polylines, text, hatch boundaries and splines as preview polylines. |
|
|
315
|
+
| DWFx / XPS | `DwfLoader` | Parses ZIP/OPC packages and renders 2D `FixedPage` path/glyph/image content. |
|
|
316
|
+
| Classic DWF | `DwfLoader` detection | Detects WHIP/W2D/W3D package content and returns a clear unsupported error. Full classic DWF requires a dedicated WHIP decoder or DWF Toolkit/WASM. |
|
|
317
|
+
|
|
318
|
+
## Color handling
|
|
319
|
+
|
|
320
|
+
The color resolver follows CAD semantics instead of treating all numbers as RGB:
|
|
321
|
+
|
|
322
|
+
1. explicit CSS color or true color object,
|
|
323
|
+
2. explicit DWG true-color integer, including low RGB values such as `0x0000ff`,
|
|
324
|
+
3. entity ACI (`colorIndex`, `colorNumber`, `color` in `1..255`),
|
|
325
|
+
4. BYBLOCK inheritance (`0`) when expanding INSERT/block geometry,
|
|
326
|
+
5. BYLAYER lookup (`256` / unset),
|
|
327
|
+
6. viewer foreground fallback.
|
|
328
|
+
|
|
329
|
+
Layer colors prefer a valid ACI index when a converter also exposes a placeholder RGB value. ACI `7` is foreground-dependent: it renders light on dark canvas and dark on light canvas. With `contrastMode: 'adaptive'`, colors too close to the current canvas background are adjusted just enough to stay readable. Use `contrastMode: 'preserve'` when exact plotted colors are more important than screen readability.
|
|
330
|
+
|
|
331
|
+
If a particular converter exposes true-color integers in BGR order:
|
|
332
|
+
|
|
333
|
+
```ts
|
|
334
|
+
new CadViewer({ canvasOptions: { trueColorByteOrder: 'bgr' } });
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Development
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
npm install
|
|
341
|
+
npm run dev # run the demo
|
|
342
|
+
npm run typecheck # TypeScript validation
|
|
343
|
+
npm run build # library + demo
|
|
344
|
+
npm run preview # preview built demo
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## npm publishing
|
|
348
|
+
|
|
349
|
+
1. Build and inspect the package:
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
npm run build:lib
|
|
353
|
+
npm run pack:dry
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
2. Publish:
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
npm login
|
|
360
|
+
npm publish --access public
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
The package also exposes:
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
npm run release:npm
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
## Cloudflare Pages publishing
|
|
370
|
+
|
|
371
|
+
Direct upload with Wrangler. The repository includes `public/_headers`, so Cloudflare Pages serves `.wasm` as `application/wasm` and caches it long-term:
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
npm install
|
|
375
|
+
npm run build:demo
|
|
376
|
+
npx wrangler pages deploy dist-demo --project-name cad-viewer
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
Or use the included script:
|
|
380
|
+
|
|
381
|
+
```bash
|
|
382
|
+
npm run deploy:pages
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
For GitHub Actions, configure repository secrets:
|
|
386
|
+
|
|
387
|
+
```text
|
|
388
|
+
CLOUDFLARE_API_TOKEN
|
|
389
|
+
CLOUDFLARE_ACCOUNT_ID
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
The workflow is included at `.github/workflows/pages.yml`.
|
|
393
|
+
|
|
394
|
+
## Repository layout
|
|
395
|
+
|
|
396
|
+
```text
|
|
397
|
+
src/
|
|
398
|
+
core/ shared format detection, colors, geometry, transforms, normalized types
|
|
399
|
+
loaders/ DwgLoader, DxfLoader, DwfLoader and CadLoaderRegistry
|
|
400
|
+
viewer/ CadViewer component and Canvas renderer
|
|
401
|
+
demo/ professional Vite demo UI
|
|
402
|
+
docs/ English and Chinese architecture / format notes
|
|
403
|
+
scripts/ clean and LibreDWG WASM copy helpers
|
|
404
|
+
public/wasm/ demo WASM asset output directory
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
## License
|
|
408
|
+
|
|
409
|
+
AGPL-3.0-only. This is a strict copyleft license: if you distribute modified versions or offer modified versions over a network, review your source-code disclosure obligations carefully.
|
|
410
|
+
|
|
411
|
+
The default DWG loader depends on `@mlightcad/libredwg-web`, which is GPL-3.0-only. For closed-source commercial use, replace the DWG loader with a properly licensed parser/converter and review all dependency licenses.
|