gerbers-renderer 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.
@@ -0,0 +1,4 @@
1
+ export { renderGerbersZip } from './render/renderGerbersZip';
2
+ export { createBoardViewer, type BoardViewerOptions } from './viewer/BoardViewer';
3
+ export type { RenderResult } from './render/renderGerbersZip';
4
+ export type { BoardViewer, BoardGeom, ViewerLayers } from './viewer/types';
@@ -0,0 +1,47 @@
1
+ import { ZipEntry } from './unzip';
2
+ export type LayerRole = "top_copper" | "bottom_copper" | "inner_copper" | "top_mask" | "bottom_mask" | "top_silk" | "bottom_silk" | "outline" | "mechanical" | "unknown";
3
+ export interface LayerHint {
4
+ /** Exact or suffix match for filenames, for example "myboard-F_Cu.gbr" */
5
+ pattern: string;
6
+ role: LayerRole;
7
+ }
8
+ /**
9
+ * Optional hints that the caller can pass in to override or refine classification.
10
+ */
11
+ export interface LayerHints {
12
+ hints: LayerHint[];
13
+ }
14
+ /**
15
+ * Normalized representation of a Gerber like file from the zip.
16
+ */
17
+ export interface ClassifiedGerberFile {
18
+ name: string;
19
+ role: LayerRole;
20
+ rawEntry: ZipEntry;
21
+ /**
22
+ * Lazily read and normalized text content.
23
+ * This calls normalizeGerberText under the hood.
24
+ */
25
+ getText: () => Promise<string>;
26
+ }
27
+ /**
28
+ * Normalized representation of a drill file from the zip.
29
+ */
30
+ export interface ClassifiedDrillFile {
31
+ name: string;
32
+ rawEntry: ZipEntry;
33
+ /**
34
+ * Lazily read and normalized text content.
35
+ * This calls normalizeDrillText under the hood.
36
+ */
37
+ getText: () => Promise<string>;
38
+ }
39
+ export interface ClassifiedFiles {
40
+ gerbers: ClassifiedGerberFile[];
41
+ drills: ClassifiedDrillFile[];
42
+ ignored: ZipEntry[];
43
+ }
44
+ /**
45
+ * Classify zip entries into Gerber layers, drill files, and ignored files.
46
+ */
47
+ export declare function classifyFiles(entries: ZipEntry[], hints?: LayerHints): ClassifiedFiles;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Normalize generic text file content coming from zip entries:
3
+ * - Strip UTF-8 BOM if present
4
+ * - Normalize line endings to "\n"
5
+ * - Trim leading and trailing blank lines
6
+ */
7
+ export declare function normalizeTextContent(raw: string): string;
8
+ /**
9
+ * Normalize Gerber specific content if needed.
10
+ * Currently just uses generic normalization, but this is the extension point
11
+ * for future format specific tweaks.
12
+ */
13
+ export declare function normalizeGerberText(raw: string): string;
14
+ /**
15
+ * Normalize Excellon drill file content if needed.
16
+ * Currently just uses generic normalization.
17
+ */
18
+ export declare function normalizeDrillText(raw: string): string;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * A single entry inside the unzipped gerbers.zip
3
+ */
4
+ export interface ZipEntry {
5
+ /** Normalized path style name, always forward slashes */
6
+ name: string;
7
+ /** Read entry as UTF-8 text */
8
+ text: () => Promise<string>;
9
+ /** Read entry as ArrayBuffer */
10
+ arrayBuffer: () => Promise<ArrayBuffer>;
11
+ }
12
+ /**
13
+ * Accepts a File, Blob, or ArrayBuffer and returns a list of ZipEntry helpers.
14
+ */
15
+ export declare function unzipGerbersZip(input: File | Blob | ArrayBuffer): Promise<ZipEntry[]>;
@@ -0,0 +1,22 @@
1
+ import { DrillHole } from '../types/pcb-model';
2
+ /**
3
+ * Parsed drill data for a single Excellon file.
4
+ * This will be fed into the geometry pipeline.
5
+ */
6
+ export interface ParsedDrillData {
7
+ name: string;
8
+ holes: DrillHole[];
9
+ }
10
+ /**
11
+ * Very naive Excellon drill parser.
12
+ *
13
+ * This is intentionally simple and conservative:
14
+ * - It understands basic tool definitions like "T01C0.300"
15
+ * - It understands coordinate lines like "X012345Y067890"
16
+ * - It assumes units are already inches or mm as used in the file, and does
17
+ * not attempt unit conversion or integer format decoding.
18
+ *
19
+ * For now, you can treat this as a stub and gradually swap in a robust parser
20
+ * if needed. At minimum, it gives you some real hole locations to play with.
21
+ */
22
+ export declare function parseDrillFile(name: string, content: string): ParsedDrillData;
@@ -0,0 +1,51 @@
1
+ import { Vec2 } from '../types/pcb-model';
2
+ import { LayerRole } from '../io/file-classifier';
3
+ /**
4
+ * Primitive types used by the geometry pipeline. These are what
5
+ * polygonizer.ts consumes.
6
+ */
7
+ export interface GerberPrimitiveTrack {
8
+ start: Vec2;
9
+ end: Vec2;
10
+ width: number;
11
+ }
12
+ export interface GerberPrimitiveArc {
13
+ start: Vec2;
14
+ end: Vec2;
15
+ center: Vec2;
16
+ clockwise: boolean;
17
+ width: number;
18
+ }
19
+ export interface GerberPrimitiveFlash {
20
+ position: Vec2;
21
+ diameterMm: number;
22
+ }
23
+ export interface GerberPrimitiveRegion {
24
+ boundary: Vec2[];
25
+ holes: Vec2[][];
26
+ }
27
+ export interface GerberPrimitives {
28
+ tracks: GerberPrimitiveTrack[];
29
+ arcs: GerberPrimitiveArc[];
30
+ flashes: GerberPrimitiveFlash[];
31
+ regions: GerberPrimitiveRegion[];
32
+ }
33
+ export interface GerberPrimitiveFlash {
34
+ position: Vec2;
35
+ diameterMm: number;
36
+ shape: string;
37
+ widthMm?: number;
38
+ heightMm?: number;
39
+ }
40
+ /**
41
+ * Parse a Gerber file into drawing primitives.
42
+ *
43
+ * This is a practical, not spec complete parser:
44
+ * - Handles %FS, %MO, %AD for simple circular apertures (C)
45
+ * - Handles D01 (draw), D02 (move), D03 (flash)
46
+ * - Handles G36/G37 for filled regions with multiple contours
47
+ * - Ignores arcs (G02/G03) for now
48
+ *
49
+ * It is good enough to visualize traces and pads for many KiCad/JLC style Gerbers.
50
+ */
51
+ export declare function parseGerberFile(name: string, content: string, _role: LayerRole | string): GerberPrimitives;
@@ -0,0 +1,11 @@
1
+ export type Classified = Partial<{
2
+ top_copper: string;
3
+ bottom_copper: string;
4
+ top_mask: string;
5
+ bottom_mask: string;
6
+ top_silk: string;
7
+ bottom_silk: string;
8
+ drills: string;
9
+ outline: string;
10
+ }>;
11
+ export declare function classifyLayerNames(names: string[]): Classified;
@@ -0,0 +1,7 @@
1
+ import { BoardGeom, ViewerLayers } from '../viewer/types';
2
+ export type RenderResult = {
3
+ boardGeom: BoardGeom;
4
+ layers: ViewerLayers;
5
+ revoke: () => void;
6
+ };
7
+ export declare function renderGerbersZip(file: File): Promise<RenderResult>;
Binary file
Binary file
Binary file
@@ -0,0 +1,19 @@
1
+ import { LayerHints } from '../io/file-classifier';
2
+ export interface LoadFromZipOptions {
3
+ /**
4
+ * Board thickness in millimeters.
5
+ * Used when the geometry pipeline builds the 3D model.
6
+ */
7
+ boardThicknessMm?: number;
8
+ /**
9
+ * Optional hints to override layer role detection based on filenames.
10
+ */
11
+ layerHints?: LayerHints;
12
+ }
13
+ /**
14
+ * Options used when you eventually hook this into a 3D viewer.
15
+ * For now, only LoadFromZipOptions is used by the pipeline.
16
+ */
17
+ export interface RenderFromZipOptions extends LoadFromZipOptions {
18
+ canvas?: HTMLCanvasElement;
19
+ }
@@ -0,0 +1,32 @@
1
+ export type PcbSide = "top" | "bottom";
2
+ export type PcbLayerKind = "copper" | "soldermask" | "silkscreen" | "outline";
3
+ export interface Vec2 {
4
+ x: number;
5
+ y: number;
6
+ }
7
+ export interface Polygon {
8
+ outer: Vec2[];
9
+ holes: Vec2[][];
10
+ }
11
+ export interface LayerGeometry {
12
+ name: string;
13
+ side: PcbSide | null;
14
+ kind: PcbLayerKind;
15
+ polygons: Polygon[];
16
+ }
17
+ export interface DrillHole {
18
+ x: number;
19
+ y: number;
20
+ diameter: number;
21
+ plated: boolean;
22
+ }
23
+ export interface PcbModelGeometry {
24
+ widthMm: number;
25
+ heightMm: number;
26
+ thicknessMm: number;
27
+ copperLayers: LayerGeometry[];
28
+ maskLayers: LayerGeometry[];
29
+ silkLayers: LayerGeometry[];
30
+ outline: LayerGeometry | null;
31
+ drills: DrillHole[];
32
+ }
@@ -0,0 +1,5 @@
1
+ import { BoardViewer } from './types';
2
+ export type BoardViewerOptions = {
3
+ onDownload?: () => void;
4
+ };
5
+ export declare function createBoardViewer(host: HTMLElement, opts?: BoardViewerOptions): BoardViewer;
@@ -0,0 +1,34 @@
1
+ export type BoardGeom = {
2
+ board: {
3
+ width_in: number;
4
+ height_in: number;
5
+ mm_bounds: {
6
+ min_x_mm: number;
7
+ min_y_mm: number;
8
+ max_x_mm: number;
9
+ max_y_mm: number;
10
+ };
11
+ };
12
+ };
13
+ export type ViewerLayers = Partial<{
14
+ top_copper: string;
15
+ bottom_copper: string;
16
+ top_mask: string;
17
+ bottom_mask: string;
18
+ top_silk: string;
19
+ bottom_silk: string;
20
+ drills: string;
21
+ vias: string;
22
+ top_board_mask: string;
23
+ bottom_board_mask: string;
24
+ }>;
25
+ export type ViewerSideMode = "top" | "bottom";
26
+ export type BoardViewer = {
27
+ setData: (data: {
28
+ boardGeom: BoardGeom;
29
+ layers: ViewerLayers;
30
+ }) => void;
31
+ setSideMode: (mode: ViewerSideMode) => void;
32
+ fit: () => void;
33
+ dispose: () => void;
34
+ };
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "gerbers-renderer",
3
+ "version": "0.1.0",
4
+ "description": "A frontend-only Gerber viewer for rendering PCB Gerbers directly in the browser.",
5
+ "private": false,
6
+ "type": "module",
7
+ "main": "./dist/gerbers-renderer.umd.js",
8
+ "module": "./dist/gerbers-renderer.es.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/gerbers-renderer.es.js",
13
+ "require": "./dist/gerbers-renderer.umd.js"
14
+ }
15
+ },
16
+ "unpkg": "./dist/gerbers-renderer.umd.js",
17
+ "jsdelivr": "./dist/gerbers-renderer.umd.js",
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "scripts": {
22
+ "dev": "vite",
23
+ "build": "vite build",
24
+ "preview": "vite preview"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/asappcb/gerbers-renderer.git"
29
+ },
30
+ "keywords": [
31
+ "pcb",
32
+ "gerber",
33
+ "excellon",
34
+ "viewer",
35
+ "renderer",
36
+ "frontend",
37
+ "browser",
38
+ "svg",
39
+ "electronics"
40
+ ],
41
+ "author": "",
42
+ "license": "MIT",
43
+ "bugs": {
44
+ "url": "https://github.com/asappcb/gerbers-renderer/issues"
45
+ },
46
+ "homepage": "https://github.com/asappcb/gerbers-renderer#readme",
47
+ "dependencies": {
48
+ "jszip": "^3.10.1"
49
+ },
50
+ "devDependencies": {
51
+ "@types/jszip": "^3.4.0",
52
+ "@types/node": "^24.10.1",
53
+ "@types/three": "^0.181.0",
54
+ "ts-node": "^10.9.2",
55
+ "typescript": "^5.9.3",
56
+ "vite": "^7.2.7",
57
+ "vite-plugin-dts": "^4.5.4"
58
+ }
59
+ }