gerbers-renderer 0.1.2 โ 0.1.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/README.md +193 -117
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,178 +1,254 @@
|
|
|
1
1
|
# gerbers-renderer
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
Render PCB
|
|
3
|
+
Pure frontend Gerber rendering for the web.
|
|
4
|
+
Render PCB Gerber bundles (`.zip`, `.rar`) directly in the browser with zero backend, zero native dependencies.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
๐ View Top / Bottom copper, mask, silkscreen, drills
|
|
8
|
-
๐ Pan, zoom, fit, grid
|
|
9
|
-
๐ Download the original Gerbers ZIP
|
|
6
|
+
Designed for:
|
|
10
7
|
|
|
11
|
-
|
|
8
|
+
- Web apps
|
|
9
|
+
- Browser extensions
|
|
10
|
+
- CI previews
|
|
11
|
+
- Manufacturing portals
|
|
12
|
+
- DFM tools
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
- Accepts standard gerbers.zip exports
|
|
15
|
-
- Automatic layer classification
|
|
16
|
-
- Correct board masking and clipping
|
|
17
|
-
- Top / Bottom view toggle
|
|
18
|
-
- Grid overlay (mm / inch)
|
|
19
|
-
- Designed to embed into any website
|
|
20
|
-
- No framework dependency (not React/Vue/etc.)
|
|
14
|
+
## Features
|
|
21
15
|
|
|
22
|
-
|
|
16
|
+
- ๐ง Gerber bundle detection (not just โtry and failโ)
|
|
17
|
+
- ๐ฆ Supports `.zip` and `.rar` archives (browser-side)
|
|
18
|
+
- ๐จ 2D SVG-based board viewer
|
|
19
|
+
- ๐งฉ Drop-in viewer that mounts into any DOM node
|
|
20
|
+
- ๐งช Typed, deterministic render results
|
|
21
|
+
- ๐งผ No backend, no workers unless needed
|
|
22
|
+
- โก Vite, React, vanilla JS friendly
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
23
25
|
|
|
24
|
-
### Install from npm (recommended)
|
|
25
26
|
```bash
|
|
26
27
|
npm install gerbers-renderer
|
|
27
28
|
```
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
## Quick start (minimal)
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { renderGerbers, createBoardViewer } from "gerbers-renderer";
|
|
34
|
+
|
|
35
|
+
const viewer = createBoardViewer(document.getElementById("pcb")!);
|
|
36
|
+
|
|
37
|
+
const file = input.files[0];
|
|
38
|
+
const buffer = await file.arrayBuffer();
|
|
39
|
+
|
|
40
|
+
const result = await renderGerbers(buffer, {
|
|
41
|
+
archiveWorkerUrl: "/libarchive-worker-bundle.js", // required for .rar
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
viewer.setData({
|
|
45
|
+
boardGeom: result.boardGeom,
|
|
46
|
+
layers: result.layers,
|
|
47
|
+
});
|
|
48
|
+
viewer.fit();
|
|
35
49
|
```
|
|
36
50
|
|
|
37
|
-
|
|
51
|
+
Always call `result.revoke()` when replacing a render.
|
|
52
|
+
|
|
53
|
+
## Live demo
|
|
38
54
|
|
|
39
|
-
```
|
|
40
|
-
|
|
55
|
+
```bash
|
|
56
|
+
git clone https://github.com/asappcb/gerbers-renderer
|
|
57
|
+
npm install
|
|
58
|
+
npm run dev
|
|
41
59
|
```
|
|
42
60
|
|
|
43
|
-
|
|
61
|
+
Open:
|
|
62
|
+
๐ http://localhost:5173/demo/
|
|
63
|
+
|
|
64
|
+
## Supported input formats
|
|
65
|
+
|
|
66
|
+
| Format | Supported | Notes |
|
|
67
|
+
|---|---:|---|
|
|
68
|
+
| `.zip` | โ
| Native via JSZip |
|
|
69
|
+
| `.rar` | โ
| Via libarchive.js (WASM) |
|
|
70
|
+
| `.7z` | โ (future) | Detection works |
|
|
71
|
+
| `.tar` | โ (future) | Detection works |
|
|
72
|
+
| Directory | โ
| Use `renderGerbersFiles` |
|
|
73
|
+
|
|
74
|
+
## Gerber bundle detection
|
|
75
|
+
|
|
76
|
+
Before rendering, you can detect whether an input is actually a Gerber bundle.
|
|
44
77
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
78
|
+
```typescript
|
|
79
|
+
import { detectGerberBundle } from "gerbers-renderer";
|
|
80
|
+
|
|
81
|
+
const result = await detectGerberBundle(buffer);
|
|
82
|
+
|
|
83
|
+
if (!result.isGerber) {
|
|
84
|
+
console.log("Not a Gerber bundle:", result.reasons);
|
|
85
|
+
}
|
|
49
86
|
```
|
|
50
87
|
|
|
51
|
-
**JavaScript / TypeScript**
|
|
52
88
|
```typescript
|
|
53
|
-
|
|
89
|
+
type GerberDetectResult = {
|
|
90
|
+
isGerber: boolean;
|
|
91
|
+
archiveType: "zip" | "rar" | "7z" | "tar" | "directory" | "single-file" | "unknown";
|
|
92
|
+
confidence: number; // 0.0 โ 1.0
|
|
93
|
+
reasons: string[];
|
|
94
|
+
files?: string[];
|
|
95
|
+
};
|
|
96
|
+
```
|
|
54
97
|
|
|
55
|
-
|
|
56
|
-
const host = document.getElementById("viewer")!;
|
|
98
|
+
## Rendering APIs
|
|
57
99
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
100
|
+
### `renderGerbers(...)` (recommended)
|
|
101
|
+
|
|
102
|
+
Single high-level entrypoint.
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
renderGerbers(
|
|
106
|
+
input: ArrayBuffer | Uint8Array,
|
|
107
|
+
options?: {
|
|
108
|
+
archiveWorkerUrl?: string; // required for rar
|
|
67
109
|
}
|
|
68
|
-
|
|
110
|
+
): Promise<RenderResult>
|
|
111
|
+
```
|
|
69
112
|
|
|
70
|
-
|
|
71
|
-
let lastZip: File | null = null;
|
|
113
|
+
Handles:
|
|
72
114
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
115
|
+
- Archive detection
|
|
116
|
+
- Unpacking
|
|
117
|
+
- Validation
|
|
118
|
+
- Rendering
|
|
76
119
|
|
|
77
|
-
|
|
78
|
-
if (lastRender) lastRender.revoke();
|
|
120
|
+
### `renderGerbersZip(...)`
|
|
79
121
|
|
|
80
|
-
|
|
81
|
-
lastRender = out;
|
|
122
|
+
Zip-only convenience wrapper.
|
|
82
123
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
layers: out.layers
|
|
86
|
-
});
|
|
87
|
-
});
|
|
124
|
+
```typescript
|
|
125
|
+
renderGerbersZip(input: File | Blob | ArrayBuffer | Uint8Array)
|
|
88
126
|
```
|
|
89
127
|
|
|
90
|
-
|
|
128
|
+
### `renderGerbersFiles(...)`
|
|
91
129
|
|
|
92
|
-
|
|
130
|
+
Lowest-level API if you already have files.
|
|
93
131
|
|
|
94
|
-
|
|
132
|
+
```typescript
|
|
133
|
+
renderGerbersFiles(
|
|
134
|
+
files: Record<string, Uint8Array>
|
|
135
|
+
)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Viewer
|
|
95
139
|
|
|
96
|
-
|
|
140
|
+
Create a drop-in board viewer:
|
|
97
141
|
|
|
98
|
-
**Returns:**
|
|
99
142
|
```typescript
|
|
100
|
-
{
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
heightMm: number;
|
|
104
|
-
},
|
|
105
|
-
layers: {
|
|
106
|
-
top_copper?: string;
|
|
107
|
-
bottom_copper?: string;
|
|
108
|
-
top_silk?: string;
|
|
109
|
-
bottom_silk?: string;
|
|
110
|
-
top_mask?: string;
|
|
111
|
-
bottom_mask?: string;
|
|
112
|
-
drills?: string;
|
|
113
|
-
top_board_mask?: string;
|
|
114
|
-
bottom_board_mask?: string;
|
|
143
|
+
const viewer = createBoardViewer(container, {
|
|
144
|
+
onDownload: () => {
|
|
145
|
+
/* optional */
|
|
115
146
|
},
|
|
116
|
-
|
|
117
|
-
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
viewer.setData({
|
|
150
|
+
boardGeom,
|
|
151
|
+
layers,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
viewer.setSideMode("top"); // "top" | "bottom"
|
|
155
|
+
viewer.fit();
|
|
118
156
|
```
|
|
119
157
|
|
|
120
|
-
|
|
158
|
+
The viewer supports:
|
|
121
159
|
|
|
122
|
-
|
|
160
|
+
- Pan / zoom
|
|
161
|
+
- Layer toggling
|
|
162
|
+
- Top / bottom switching
|
|
163
|
+
- Download hook (original Gerbers)
|
|
123
164
|
|
|
124
|
-
|
|
165
|
+
## Return value
|
|
125
166
|
|
|
126
|
-
|
|
167
|
+
All render functions return a deterministic object:
|
|
127
168
|
|
|
128
169
|
```typescript
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
170
|
+
type RenderResult = {
|
|
171
|
+
boardGeom: BoardGeom;
|
|
172
|
+
layers: ViewerLayers;
|
|
173
|
+
revoke: () => void; // revoke blob URLs
|
|
174
|
+
};
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Always call `revoke()` when replacing a render.
|
|
178
|
+
|
|
179
|
+
## `.rar` support (important)
|
|
180
|
+
|
|
181
|
+
To support `.rar` archives, you must host the libarchive worker bundle.
|
|
182
|
+
|
|
183
|
+
Setup
|
|
184
|
+
|
|
185
|
+
Copy:
|
|
186
|
+
|
|
187
|
+
```text
|
|
188
|
+
node_modules/libarchive.js/dist/worker-bundle.js
|
|
132
189
|
```
|
|
133
190
|
|
|
134
|
-
|
|
135
|
-
- pan / zoom / fit
|
|
136
|
-
- Top / Bottom switching
|
|
137
|
-
- layer visibility
|
|
138
|
-
- board clipping mask
|
|
191
|
+
To:
|
|
139
192
|
|
|
140
|
-
|
|
193
|
+
```text
|
|
194
|
+
public/libarchive-worker-bundle.js
|
|
195
|
+
```
|
|
141
196
|
|
|
142
|
-
|
|
197
|
+
Then pass:
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
renderGerbers(buffer, {
|
|
201
|
+
archiveWorkerUrl: "/libarchive-worker-bundle.js",
|
|
202
|
+
});
|
|
203
|
+
```
|
|
143
204
|
|
|
144
|
-
|
|
205
|
+
ZIP users do not pay this cost.
|
|
145
206
|
|
|
146
|
-
|
|
207
|
+
## Error handling
|
|
147
208
|
|
|
148
|
-
|
|
149
|
-
- download the original gerbers.zip
|
|
150
|
-
- export SVG layers
|
|
151
|
-
- export screenshots
|
|
152
|
-
- pipe into manufacturing workflows
|
|
209
|
+
Errors are typed and structured.
|
|
153
210
|
|
|
154
|
-
|
|
211
|
+
```typescript
|
|
212
|
+
class GerberError extends Error {
|
|
213
|
+
code:
|
|
214
|
+
| "NOT_AN_ARCHIVE"
|
|
215
|
+
| "UNSUPPORTED_ARCHIVE"
|
|
216
|
+
| "NOT_GERBER"
|
|
217
|
+
| "MISSING_LAYERS"
|
|
218
|
+
| "PARSE_ERROR";
|
|
219
|
+
details?: any;
|
|
220
|
+
}
|
|
221
|
+
```
|
|
155
222
|
|
|
156
|
-
|
|
223
|
+
Always catch and inspect `error.code` in UI or CI.
|
|
157
224
|
|
|
158
|
-
|
|
159
|
-
- Frontend-only by design
|
|
160
|
-
- No assumptions about backend or manufacturing
|
|
161
|
-
- Safe to embed anywhere
|
|
162
|
-
- Easy to extend
|
|
225
|
+
## What this is not
|
|
163
226
|
|
|
164
|
-
|
|
227
|
+
- โ Not a CAM tool
|
|
228
|
+
- โ Not a DRC / DFM engine
|
|
229
|
+
- โ Not a backend renderer
|
|
165
230
|
|
|
166
|
-
|
|
231
|
+
This library is intentionally focused on fast, accurate visualization.
|
|
167
232
|
|
|
168
|
-
|
|
169
|
-
- Not a fabrication quote system
|
|
170
|
-
- Not a replacement for CAM software
|
|
233
|
+
## Roadmap
|
|
171
234
|
|
|
172
|
-
|
|
235
|
+
- 7z / tar unpacking
|
|
236
|
+
- Inner-layer rendering
|
|
237
|
+
- Canvas renderer
|
|
238
|
+
- WASM-only core split
|
|
239
|
+
- Headless CI validation mode
|
|
173
240
|
|
|
174
|
-
##
|
|
241
|
+
## License
|
|
175
242
|
|
|
176
243
|
MIT
|
|
177
244
|
|
|
178
|
-
|
|
245
|
+
## Why this exists
|
|
246
|
+
|
|
247
|
+
Most Gerber viewers:
|
|
248
|
+
|
|
249
|
+
- require servers
|
|
250
|
+
- are untyped
|
|
251
|
+
- break in browsers
|
|
252
|
+
- silently mis-detect archives
|
|
253
|
+
|
|
254
|
+
gerbers-renderer is designed from first principles for modern web tooling.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gerbers-renderer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "A frontend-only Gerber viewer for rendering PCB Gerbers directly in the browser.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -47,7 +47,8 @@
|
|
|
47
47
|
},
|
|
48
48
|
"homepage": "https://github.com/asappcb/gerbers-renderer#readme",
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"jszip": "^3.10.1"
|
|
50
|
+
"jszip": "^3.10.1",
|
|
51
|
+
"libarchive.js": "^2.0.2"
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|
|
53
54
|
"@types/jszip": "^3.4.0",
|