diff --git a/biome.json b/biome.json index 39c0c728..3470a439 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,8 @@ { "$schema": "https://biomejs.dev/schemas/1.7.3/schema.json", + "files": { + "ignore": ["gallery/**"] + }, "organizeImports": { "enabled": true }, diff --git a/gallery/generate-grid-content.ts b/gallery/generate-grid-content.ts index c37defa9..753a55c5 100644 --- a/gallery/generate-grid-content.ts +++ b/gallery/generate-grid-content.ts @@ -1,5 +1,5 @@ -import path from "path" -import fs from "fs" +import path from "node:path" +import fs from "node:fs" const snapshotsDir = path.join(__dirname, "..", "tests", "__snapshots__") const outputFile = path.join(__dirname, "content.ts") diff --git a/gallery/index.tsx b/gallery/index.tsx index 5c72f354..afc4a95d 100644 --- a/gallery/index.tsx +++ b/gallery/index.tsx @@ -1,5 +1,6 @@ import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" -import React, { useState, useCallback } from "react" +import type React from "react" +import { useState, useCallback } from "react" import ReactDOM from "react-dom/client" import { fp } from "src/footprinter" // @ts-ignore data is built during CI diff --git a/src/fn/axial.ts b/src/fn/axial.ts index bc93e358..c20327ad 100644 --- a/src/fn/axial.ts +++ b/src/fn/axial.ts @@ -6,7 +6,7 @@ import { } from "circuit-json" import { passive, type PassiveDef } from "../helpers/passive-fn" import { z } from "zod" -import { platedhole } from "src/helpers/platedhole" +import { platedhole } from "../helpers/platedhole" import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/bga.ts b/src/fn/bga.ts index 93a3fecd..55e3f9f5 100644 --- a/src/fn/bga.ts +++ b/src/fn/bga.ts @@ -5,11 +5,11 @@ import { ALPHABET } from "../helpers/zod/ALPHABET" import { z } from "zod" import { base_def } from "../helpers/zod/base_def" import { length, distance } from "circuit-json" -import { dim2d } from "src/helpers/zod/dim-2d" -import { function_call } from "src/helpers/zod/function-call" -import type { NowDefined } from "src/helpers/zod/now-defined" -import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" -import { type PcbSilkscreenPath } from "circuit-json" +import { dim2d } from "../helpers/zod/dim-2d" +import { function_call } from "../helpers/zod/function-call" +import type { NowDefined } from "../helpers/zod/now-defined" +import { type SilkscreenRef, silkscreenRef } from "../helpers/silkscreenRef" +import type { PcbSilkscreenPath } from "circuit-json" export const bga_def = base_def .extend({ @@ -136,7 +136,6 @@ export const bga = ( pin_x = grid.x - 1 - x pin_y = y break - case "tl": default: // Keep original x,y for pin numbering break @@ -201,7 +200,6 @@ export const bga = ( { x: edgeX, y: edgeY }, // Back to start ] break - case "tl": default: markerRoute = [ { x: -edgeX, y: edgeY }, // Start at corner diff --git a/src/fn/breakoutheaders.ts b/src/fn/breakoutheaders.ts index 700c47c2..ec0dd9cd 100644 --- a/src/fn/breakoutheaders.ts +++ b/src/fn/breakoutheaders.ts @@ -6,8 +6,8 @@ import { } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" -import { platedhole } from "src/helpers/platedhole" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" +import { platedhole } from "../helpers/platedhole" import { base_def } from "../helpers/zod/base_def" export const breakoutheaders_def = base_def.extend({ diff --git a/src/fn/dfn.ts b/src/fn/dfn.ts index 08e76bb6..b729af7e 100644 --- a/src/fn/dfn.ts +++ b/src/fn/dfn.ts @@ -5,10 +5,10 @@ import { type SoicInput, getCcwSoicCoords, } from "./soic" -import { rectpad } from "src/helpers/rectpad" +import { rectpad } from "../helpers/rectpad" import { z } from "zod" -import { CORNERS } from "src/helpers/corner" -import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" +import { CORNERS } from "../helpers/corner" +import { type SilkscreenRef, silkscreenRef } from "../helpers/silkscreenRef" export const dfn_def = extendSoicDef({}) @@ -32,7 +32,13 @@ export const dfn = ( widthincludeslegs: true, }) pads.push( - rectpad(i + 1, x, y, parameters.pl ?? "1mm", parameters.pw ?? "0.6mm"), + rectpad( + i + 1, + x, + y, + Number.parseFloat(parameters.pl ?? "1mm"), + Number.parseFloat(parameters.pw ?? "0.6mm"), + ), ) } diff --git a/src/fn/diode.ts b/src/fn/diode.ts index b08e1162..2d85d3b5 100644 --- a/src/fn/diode.ts +++ b/src/fn/diode.ts @@ -1,5 +1,5 @@ import type { AnySoupElement } from "circuit-json" -import { passive, type PassiveDef } from "src/helpers/passive-fn" +import { passive, type PassiveDef } from "../helpers/passive-fn" export const diode = (parameters: { tht: boolean diff --git a/src/fn/dip.ts b/src/fn/dip.ts index 614d6f3c..7712d46c 100644 --- a/src/fn/dip.ts +++ b/src/fn/dip.ts @@ -3,7 +3,7 @@ import type { PcbFabricationNoteText, PcbSilkscreenPath, } from "circuit-json" -import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" +import { type SilkscreenRef, silkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" import { z } from "zod" @@ -16,9 +16,9 @@ import type { NowDefined } from "../helpers/zod/now-defined" function convertMilToMm(value: string | number): number { if (typeof value === "string") { if (value.trim().toLowerCase().endsWith("mil")) { - return parseFloat(value) * 0.0254 + return Number.parseFloat(value) * 0.0254 } - return parseFloat(value) + return Number.parseFloat(value) } return Number(value) } diff --git a/src/fn/electrolytic.ts b/src/fn/electrolytic.ts index 1d338e82..dfe7f020 100644 --- a/src/fn/electrolytic.ts +++ b/src/fn/electrolytic.ts @@ -4,7 +4,7 @@ import { type PcbSilkscreenPath, } from "circuit-json" import { z } from "zod" -import { platedhole } from "src/helpers/platedhole" +import { platedhole } from "../helpers/platedhole" import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/hc49.ts b/src/fn/hc49.ts index 17669c3f..38f5bf3e 100644 --- a/src/fn/hc49.ts +++ b/src/fn/hc49.ts @@ -4,7 +4,7 @@ import { type PcbSilkscreenPath, } from "circuit-json" import { z } from "zod" -import { platedhole } from "src/helpers/platedhole" +import { platedhole } from "../helpers/platedhole" import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/index.ts b/src/fn/index.ts index c3ee18a1..7e6647fb 100644 --- a/src/fn/index.ts +++ b/src/fn/index.ts @@ -24,6 +24,8 @@ export { ms013 } from "./ms013" export { sot723 } from "./sot723" export { sod123 } from "./sod123" export { axial } from "./axial" +export { pdip } from "./pdip" +export { pdip8 } from "./pdip8" export { radial } from "./radial" export { pushbutton } from "./pushbutton" export { stampboard } from "./stampboard" @@ -80,3 +82,5 @@ export { sot343 } from "./sot343" export { m2host } from "./m2host" export { mountedpcbmodule } from "./mountedpcbmodule" export { to92l } from "./to92l" +export { spdip } from "./spdip" +export { utdfn } from "./utdfn" diff --git a/src/fn/jst.ts b/src/fn/jst.ts index d11bb091..eb3db59b 100644 --- a/src/fn/jst.ts +++ b/src/fn/jst.ts @@ -1,56 +1,43 @@ -import { - length, - type AnySoupElement, - type PcbSilkscreenPath, -} from "circuit-json" import { z } from "zod" - -import { platedHoleWithRectPad } from "src/helpers/platedHoleWithRectPad" -import { rectpad } from "src/helpers/rectpad" +import { length } from "circuit-json" +import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" +import { platedHoleWithRectPad } from "../helpers/platedHoleWithRectPad" +import { rectpad } from "../helpers/rectpad" import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" -import { base_def } from "../helpers/zod/base_def" -export const jst_def = base_def.extend({ +export const jst_def = z.object({ fn: z.string(), - p: length.optional(), - id: length.optional(), - pw: length.optional(), - pl: length.optional(), - w: length.optional(), - h: length.optional(), - sh: z - .boolean() - .optional() - .describe( - 'JST SH (Surface-mount) connector family. SH stands for "Super High-density".', - ), - - ph: z - .boolean() - .optional() - .describe( - 'JST PH (Through-hole) connector family. PH stands for "Pin Header".', - ), - + num_pins: z.number().optional(), + p: z.union([z.string(), z.number()]).optional(), + id: z.union([z.string(), z.number()]).optional(), + pw: z.union([z.string(), z.number()]).optional(), + pl: z.union([z.string(), z.number()]).optional(), + w: z.union([z.string(), z.number()]).optional(), + h: z.union([z.string(), z.number()]).optional(), + sh: z.boolean().optional(), + ph: z.boolean().optional(), string: z.string().optional(), }) -export type jstDef = z.input +export type jstDef = z.infer -// Variant type type JstVariant = "ph" | "sh" -const variantDefaults: Record = { +const variantDefaults: Record< + JstVariant, + { p: number; id: number; pw: number; pl: number; w: number; h: number } +> = { ph: { p: length.parse("2.2mm"), id: length.parse("0.70mm"), - pw: length.parse("1.20mm"), - pl: length.parse("1.20mm"), + pw: length.parse("1.2mm"), + pl: length.parse("1.2mm"), w: length.parse("6mm"), h: length.parse("5mm"), }, sh: { p: length.parse("1mm"), + id: length.parse("0.70mm"), pw: length.parse("0.6mm"), pl: length.parse("1.55mm"), w: length.parse("5.8mm"), @@ -124,15 +111,14 @@ function generateSilkscreenBody( stroke_width: 0.1, pcb_silkscreen_path_id: "", } - } else { - return { - type: "pcb_silkscreen_path", - layer: "top", - pcb_component_id: "", - route: [], - stroke_width: 0.1, - pcb_silkscreen_path_id: "", - } + } + return { + type: "pcb_silkscreen_path", + layer: "top", + pcb_component_id: "", + route: [], + stroke_width: 0.1, + pcb_silkscreen_path_id: "", } } @@ -143,12 +129,12 @@ export const jst = ( const variant = getVariant(params) const defaults = variantDefaults[variant] - const p = params.p ?? defaults.p - const id = params.id ?? defaults.id - const pw = params.pw ?? defaults.pw - const pl = params.pl ?? defaults.pl - const w = params.w ?? defaults.w - const h = params.h ?? defaults.h + const p = params.p ? length.parse(params.p) : defaults.p + const id = params.id ? length.parse(params.id) : defaults.id + const pw = params.pw ? length.parse(params.pw) : defaults.pw + const pl = params.pl ? length.parse(params.pl) : defaults.pl + const w = params.w ? length.parse(params.w) : defaults.w + const h = params.h ? length.parse(params.h) : defaults.h let numPins: number | undefined @@ -158,12 +144,11 @@ export const jst = ( } const str = typeof raw_params.string === "string" ? raw_params.string : "" - const match = str.match(/(?:^|_)jst(\d+)(?:_|$)/) - if (match && match[1]) { - const parsed = parseInt(match[1], 10) - if (!Number.isNaN(parsed)) { - numPins = parsed - } + + // Robust parsing: find any sequence of digits after 'jst' or variant prefix + const jstMatch = str.match(/jst.*(\d+)/i) + if (jstMatch?.[1]) { + numPins = Number.parseInt(jstMatch[1], 10) } if (typeof numPins !== "number") { diff --git a/src/fn/m2host.ts b/src/fn/m2host.ts index ad734576..76e78be1 100644 --- a/src/fn/m2host.ts +++ b/src/fn/m2host.ts @@ -80,10 +80,10 @@ export const m2host = ( // const silkscreenRefText: SilkscreenRef = silkscreenRef(0, padLength, 0.5) // --- center footprint around (0,0) --- - let minX = Infinity - let maxX = -Infinity - let minY = Infinity - let maxY = -Infinity + let minX = Number.POSITIVE_INFINITY + let maxX = Number.NEGATIVE_INFINITY + let minY = Number.POSITIVE_INFINITY + let maxY = Number.NEGATIVE_INFINITY const updateBounds = (x: number, y: number, w = 0, h = 0) => { minX = Math.min(minX, x - w / 2) diff --git a/src/fn/melf.ts b/src/fn/melf.ts index 036905c3..39dfcb30 100644 --- a/src/fn/melf.ts +++ b/src/fn/melf.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/micromelf.ts b/src/fn/micromelf.ts index 183d00aa..c86d8b7a 100644 --- a/src/fn/micromelf.ts +++ b/src/fn/micromelf.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/minimelf.ts b/src/fn/minimelf.ts index f4130954..7c62fe7c 100644 --- a/src/fn/minimelf.ts +++ b/src/fn/minimelf.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/mountedpcbmodule.ts b/src/fn/mountedpcbmodule.ts index 7ccf2bae..f4c7ccaa 100644 --- a/src/fn/mountedpcbmodule.ts +++ b/src/fn/mountedpcbmodule.ts @@ -1,7 +1,7 @@ import { type AnyCircuitElement, length } from "circuit-json" -import { determinePinlabelAnchorSide } from "src/helpers/determine-pin-label-anchor-side" -import { silkscreenPin } from "src/helpers/silkscreenPin" -import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" +import { determinePinlabelAnchorSide } from "../helpers/determine-pin-label-anchor-side" +import { silkscreenPin } from "../helpers/silkscreenPin" +import { type SilkscreenRef, silkscreenRef } from "../helpers/silkscreenRef" import { z } from "zod" import { platedHoleWithRectPad } from "../helpers/platedHoleWithRectPad" import { platedhole } from "../helpers/platedhole" diff --git a/src/fn/msop.ts b/src/fn/msop.ts index e515eaf9..92aebb24 100644 --- a/src/fn/msop.ts +++ b/src/fn/msop.ts @@ -1,7 +1,7 @@ import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/pad.ts b/src/fn/pad.ts index 4bce6f0a..b120f506 100644 --- a/src/fn/pad.ts +++ b/src/fn/pad.ts @@ -1,4 +1,4 @@ -import { z } from "zod" +import type { z } from "zod" import { rectpad } from "../helpers/rectpad" import { silkscreenRef } from "../helpers/silkscreenRef" import type { AnySoupElement } from "circuit-json" diff --git a/src/fn/pdip.ts b/src/fn/pdip.ts new file mode 100644 index 00000000..c3ed0dbc --- /dev/null +++ b/src/fn/pdip.ts @@ -0,0 +1,12 @@ +import { dip, dip_def, extendDipDef } from "./dip" + +export const pdip_def = extendDipDef({ w: "300mil", p: "2.54mm" }) + +export const pdip = (raw_params: any) => { + const parameters = pdip_def.parse(raw_params) + return dip({ + ...parameters, + num_pins: raw_params.num_pins ?? 8, + dip: true, + } as any) +} diff --git a/src/fn/pdip8.ts b/src/fn/pdip8.ts new file mode 100644 index 00000000..35b1446a --- /dev/null +++ b/src/fn/pdip8.ts @@ -0,0 +1,11 @@ +import { dip, dip_def, extendDipDef } from "./dip" + +export const pdip8_def = extendDipDef({ w: "300mil", p: "2.54mm" }) + +export const pdip8 = (raw_params: any) => { + const parameters = pdip8_def.parse({ ...raw_params, num_pins: 8 }) + return dip({ + ...parameters, + dip: true, + } as any) +} diff --git a/src/fn/pinrow.ts b/src/fn/pinrow.ts index ec77b477..f1df02db 100644 --- a/src/fn/pinrow.ts +++ b/src/fn/pinrow.ts @@ -3,10 +3,10 @@ import { length, rotation, type AnySoupElement } from "circuit-json" import { platedhole } from "../helpers/platedhole" import { platedHoleWithRectPad } from "../helpers/platedHoleWithRectPad" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" -import { silkscreenPin } from "src/helpers/silkscreenPin" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" +import { silkscreenPin } from "../helpers/silkscreenPin" import { mm } from "@tscircuit/mm" -import { determinePinlabelAnchorSide } from "src/helpers/determine-pin-label-anchor-side" +import { determinePinlabelAnchorSide } from "../helpers/determine-pin-label-anchor-side" import { base_def } from "../helpers/zod/base_def" export const pinrow_def = base_def diff --git a/src/fn/potentiometer.ts b/src/fn/potentiometer.ts index f8bffdfe..d13e4274 100644 --- a/src/fn/potentiometer.ts +++ b/src/fn/potentiometer.ts @@ -1,5 +1,5 @@ import { string, z } from "zod" -import { platedhole } from "src/helpers/platedhole" +import { platedhole } from "../helpers/platedhole" import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/pushbutton.ts b/src/fn/pushbutton.ts index cd9ab844..d5c0039f 100644 --- a/src/fn/pushbutton.ts +++ b/src/fn/pushbutton.ts @@ -2,7 +2,7 @@ import { length, type AnyCircuitElement } from "circuit-json" import { z } from "zod" import { platedhole } from "../helpers/platedhole" import { silkscreenpath } from "../helpers/silkscreenpath" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" export const pushbutton_def = base_def.extend({ diff --git a/src/fn/quad.ts b/src/fn/quad.ts index b9993016..d0bb8e9a 100644 --- a/src/fn/quad.ts +++ b/src/fn/quad.ts @@ -3,10 +3,10 @@ import { optional, z } from "zod" import { length } from "circuit-json" import type { NowDefined } from "../helpers/zod/now-defined" import { rectpad } from "../helpers/rectpad" -import { pin_order_specifier } from "src/helpers/zod/pin-order-specifier" -import { getQuadPinMap } from "src/helpers/get-quad-pin-map" -import { dim2d } from "src/helpers/zod/dim-2d" -import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" +import { pin_order_specifier } from "../helpers/zod/pin-order-specifier" +import { getQuadPinMap } from "../helpers/get-quad-pin-map" +import { dim2d } from "../helpers/zod/dim-2d" +import { type SilkscreenRef, silkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" export const base_quad_def = base_def.extend({ diff --git a/src/fn/radial.ts b/src/fn/radial.ts index 8198324a..82c01104 100644 --- a/src/fn/radial.ts +++ b/src/fn/radial.ts @@ -5,7 +5,7 @@ import { } from "circuit-json" import { z } from "zod" import { generateCircleArcs } from "../helpers/generateCircleArcs" -import { platedhole } from "src/helpers/platedhole" +import { platedhole } from "../helpers/platedhole" import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sma.ts b/src/fn/sma.ts index 178e8748..7e35d0d9 100644 --- a/src/fn/sma.ts +++ b/src/fn/sma.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/smb.ts b/src/fn/smb.ts index a243edc3..b13d96fa 100644 --- a/src/fn/smb.ts +++ b/src/fn/smb.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/smbf.ts b/src/fn/smbf.ts index fa21bf59..aaff023b 100644 --- a/src/fn/smbf.ts +++ b/src/fn/smbf.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/smc.ts b/src/fn/smc.ts index 1f865379..bb5b9485 100644 --- a/src/fn/smc.ts +++ b/src/fn/smc.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/smf.ts b/src/fn/smf.ts index 36df2743..c797a27c 100644 --- a/src/fn/smf.ts +++ b/src/fn/smf.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sod110.ts b/src/fn/sod110.ts index 6d4d2c44..615cf6aa 100644 --- a/src/fn/sod110.ts +++ b/src/fn/sod110.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sod123.ts b/src/fn/sod123.ts index bfa1ef57..5fd50428 100644 --- a/src/fn/sod123.ts +++ b/src/fn/sod123.ts @@ -1,7 +1,7 @@ import type { AnySoupElement } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sod123f.ts b/src/fn/sod123f.ts index 1f5c9394..92cc16ae 100644 --- a/src/fn/sod123f.ts +++ b/src/fn/sod123f.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sod123fl.ts b/src/fn/sod123fl.ts index d4ecdb8a..53b508da 100644 --- a/src/fn/sod123fl.ts +++ b/src/fn/sod123fl.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sod123w.ts b/src/fn/sod123w.ts index 20ad6c9b..65e8e694 100644 --- a/src/fn/sod123w.ts +++ b/src/fn/sod123w.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sod128.ts b/src/fn/sod128.ts index 057f30ad..50c373f7 100644 --- a/src/fn/sod128.ts +++ b/src/fn/sod128.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sod323.ts b/src/fn/sod323.ts index 23d476e6..13b6b212 100644 --- a/src/fn/sod323.ts +++ b/src/fn/sod323.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sod323f.ts b/src/fn/sod323f.ts index 7b3c1455..c765ba6e 100644 --- a/src/fn/sod323f.ts +++ b/src/fn/sod323f.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sod323fl.ts b/src/fn/sod323fl.ts index e9b23368..fe1e2576 100644 --- a/src/fn/sod323fl.ts +++ b/src/fn/sod323fl.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sod323w.ts b/src/fn/sod323w.ts index be150b95..b6dea070 100644 --- a/src/fn/sod323w.ts +++ b/src/fn/sod323w.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sod523.ts b/src/fn/sod523.ts index 827ed3e6..8a51ad4d 100644 --- a/src/fn/sod523.ts +++ b/src/fn/sod523.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sod723.ts b/src/fn/sod723.ts index de43cc93..3f4fd2d6 100644 --- a/src/fn/sod723.ts +++ b/src/fn/sod723.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sod80.ts b/src/fn/sod80.ts index d6ff9cfd..f48fa346 100644 --- a/src/fn/sod80.ts +++ b/src/fn/sod80.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sod882.ts b/src/fn/sod882.ts index b8917805..1ce273f8 100644 --- a/src/fn/sod882.ts +++ b/src/fn/sod882.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sod882d.ts b/src/fn/sod882d.ts index 148da753..750c3dc3 100644 --- a/src/fn/sod882d.ts +++ b/src/fn/sod882d.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sod923.ts b/src/fn/sod923.ts index fecd7032..e080c92a 100644 --- a/src/fn/sod923.ts +++ b/src/fn/sod923.ts @@ -1,7 +1,7 @@ import type { AnySoupElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/soic.ts b/src/fn/soic.ts index a324887b..ebf950cf 100644 --- a/src/fn/soic.ts +++ b/src/fn/soic.ts @@ -3,8 +3,8 @@ import { z } from "zod" import { length } from "circuit-json" import type { NowDefined } from "../helpers/zod/now-defined" import { u_curve } from "../helpers/u-curve" -import { rectpad } from "src/helpers/rectpad" -import { pillpad } from "src/helpers/pillpad" +import { rectpad } from "../helpers/rectpad" +import { pillpad } from "../helpers/pillpad" import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/solderjumper.ts b/src/fn/solderjumper.ts index b4b1ac99..3c05f794 100644 --- a/src/fn/solderjumper.ts +++ b/src/fn/solderjumper.ts @@ -35,7 +35,7 @@ export const solderjumper = (params: { for (let i = 0; i < num_pins; i++) { pads.push(rectpad(i + 1, i * padSpacing, 0, padWidth, padHeight)) } - let traces: AnyCircuitElement[] = [] + const traces: AnyCircuitElement[] = [] if (bridged) { const pins = bridged.split("").map(Number) if (pins.length > 1) { @@ -45,8 +45,8 @@ export const solderjumper = (params: { if ( typeof from === "number" && typeof to === "number" && - !isNaN(from) && - !isNaN(to) + !Number.isNaN(from) && + !Number.isNaN(to) ) { const xCenterFrom = (from - 1) * padSpacing const xCenterTo = (to - 1) * padSpacing diff --git a/src/fn/son.ts b/src/fn/son.ts index eaa096f3..827d691c 100644 --- a/src/fn/son.ts +++ b/src/fn/son.ts @@ -2,7 +2,7 @@ import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { length } from "circuit-json" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" export const son_def = base_def.extend({ @@ -22,7 +22,7 @@ export const son_def = base_def.extend({ export const son = ( raw_params: z.input, ): { circuitJson: AnyCircuitElement[]; parameters: any } => { - if (raw_params.string && raw_params.string.includes("_ep")) { + if (raw_params.string?.includes("_ep")) { raw_params.ep = true } diff --git a/src/fn/sop8.ts b/src/fn/sop8.ts index 93861fd3..de2a1fb6 100644 --- a/src/fn/sop8.ts +++ b/src/fn/sop8.ts @@ -1,7 +1,7 @@ import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" import { extendSoicDef, type SoicInput, getCcwSoicCoords } from "./soic" -import { rectpad } from "src/helpers/rectpad" -import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" +import { rectpad } from "../helpers/rectpad" +import { type SilkscreenRef, silkscreenRef } from "../helpers/silkscreenRef" export const sop8_def = extendSoicDef({ w: "7.05mm", @@ -26,7 +26,13 @@ export const sop8 = ( widthincludeslegs: true, }) pads.push( - rectpad(i + 1, x, y, parameters.pl ?? "1.5mm", parameters.pw ?? "0.6mm"), + rectpad( + i + 1, + x, + y, + Number.parseFloat(parameters.pl ?? "1.5mm"), + Number.parseFloat(parameters.pw ?? "0.6mm"), + ), ) } diff --git a/src/fn/sot.ts b/src/fn/sot.ts index 49c1a369..d5a57677 100644 --- a/src/fn/sot.ts +++ b/src/fn/sot.ts @@ -1,7 +1,7 @@ import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" export const sot_def = base_def.extend({ diff --git a/src/fn/sot223.ts b/src/fn/sot223.ts index 631f8add..7d432e14 100644 --- a/src/fn/sot223.ts +++ b/src/fn/sot223.ts @@ -1,5 +1,5 @@ import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" -import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" +import { type SilkscreenRef, silkscreenRef } from "../helpers/silkscreenRef" import { z } from "zod" import { rectpad } from "../helpers/rectpad" import { extendSoicDef, soicWithoutParsing } from "./soic" @@ -35,7 +35,7 @@ export const sot223 = ( const parameters = sot223_def.parse({ ...raw_params, - num_pins: numPins, + num_pins: (raw_params as any).num_pins ?? numPins, }) if (parameters.num_pins === 4) { diff --git a/src/fn/sot23.ts b/src/fn/sot23.ts index 6244ed06..2aeacdb7 100644 --- a/src/fn/sot23.ts +++ b/src/fn/sot23.ts @@ -1,5 +1,5 @@ import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" -import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" +import { type SilkscreenRef, silkscreenRef } from "../helpers/silkscreenRef" import { z } from "zod" import { rectpad } from "../helpers/rectpad" import { extendSoicDef, soicWithoutParsing } from "./soic" diff --git a/src/fn/sot23w.ts b/src/fn/sot23w.ts index ed0c613c..fd6cdcf4 100644 --- a/src/fn/sot23w.ts +++ b/src/fn/sot23w.ts @@ -1,5 +1,5 @@ import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" -import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" +import { type SilkscreenRef, silkscreenRef } from "../helpers/silkscreenRef" import { z } from "zod" import { rectpad } from "../helpers/rectpad" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sot25.ts b/src/fn/sot25.ts index 052036be..df2f2382 100644 --- a/src/fn/sot25.ts +++ b/src/fn/sot25.ts @@ -1,5 +1,5 @@ import type { AnyCircuitElement } from "circuit-json" -import { z } from "zod" +import type { z } from "zod" import { sot23_def, sot23_5 } from "./sot23" export const sot25_def = sot23_def.extend({}) diff --git a/src/fn/sot323.ts b/src/fn/sot323.ts index 4a16d629..9dd8ac3f 100644 --- a/src/fn/sot323.ts +++ b/src/fn/sot323.ts @@ -1,5 +1,5 @@ import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" -import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" +import { type SilkscreenRef, silkscreenRef } from "../helpers/silkscreenRef" import { z } from "zod" import { rectpad } from "../helpers/rectpad" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/sot343.ts b/src/fn/sot343.ts index f201b925..084dd6e0 100644 --- a/src/fn/sot343.ts +++ b/src/fn/sot343.ts @@ -1,5 +1,5 @@ import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" -import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" +import { type SilkscreenRef, silkscreenRef } from "../helpers/silkscreenRef" import { z } from "zod" import { rectpad } from "../helpers/rectpad" import { base_def } from "../helpers/zod/base_def" @@ -61,10 +61,10 @@ export const sot343_4 = (parameters: z.infer) => { const pw = Number.parseFloat(parameters.pw) const p = Number.parseFloat(parameters.p) - let minX = Infinity - let maxX = -Infinity - let minY = Infinity - let maxY = -Infinity + let minX = Number.POSITIVE_INFINITY + let maxX = Number.NEGATIVE_INFINITY + let minY = Number.POSITIVE_INFINITY + let maxY = Number.NEGATIVE_INFINITY for (let i = 0; i < parameters.num_pins; i++) { const { x, y } = getCcwSot343Coords({ diff --git a/src/fn/sot363.ts b/src/fn/sot363.ts index 1ea5abf8..001deeb4 100644 --- a/src/fn/sot363.ts +++ b/src/fn/sot363.ts @@ -2,7 +2,7 @@ import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { length } from "circuit-json" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" export const sot363_def = base_def.extend({ diff --git a/src/fn/sot457.ts b/src/fn/sot457.ts index 6b8caabf..6a1d96ca 100644 --- a/src/fn/sot457.ts +++ b/src/fn/sot457.ts @@ -3,7 +3,7 @@ import { z } from "zod" import { rectpad } from "../helpers/rectpad" import { pillpad } from "../helpers/pillpad" import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" -import { base_def } from "src/helpers/zod/base_def" +import { base_def } from "../helpers/zod/base_def" // Common schema properties for both SOT-457 configurations const commonSchema = { diff --git a/src/fn/sot563.ts b/src/fn/sot563.ts index 7aa434e8..96485991 100644 --- a/src/fn/sot563.ts +++ b/src/fn/sot563.ts @@ -2,7 +2,7 @@ import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { length } from "circuit-json" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" export const sot563_def = base_def.extend({ diff --git a/src/fn/sot723.ts b/src/fn/sot723.ts index dfad4d9a..7e435bac 100644 --- a/src/fn/sot723.ts +++ b/src/fn/sot723.ts @@ -1,7 +1,7 @@ import { length, type AnySoupElement } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" export const sot723_def = base_def.extend({ diff --git a/src/fn/sot886.ts b/src/fn/sot886.ts index a36660bd..414d644c 100644 --- a/src/fn/sot886.ts +++ b/src/fn/sot886.ts @@ -2,7 +2,7 @@ import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { length } from "circuit-json" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" export const sot886_def = base_def.extend({ diff --git a/src/fn/sot89.ts b/src/fn/sot89.ts index 6dc89d36..984fa8f6 100644 --- a/src/fn/sot89.ts +++ b/src/fn/sot89.ts @@ -1,7 +1,7 @@ import { z } from "zod" import { rectpad } from "../helpers/rectpad" import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" -import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" +import { type SilkscreenRef, silkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" export const sot89_def = base_def.extend({ diff --git a/src/fn/sot963.ts b/src/fn/sot963.ts index 61c002d1..bee80dfd 100644 --- a/src/fn/sot963.ts +++ b/src/fn/sot963.ts @@ -2,7 +2,7 @@ import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" import { z } from "zod" import { length } from "circuit-json" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" export const sot963_def = base_def.extend({ diff --git a/src/fn/spdip.ts b/src/fn/spdip.ts new file mode 100644 index 00000000..35435fbf --- /dev/null +++ b/src/fn/spdip.ts @@ -0,0 +1,11 @@ +import { dip, extendDipDef } from "./dip" + +export const spdip_def = extendDipDef({ w: "300mil", p: "2.54mm" }) + +export const spdip = (raw_params: any) => { + const parameters = spdip_def.parse(raw_params) + return dip({ + ...parameters, + dip: true, + } as any) +} diff --git a/src/fn/stampboard.ts b/src/fn/stampboard.ts index 6e12f4bb..01efe274 100644 --- a/src/fn/stampboard.ts +++ b/src/fn/stampboard.ts @@ -7,8 +7,8 @@ import { } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { platedhole } from "src/helpers/platedhole" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { platedhole } from "../helpers/platedhole" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" export const stampboard_def = base_def.extend({ diff --git a/src/fn/stampreceiver.ts b/src/fn/stampreceiver.ts index abb99abf..99fb4fc3 100644 --- a/src/fn/stampreceiver.ts +++ b/src/fn/stampreceiver.ts @@ -7,8 +7,8 @@ import { } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" -import { platedhole } from "src/helpers/platedhole" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" +import { platedhole } from "../helpers/platedhole" import { base_def } from "../helpers/zod/base_def" export const stampreceiver_def = base_def.extend({ diff --git a/src/fn/to220.ts b/src/fn/to220.ts index 9f5c1c6a..0d88f61f 100644 --- a/src/fn/to220.ts +++ b/src/fn/to220.ts @@ -3,7 +3,7 @@ import { type PcbSilkscreenPath, length, } from "circuit-json" -import { platedhole } from "src/helpers/platedhole" +import { platedhole } from "../helpers/platedhole" import { z } from "zod" import { type SilkscreenRef, silkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/to92.ts b/src/fn/to92.ts index 00a55a51..461d8754 100644 --- a/src/fn/to92.ts +++ b/src/fn/to92.ts @@ -1,8 +1,8 @@ import { z } from "zod" import { mm } from "@tscircuit/mm" -import { platedhole } from "src/helpers/platedhole" -import { platedHoleWithRectPad } from "src/helpers/platedHoleWithRectPad" -import { platedHolePill } from "src/helpers/platedHolePill" +import { platedhole } from "../helpers/platedhole" +import { platedHoleWithRectPad } from "../helpers/platedHoleWithRectPad" +import { platedHolePill } from "../helpers/platedHolePill" import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/to92l.ts b/src/fn/to92l.ts index 644103eb..61b3b58d 100644 --- a/src/fn/to92l.ts +++ b/src/fn/to92l.ts @@ -1,10 +1,10 @@ import { z } from "zod" -import { platedhole } from "src/helpers/platedhole" -import { platedHoleWithRectPad } from "src/helpers/platedHoleWithRectPad" -import { platedHolePill } from "src/helpers/platedHolePill" +import { platedhole } from "../helpers/platedhole" +import { platedHoleWithRectPad } from "../helpers/platedHoleWithRectPad" +import { platedHolePill } from "../helpers/platedHolePill" import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" -import { base_def } from "src/helpers/zod/base_def" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" +import { base_def } from "../helpers/zod/base_def" export const to92l_def = base_def.extend({ fn: z.string(), diff --git a/src/fn/to92s.ts b/src/fn/to92s.ts index f2b82ea5..9941e503 100644 --- a/src/fn/to92s.ts +++ b/src/fn/to92s.ts @@ -1,5 +1,5 @@ import { z } from "zod" -import { platedhole } from "src/helpers/platedhole" +import { platedhole } from "../helpers/platedhole" import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { base_def } from "../helpers/zod/base_def" diff --git a/src/fn/utdfn.ts b/src/fn/utdfn.ts new file mode 100644 index 00000000..1a41760e --- /dev/null +++ b/src/fn/utdfn.ts @@ -0,0 +1,57 @@ +import { z } from "zod" +import { length } from "circuit-json" +import type { AnyCircuitElement, PcbSilkscreenPath } from "circuit-json" +import { rectpad } from "../helpers/rectpad" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" +import { base_def } from "../helpers/zod/base_def" + +export const utdfn_def = base_def.extend({ + fn: z.string(), + num_pins: z.number().default(4), + w: z.string().default("1mm"), + h: z.string().default("1mm"), + p: z.string().default("0.65mm"), + pl: z.string().default("0.3mm"), + pw: z.string().default("0.25mm"), + epw: z.string().default("0.45mm"), + eph: z.string().default("0.45mm"), + string: z.string().optional(), + ep: z.boolean().default(true), +}) + +export type utdfnDef = z.infer + +export const utdfn = ( + raw_params: utdfnDef, +): { circuitJson: AnyCircuitElement[]; parameters: any } => { + const params = utdfn_def.parse(raw_params) + + const w = length.parse(params.w) + const h = length.parse(params.h) + const p = length.parse(params.p) + const pl = length.parse(params.pl) + const pw = length.parse(params.pw) + const epw = length.parse(params.epw) + const eph = length.parse(params.eph) + + const pads: AnyCircuitElement[] = [] + + // UTDFN-4: 2 on each side + for (let i = 0; i < params.num_pins; i++) { + const isLeft = i < params.num_pins / 2 + const x = isLeft ? -w / 2 + pl / 2 : w / 2 - pl / 2 + const y = ((i % 2 === 0 ? 1 : -1) * p) / 2 + pads.push(rectpad(i + 1, x, y, pl, pw)) + } + + if (params.ep) { + pads.push(rectpad(params.num_pins + 1, 0, 0, epw, eph)) + } + + const silkscreenRefText: SilkscreenRef = silkscreenRef(0, h / 2 + 0.5, 0.2) + + return { + circuitJson: [...pads, silkscreenRefText], + parameters: params, + } +} diff --git a/src/fn/vson.ts b/src/fn/vson.ts index ca0529f7..af47e1dc 100644 --- a/src/fn/vson.ts +++ b/src/fn/vson.ts @@ -7,8 +7,8 @@ import { rectpad } from "../helpers/rectpad" import { z } from "zod" import { base_def } from "../helpers/zod/base_def" import { length, distance } from "circuit-json" -import { dim2d } from "src/helpers/zod/dim-2d" -import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef" +import { dim2d } from "../helpers/zod/dim-2d" +import { type SilkscreenRef, silkscreenRef } from "../helpers/silkscreenRef" // can't use defaults because there is not a lot of common dimensions. export const vson_def = base_def.extend({ diff --git a/src/fn/vssop.ts b/src/fn/vssop.ts index 1306a7dc..6f5f8f2a 100644 --- a/src/fn/vssop.ts +++ b/src/fn/vssop.ts @@ -6,7 +6,7 @@ import type { } from "circuit-json" import { z } from "zod" import { rectpad } from "../helpers/rectpad" -import { silkscreenRef, type SilkscreenRef } from "src/helpers/silkscreenRef" +import { silkscreenRef, type SilkscreenRef } from "../helpers/silkscreenRef" import { length } from "circuit-json" import { base_def } from "../helpers/zod/base_def" diff --git a/src/footprinter.ts b/src/footprinter.ts index 259d1d27..e41c6b6e 100644 --- a/src/footprinter.ts +++ b/src/footprinter.ts @@ -39,6 +39,20 @@ export type Footprinter = { dip: ( num_pins?: number, ) => FootprinterParamsBuilder<"w" | "p" | "id" | "od" | "wide" | "narrow"> + pdip: ( + num_pins?: number, + ) => FootprinterParamsBuilder<"w" | "p" | "id" | "od" | "wide" | "narrow"> + pdip8: () => FootprinterParamsBuilder< + "w" | "p" | "id" | "od" | "wide" | "narrow" + > + spdip: ( + num_pins?: number, + ) => FootprinterParamsBuilder<"w" | "p" | "id" | "od" | "wide" | "narrow"> + utdfn: ( + num_pins?: number, + ) => FootprinterParamsBuilder< + "w" | "h" | "p" | "pl" | "pw" | "epw" | "eph" | "ep" + > cap: () => FootprinterParamsBuilder res: () => FootprinterParamsBuilder diode: () => FootprinterParamsBuilder @@ -386,7 +400,11 @@ export const footprinter = (): Footprinter & { } } return (v: any) => { - if (Object.keys(target).length === 0) { + if ( + Object.keys(target).length === 0 || + prop === "pdip" || + prop === "pdip8" + ) { if (`${prop}${v}` in FOOTPRINT_FN) { target[`${prop}${v}`] = true target.fn = `${prop}${v}` diff --git a/src/footprinter.ts.orig b/src/footprinter.ts.orig new file mode 100644 index 00000000..759d783f --- /dev/null +++ b/src/footprinter.ts.orig @@ -0,0 +1,434 @@ +import * as FOOTPRINT_FN from "./fn" +import type { AnySoupElement } from "circuit-json" +import type { AnyCircuitElement } from "circuit-json" +import type { AnyFootprinterDefinitionOutput } from "./helpers/zod/AnyFootprinterDefinitionOutput" +import { isNotNull } from "./helpers/is-not-null" +import { footprintSizes } from "./helpers/passive-fn" +import { applyOrigin } from "./helpers/apply-origin" +import { applyNoRefDes } from "./helpers/apply-norefdes" +import { applyNoSilkscreen } from "./helpers/apply-nosilkscreen" + +type BaseOptionKey = + | "origin" + | "norefdes" + | "invert" + | "faceup" + | "nosilkscreen" + +export type FootprinterParamsBuilder = { + [P in K | BaseOptionKey | "params" | "soup" | "circuitJson"]: P extends + | "params" + | "soup" + | "circuitJson" + ? Footprinter[P] + : (v?: number | string | boolean) => FootprinterParamsBuilder +} + +type CommonPassiveOptionKey = + | "metric" + | "imperial" + | "tht" + | "p" + | "pw" + | "ph" + | "w" + | "h" + | "textbottom" + +export type Footprinter = { + dip: ( + num_pins?: number, + ) => FootprinterParamsBuilder<"w" | "p" | "id" | "od" | "wide" | "narrow"> + pdip: ( + num_pins?: number, + ) => FootprinterParamsBuilder<"w" | "p" | "id" | "od" | "wide" | "narrow"> + pdip8: () => FootprinterParamsBuilder< + "w" | "p" | "id" | "od" | "wide" | "narrow" + > + cap: () => FootprinterParamsBuilder + res: () => FootprinterParamsBuilder + diode: () => FootprinterParamsBuilder + led: () => FootprinterParamsBuilder + lr: (num_pins?: number) => FootprinterParamsBuilder<"w" | "l" | "pl" | "pr"> + qfp: ( + num_pins?: number, + ) => FootprinterParamsBuilder<"w" | "p" | "id" | "od" | "wide" | "narrow"> + quad: ( + num_pins?: number, + ) => FootprinterParamsBuilder< + "w" | "l" | "square" | "pl" | "pr" | "pb" | "pt" | "p" | "pw" | "ph" + > + bga: ( + num_pins?: number, + ) => FootprinterParamsBuilder< + | "grid" + | "p" + | "w" + | "h" + | "ball" + | "pad" + | "missing" + | "tlorigin" + | "blorigin" + | "trorigin" + | "brorigin" + | "circularpads" + > + qfn: (num_pins?: number) => FootprinterParamsBuilder<"w" | "h" | "p"> + tqfp: (num_pins?: number) => FootprinterParamsBuilder<"w" | "h" | "p"> + soic: ( + num_pins?: number, + ) => FootprinterParamsBuilder< + "w" | "p" | "pw" | "pl" | "id" | "od" | "pillpads" + > + mlp: (num_pins?: number) => FootprinterParamsBuilder<"w" | "h" | "p"> + ssop: (num_pins?: number) => FootprinterParamsBuilder<"w" | "p"> + tssop: (num_pins?: number) => FootprinterParamsBuilder<"w" | "p"> + dfn: (num_pins?: number) => FootprinterParamsBuilder<"w" | "p"> + pinrow: ( + num_pins?: number, + ) => FootprinterParamsBuilder< + | "p" + | "id" + | "od" + | "male" + | "female" + | "rows" + | "smd" + | "surfacemount" + | "rightangle" + | "pw" + | "pl" + | "pinlabeltextalignleft" + | "pinlabeltextaligncenter" + | "pinlabeltextalignright" + | "pinlabelverticallyinverted" + | "pinlabelorthogonal" + | "nosquareplating" + | "nopinlabels" + | "doublesidedpinlabel" + | "bottomsidepinlabel" + > + axial: () => FootprinterParamsBuilder<"p" | "id" | "od"> + radial: () => FootprinterParamsBuilder< + "p" | "id" | "od" | "ceramic" | "electrolytic" | "polarized" + > + hc49: () => FootprinterParamsBuilder<"p" | "id" | "od" | "w" | "h"> + to220: () => FootprinterParamsBuilder<"w" | "h" | "p" | "id" | "od"> + sot363: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sot886: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sot457: () => FootprinterParamsBuilder< + | "w" + | "p" + | "h" + | "pl" + | "pw" + | "wave" + | "reflow" + | "pillr" + | "pillh" + | "pillw" + > + sot563: () => FootprinterParamsBuilder<"w" | "p" | "pl" | "pw"> + sot723: () => FootprinterParamsBuilder<"w" | "h" | "pl" | "pw" | "p"> + sot23: () => FootprinterParamsBuilder<"w" | "h" | "pl" | "pw"> + sot25: () => FootprinterParamsBuilder<"w" | "h" | "pl" | "pw"> + sot: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sot323: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sot89: () => FootprinterParamsBuilder<"w" | "p" | "pl" | "pw" | "h"> + sot343: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sod323w: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + smc: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pw" | "pl"> + minimelf: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pw" | "pl"> + melf: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pw" | "pl"> + jst: () => FootprinterParamsBuilder< + "w" | "h" | "p" | "id" | "pw" | "pl" | "ph" | "sh" + > + micromelf: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pw" | "pl"> + ms013: () => FootprinterParamsBuilder<"w" | "p"> + ms012: () => FootprinterParamsBuilder<"w" | "p"> + lqfp: (num_pins?: number) => FootprinterParamsBuilder<"w" | "h" | "pl" | "pw"> + sma: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + smf: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + smb: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + smbf: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + potentiometer: () => FootprinterParamsBuilder< + "w" | "h" | "p" | "id" | "od" | "pw" | "ca" + > + electrolytic: () => FootprinterParamsBuilder<"d" | "p" | "id" | "od"> + sod923: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sod323: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sod80: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sod882: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sod882d: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sod723: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sod523: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sod323f: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sod323fl: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sod128: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sod123f: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sod123fl: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sod123: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sod123w: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sod110: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + to92: () => FootprinterParamsBuilder<"w" | "h" | "p" | "id" | "od" | "inline"> + to92s: () => FootprinterParamsBuilder<"w" | "h" | "p" | "id" | "od"> + to92l: () => FootprinterParamsBuilder<"w" | "h" | "p" | "id" | "od"> + sot223: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + m2host: () => FootprinterParamsBuilder + son: ( + num_pins?: number, + ) => FootprinterParamsBuilder< + "w" | "h" | "p" | "pl" | "pw" | "epw" | "eph" | "ep" + > + vson: ( + num_pins?: number, + ) => FootprinterParamsBuilder< + "p" | "w" | "grid" | "ep" | "epx" | "pinw" | "pinh" + > + vssop: ( + num_pins?: number, + ) => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + msop: ( + num_pins?: number, + ) => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + sot23w: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw"> + pushbutton: () => FootprinterParamsBuilder< + "tllabel" | "trlabel" | "bllabel" | "brlabel" + > + stampboard: () => FootprinterParamsBuilder< + | "w" + | "h" + | "left" + | "right" + | "top" + | "bottom" + | "p" + | "pw" + | "pl" + | "innerhole" + | "innerholeedgedistance" + | "silkscreenlabels" + | "silkscreenlabelmargin" + > + stampreceiver: () => FootprinterParamsBuilder< + | "w" + | "h" + | "left" + | "right" + | "top" + | "bottom" + | "p" + | "pw" + | "pl" + | "innerhole" + | "innerholeedgedistance" + > + breakoutheaders: () => FootprinterParamsBuilder< + "w" | "h" | "left" | "right" | "top" | "bottom" | "p" | "id" | "od" + > + smtpad: () => FootprinterParamsBuilder< + | "circle" + | "rect" + | "square" + | "pill" + | "d" + | "pd" + | "diameter" + | "r" + | "pr" + | "radius" + | "w" + | "pw" + | "width" + | "h" + | "ph" + | "height" + | "s" + | "size" + > & { + params: () => any + soup: () => AnySoupElement[] + circuitJson: () => AnyCircuitElement[] + } + platedhole: () => FootprinterParamsBuilder< + "d" | "hd" | "r" | "hr" | "pd" | "pr" + > + pad: () => FootprinterParamsBuilder<"w" | "h"> & { + params: () => any + soup: () => AnySoupElement[] + circuitJson: () => AnyCircuitElement[] + } + solderjumper: ( + num_pins?: number, + ) => FootprinterParamsBuilder<"bridged" | "p" | "pw" | "ph"> + + params: () => any + /** @deprecated use circuitJson() instead */ + soup: () => AnySoupElement[] + circuitJson: () => AnyCircuitElement[] + json: () => AnyFootprinterDefinitionOutput[] + getFootprintNames: () => string[] +} + +export const string = (def: string): Footprinter => { + let fp = footprinter() + + // The regex below automatically inserts a "res" prefix so forms like + // "0603_pw1.0_ph1.1" are understood without typing "res0603". + const modifiedDef = def.replace(/^((?:\d{4}|\d{5}))(?=$|_|x)/, "res$1") + + const def_parts = modifiedDef + .split(/_(?!metric)/) // split on '_' not followed by 'metric' + .map((s) => { + const m = s.match(/([a-zA-Z]+)([\(\d\.\+\?].*)?/) + if (!m) return null + const [, rawFn, v] = m + if (!rawFn) return null + const fn = rawFn.toLowerCase() + if (v?.includes("?")) return null + return { fn, v } + }) + .filter(isNotNull) + + for (const { fn, v } of def_parts) { + fp = fp[fn](v) + } + + fp.setString(def) + + return fp +} + +export const getFootprintNames = (): string[] => { + return Object.keys(FOOTPRINT_FN) +} + +export const getFootprintSizes = (): typeof footprintSizes => { + return footprintSizes +} + +export const getFootprintNamesByType = (): { + passiveFootprintNames: string[] + normalFootprintNames: string[] +} => { + const allFootprintNames = Object.keys(FOOTPRINT_FN) + + const passiveFootprintNames = allFootprintNames.filter((name) => { + const fn = FOOTPRINT_FN[name] + + return fn.toString().includes("passive(") + }) + + return { + passiveFootprintNames, + normalFootprintNames: allFootprintNames.filter( + (name) => !passiveFootprintNames.includes(name), + ), + } +} + +export const footprinter = (): Footprinter & { + string: typeof string + getFootprintNames: string[] + setString: (string) => void +} => { + const proxy = new Proxy( + {}, + { + get: (target: any, prop: string) => { + if (prop === "soup" || prop === "circuitJson") { + if ("fn" in target && FOOTPRINT_FN[target.fn]) { + return () => { + const { circuitJson } = FOOTPRINT_FN[target.fn](target) + const circuitWithoutSilkscreen = applyNoSilkscreen( + circuitJson, + target, + ) + const circuitWithoutRefDes = applyNoRefDes( + circuitWithoutSilkscreen, + target, + ) + return applyOrigin(circuitWithoutRefDes, target.origin) + } + } + + if (!FOOTPRINT_FN[target.fn]) { + throw new Error( + `Invalid footprint function, got "${target.fn}"${ + target.string ? `, from string "${target.string}"` : "" + }`, + ) + } + + return () => { + // TODO improve error + throw new Error( + `No function found for footprinter, make sure to specify .dip, .lr, .p, etc. Got "${prop}"`, + ) + } + } + if (prop === "json") { + if (!FOOTPRINT_FN[target.fn]) { + throw new Error( + `Invalid footprint function, got "${target.fn}"${ + target.string ? `, from string "${target.string}"` : "" + }`, + ) + } + return () => FOOTPRINT_FN[target.fn](target).parameters + } + if (prop === "getFootprintNames") { + return () => Object.keys(FOOTPRINT_FN) + } + if (prop === "params") { + // TODO + return () => target + } + if (prop === "setString") { + return (v: string) => { + target.string = v + return proxy + } + } + return (v: any) => { + if (Object.keys(target).length === 0) { + if (`${prop}${v}` in FOOTPRINT_FN) { + target[`${prop}${v}`] = true + target.fn = `${prop}${v}` + } else { + target[prop] = true + target.fn = prop + if (prop === "res" || prop === "cap") { + if (v) { + if (typeof v === "string" && v.includes("_metric")) { + target.metric = v.split("_metric")[0] + } else { + target.imperial = v // e.g., res0402, cap0603 etc. + } + } + } else { + target.num_pins = Number.isNaN(Number.parseFloat(v)) + ? undefined + : Number.parseFloat(v) + } + } + } else { + // handle dip_w or other invalid booleans + if (!v && ["w", "h", "p"].includes(prop as string)) { + // ignore + } else { + target[prop] = v ?? true + } + } + return proxy + } + }, + }, + ) + return proxy as any +} +footprinter.string = string +footprinter.getFootprintNames = getFootprintNames + +export const fp = footprinter diff --git a/src/helpers/apply-origin.ts b/src/helpers/apply-origin.ts index 2c3d51b2..c36b944a 100644 --- a/src/helpers/apply-origin.ts +++ b/src/helpers/apply-origin.ts @@ -20,10 +20,7 @@ export const applyOrigin = ( if (!origin) return elements const pads = elements.filter( - (el) => - el.type === "pcb_smtpad" || - el.type === "pcb_plated_hole" || - el.type === "pcb_thtpad", + (el) => el.type === "pcb_smtpad" || el.type === "pcb_plated_hole", ) as Array if (pads.length === 0) return elements @@ -52,9 +49,7 @@ export const applyOrigin = ( } else if (pad.type === "pcb_plated_hole") { const d = pad.outer_diameter ?? pad.hole_diameter updateBounds(pad.x, pad.y, d, d) - } else if (pad.type === "pcb_thtpad") { - const d = pad.diameter - updateBounds(pad.x, pad.y, d, d) + // pcb_thtpad type no longer exists in circuit-json types } } diff --git a/src/helpers/boolean-difference.ts b/src/helpers/boolean-difference.ts index 2ada0345..eac528a8 100644 --- a/src/helpers/boolean-difference.ts +++ b/src/helpers/boolean-difference.ts @@ -576,7 +576,7 @@ export function createBooleanDifferenceVisualization( svg += `` } } - svg += `` + svg += "" svg += `` @@ -606,7 +606,7 @@ export function createBooleanDifferenceVisualization( svg += `` } } - svg += `` + svg += "" const centerX = viewBoxX + width / 2 const centerY = viewBoxY + height / 2 @@ -615,7 +615,7 @@ export function createBooleanDifferenceVisualization( svg += `` svg += `` svg += `` - svg += `` + svg += "" // Add compact legend for overlay visualization (sized to fit within bounds) if (showLegend) { @@ -647,7 +647,7 @@ export function createBooleanDifferenceVisualization( // Compact instructions svg += `Perfect alignment = complete overlap` - svg += `` + svg += "" } svg += "" diff --git a/src/helpers/zod/dim-2d.ts b/src/helpers/zod/dim-2d.ts index 798fd436..6f979753 100644 --- a/src/helpers/zod/dim-2d.ts +++ b/src/helpers/zod/dim-2d.ts @@ -5,8 +5,8 @@ export const dim2d = z .transform((a) => { const [x, y] = a.split(/[x ]/) return { - x: parseFloat(x ?? ""), - y: parseFloat(y ?? ""), + x: Number.parseFloat(x ?? ""), + y: Number.parseFloat(y ?? ""), } }) .pipe( diff --git a/src/helpers/zod/function-call.ts b/src/helpers/zod/function-call.ts index 57c0a154..5fe47c70 100644 --- a/src/helpers/zod/function-call.ts +++ b/src/helpers/zod/function-call.ts @@ -5,12 +5,13 @@ export const function_call = z .or(z.array(z.any())) .transform((a) => { if (Array.isArray(a)) return a - if (a.startsWith("(") && a.endsWith(")")) { - a = a.slice(1, -1) + let str = a + if (str.startsWith("(") && str.endsWith(")")) { + str = str.slice(1, -1) } - return a.split(",").map((v) => { + return str.split(",").map((v) => { const numVal = Number(v) - return isNaN(numVal) ? v : numVal + return Number.isNaN(numVal) ? v : numVal }) }) .pipe(z.array(z.string().or(z.number()))) diff --git a/tests/all-fixes.test.ts b/tests/all-fixes.test.ts new file mode 100644 index 00000000..1ea72007 --- /dev/null +++ b/tests/all-fixes.test.ts @@ -0,0 +1,16 @@ +import { describe, expect, it } from "bun:test" +import { fp } from "../src/footprinter" + +describe("all-fixes", () => { + it("pdip8 should have 8 pins (#371)", () => { + const circuitJson = fp().pdip8().circuitJson() + const pins = circuitJson.filter((e) => e.type === "pcb_plated_hole") + expect(pins.length).toBe(8) + }) + + it("jst_ph_4 should have 4 pins (#495)", () => { + const circuitJson = fp.string("jst_ph_4").circuitJson() + const pads = circuitJson.filter((e) => e.type === "pcb_plated_hole") + expect(pads.length).toBe(4) + }) +}) diff --git a/tests/bga.test.ts b/tests/bga.test.ts index 01a89bd2..b3bd7501 100644 --- a/tests/bga.test.ts +++ b/tests/bga.test.ts @@ -62,8 +62,8 @@ test("bga origin parameters", () => { el.port_hints !== undefined && el.port_hints[0] === "1", ) - expect(firstPadBl?.x).toBe(-0.5) // Left column - expect(firstPadBl?.y).toBe(0.5) // Bottom row + expect(firstPadBl && "x" in firstPadBl ? firstPadBl.x : undefined).toBe(-0.5) // Left column + expect(firstPadBl && "y" in firstPadBl ? firstPadBl.y : undefined).toBe(0.5) // Bottom row // Test bottom-right origin (pin 1 at bottom-right) const soupBr = fp().bga(4).grid("2x2").p(1).brorigin(true).soup() @@ -78,8 +78,8 @@ test("bga origin parameters", () => { el.port_hints !== undefined && el.port_hints[0] === "1", ) - expect(firstPadBr?.x).toBe(0.5) // Right column - expect(firstPadBr?.y).toBe(0.5) // Bottom row + expect(firstPadBr && "x" in firstPadBr ? firstPadBr.x : undefined).toBe(0.5) // Right column + expect(firstPadBr && "y" in firstPadBr ? firstPadBr.y : undefined).toBe(0.5) // Bottom row // Test top-right origin (pin 1 at top-right) const soupTr = fp().bga(4).grid("2x2").p(1).trorigin(true).soup() @@ -94,8 +94,8 @@ test("bga origin parameters", () => { el.port_hints !== undefined && el.port_hints[0] === "1", ) - expect(firstPadTr?.x).toBe(0.5) // Right column - expect(firstPadTr?.y).toBe(-0.5) // Top row + expect(firstPadTr && "x" in firstPadTr ? firstPadTr.x : undefined).toBe(0.5) // Right column + expect(firstPadTr && "y" in firstPadTr ? firstPadTr.y : undefined).toBe(-0.5) // Top row // Test top-left origin (default, pin 1 at top-left) const soupTl = fp().bga(4).grid("2x2").p(1).soup() @@ -110,13 +110,16 @@ test("bga origin parameters", () => { el.port_hints !== undefined && el.port_hints[0] === "1", ) - expect(firstPadTl?.x).toBe(-0.5) // Left column - expect(firstPadTl?.y).toBe(-0.5) // Top row + expect(firstPadTl && "x" in firstPadTl ? firstPadTl.x : undefined).toBe(-0.5) // Left column + expect(firstPadTl && "y" in firstPadTl ? firstPadTl.y : undefined).toBe(-0.5) // Top row // Verify that all pads are in the same physical positions regardless of origin const allPads = (soup: AnySoupElement[]) => soup - .filter((el): el is PcbSmtPad => el.type === "pcb_smtpad") + .filter( + (el): el is PcbSmtPad & { x: number; y: number } => + el.type === "pcb_smtpad" && "x" in el && "y" in el, + ) .sort((a, b) => (a.x === b.x ? a.y - b.y : a.x - b.x)) const padsTl = allPads(soupTl) @@ -126,12 +129,24 @@ test("bga origin parameters", () => { // All configurations should have pads in the same physical positions for (let i = 0; i < padsTl.length; i++) { - expect(padsTl[i]!.x).toBe(padsBl[i]!.x) - expect(padsTl[i]!.y).toBe(padsBl[i]!.y) - expect(padsTl[i]!.x).toBe(padsBr[i]!.x) - expect(padsTl[i]!.y).toBe(padsBr[i]!.y) - expect(padsTl[i]!.x).toBe(padsTr[i]!.x) - expect(padsTl[i]!.y).toBe(padsTr[i]!.y) + expect(padsTl[i] && "x" in padsTl[i] ? padsTl[i].x : undefined).toBe( + padsBl[i] && "x" in padsBl[i] ? padsBl[i].x : undefined, + ) + expect(padsTl[i] && "y" in padsTl[i] ? padsTl[i].y : undefined).toBe( + padsBl[i] && "y" in padsBl[i] ? padsBl[i].y : undefined, + ) + expect(padsTl[i] && "x" in padsTl[i] ? padsTl[i].x : undefined).toBe( + padsBr[i] && "x" in padsBr[i] ? padsBr[i].x : undefined, + ) + expect(padsTl[i] && "y" in padsTl[i] ? padsTl[i].y : undefined).toBe( + padsBr[i] && "y" in padsBr[i] ? padsBr[i].y : undefined, + ) + expect(padsTl[i] && "x" in padsTl[i] ? padsTl[i].x : undefined).toBe( + padsTr[i] && "x" in padsTr[i] ? padsTr[i].x : undefined, + ) + expect(padsTl[i] && "y" in padsTl[i] ? padsTl[i].y : undefined).toBe( + padsTr[i] && "y" in padsTr[i] ? padsTr[i].y : undefined, + ) } }) diff --git a/tests/dip.test.ts b/tests/dip.test.ts index ccc0d214..edcea132 100644 --- a/tests/dip.test.ts +++ b/tests/dip.test.ts @@ -81,7 +81,7 @@ test("dip4", () => { test("dip8_p1.27mm", () => { const circuitJson = fp.string("dip8_p1.27mm").circuitJson() - let svgContent = convertCircuitJsonToPcbSvg(circuitJson) + const svgContent = convertCircuitJsonToPcbSvg(circuitJson) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "dip8_p1.27mm") }) diff --git a/tests/fixtures/compareFootprinterVsKicad.ts b/tests/fixtures/compareFootprinterVsKicad.ts index 8512d6dd..12b53866 100644 --- a/tests/fixtures/compareFootprinterVsKicad.ts +++ b/tests/fixtures/compareFootprinterVsKicad.ts @@ -211,10 +211,10 @@ export async function compareFootprinterVsKicad( ) // Bounding box for both sets - let minX = Infinity - let maxX = -Infinity - let minY = Infinity - let maxY = -Infinity + let minX = Number.POSITIVE_INFINITY + let maxX = Number.NEGATIVE_INFINITY + let minY = Number.POSITIVE_INFINITY + let maxY = Number.NEGATIVE_INFINITY for (const elm of [...fpCircuitJson, ...transformedKiCad]) { if ( diff --git a/tests/fixtures/index.ts b/tests/fixtures/index.ts index 25529c8e..61d17a96 100644 --- a/tests/fixtures/index.ts +++ b/tests/fixtures/index.ts @@ -11,7 +11,8 @@ export const toPinPositionString = (soup: AnySoupElement[]) => { y: e.y, pn: e.port_hints?.[0], } - } else if (e.type === "pcb_smtpad") { + } + if (e.type === "pcb_smtpad") { return { x: e.x, y: e.y, diff --git a/tests/footprint-completeness.test.ts b/tests/footprint-completeness.test.ts index 4aa91138..963419ca 100644 --- a/tests/footprint-completeness.test.ts +++ b/tests/footprint-completeness.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "bun:test" import { getFootprintNames } from "../src/footprinter" -import fs from "fs" -import path from "path" +import fs from "node:fs" +import path from "node:path" describe("footprint completeness", () => { it("should expose all footprint functions from src/fn/", () => { diff --git a/tests/jst.test.ts b/tests/jst.test.ts index fe111209..7273d11d 100644 --- a/tests/jst.test.ts +++ b/tests/jst.test.ts @@ -5,30 +5,30 @@ import { fp } from "../src/footprinter" test("jst2_ph", () => { const circuitJson = fp.string("jst2_ph").circuitJson() const svgContent = convertCircuitJsonToPcbSvg(circuitJson) - expect(svgContent).toMatchSvgSnapshot(import.meta.path + "jst2_ph") + expect(svgContent).toMatchSvgSnapshot(`${import.meta.path}jst2_ph`) }) test("jst4_sh", () => { const circuitJson = fp.string("jst4_sh").circuitJson() const svgContent = convertCircuitJsonToPcbSvg(circuitJson) - expect(svgContent).toMatchSvgSnapshot(import.meta.path + "jst4_sh") + expect(svgContent).toMatchSvgSnapshot(`${import.meta.path}jst4_sh`) }) test("jst8_sh", () => { const circuitJson = fp.string("jst8_sh").circuitJson() const svgContent = convertCircuitJsonToPcbSvg(circuitJson) - expect(svgContent).toMatchSvgSnapshot(import.meta.path + "jst8_sh") + expect(svgContent).toMatchSvgSnapshot(`${import.meta.path}jst8_sh`) }) test("jst2_sh", () => { const circuitJson = fp.string("jst2_sh").circuitJson() const svgContent = convertCircuitJsonToPcbSvg(circuitJson) - expect(svgContent).toMatchSvgSnapshot(import.meta.path + "jst2_sh") + expect(svgContent).toMatchSvgSnapshot(`${import.meta.path}jst2_sh`) }) test("jst6_sh", () => { const circuitJson = fp.string("jst6_sh").circuitJson() const svgContent = convertCircuitJsonToPcbSvg(circuitJson) - expect(svgContent).toMatchSvgSnapshot(import.meta.path + "jst6_sh") + expect(svgContent).toMatchSvgSnapshot(`${import.meta.path}jst6_sh`) }) test("jst_sh6_is_invalid", () => { diff --git a/tests/pdip.test.ts b/tests/pdip.test.ts new file mode 100644 index 00000000..55d7d004 --- /dev/null +++ b/tests/pdip.test.ts @@ -0,0 +1,28 @@ +import { describe, expect, it } from "bun:test" +import { fp } from "../src/footprinter" + +describe("pdip", () => { + it("pdip8 should have 8 pins and correct dimensions", () => { + // Correct usage for the standard library structure: fp().fn() + const circuitJson = fp().pdip8().circuitJson() + const pins = circuitJson.filter((e) => e.type === "pcb_plated_hole") + expect(pins.length).toBe(8) + + // Find pins by port_hints (standard in tscircuit) + const pin1 = pins.find((p: any) => p.port_hints?.includes("1")) as any + const pin2 = pins.find((p: any) => p.port_hints?.includes("2")) as any + const pin8 = pins.find((p: any) => p.port_hints?.includes("8")) as any + + expect(pin1).toBeDefined() + expect(Math.abs(pin1.x - -3.81)).toBeLessThan(0.01) + expect(Math.abs(pin1.y - 3.81)).toBeLessThan(0.01) + expect(Math.abs(pin2.y - 1.27)).toBeLessThan(0.01) + expect(Math.abs(pin8.x - 3.81)).toBeLessThan(0.01) + }) + + it("pdip should work with custom pin count", () => { + const circuitJson = fp().pdip(14).circuitJson() + const pins = circuitJson.filter((e) => e.type === "pcb_plated_hole") + expect(pins.length).toBe(14) + }) +}) diff --git a/tests/pinrow.test.ts b/tests/pinrow.test.ts index d5078b4c..2a6ad7e3 100644 --- a/tests/pinrow.test.ts +++ b/tests/pinrow.test.ts @@ -141,7 +141,7 @@ for (const textAlign of textAlignments) { } // Construct snapshot name similar to the definition string but more readable for file names - let snapshotName = `pinrow5_textalign${textAlign}${orthoState.name}${invertedState.name}` + const snapshotName = `pinrow5_textalign${textAlign}${orthoState.name}${invertedState.name}` test(`Test: ${def} (Snapshot: ${snapshotName})`, () => { const soup = fp.string(def).circuitJson()