diff --git a/src/footprinter.ts b/src/footprinter.ts
index fa51a3b4..46125f03 100644
--- a/src/footprinter.ts
+++ b/src/footprinter.ts
@@ -270,6 +270,7 @@ export type Footprinter = {
const normalizeDefinition = (def: string): string => {
return def
.trim()
+ .replace(/^spdip-?(?=[\d_]|$)/i, "dip")
.replace(/^pinheader(?=[\d_]|$)/i, "pinrow")
.replace(/^sot23-(\d+)(?=_|$)/i, "sot23_$1")
.replace(/^sot-223-(\d+)(?=_|$)/i, "sot223_$1")
diff --git a/tests/__snapshots__/spdip28.snap.svg b/tests/__snapshots__/spdip28.snap.svg
new file mode 100644
index 00000000..f76aef94
--- /dev/null
+++ b/tests/__snapshots__/spdip28.snap.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tests/kicad-parity/__snapshots__/spdip28.snap.svg b/tests/kicad-parity/__snapshots__/spdip28.snap.svg
new file mode 100644
index 00000000..4e803cfd
--- /dev/null
+++ b/tests/kicad-parity/__snapshots__/spdip28.snap.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tests/kicad-parity/__snapshots__/spdip28_boolean_difference.snap.svg b/tests/kicad-parity/__snapshots__/spdip28_boolean_difference.snap.svg
new file mode 100644
index 00000000..7eb320ef
--- /dev/null
+++ b/tests/kicad-parity/__snapshots__/spdip28_boolean_difference.snap.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/tests/kicad-parity/spdip28_kicad_parity.test.ts b/tests/kicad-parity/spdip28_kicad_parity.test.ts
new file mode 100644
index 00000000..edb6c26c
--- /dev/null
+++ b/tests/kicad-parity/spdip28_kicad_parity.test.ts
@@ -0,0 +1,24 @@
+import { expect, test } from "bun:test"
+import { convertCircuitJsonToPcbSvg } from "circuit-to-svg"
+import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad"
+
+test("parity/spdip28", async () => {
+ const {
+ combinedFootprintElements,
+ booleanDifferenceSvg,
+ courtyardDiffPercent,
+ } = await compareFootprinterVsKicad(
+ "spdip28",
+ "Package_DIP.pretty/DIP-28_W7.62mm.circuit.json",
+ )
+
+ const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements, {
+ showCourtyards: true,
+ })
+ expect(courtyardDiffPercent).toBeLessThan(0.5)
+ expect(svgContent).toMatchSvgSnapshot(import.meta.path, "spdip28")
+ expect(booleanDifferenceSvg).toMatchSvgSnapshot(
+ import.meta.path,
+ "spdip28_boolean_difference",
+ )
+})
diff --git a/tests/spdip.test.ts b/tests/spdip.test.ts
new file mode 100644
index 00000000..33be389e
--- /dev/null
+++ b/tests/spdip.test.ts
@@ -0,0 +1,17 @@
+import { expect, test } from "bun:test"
+import type { AnyCircuitElement } from "circuit-json"
+import { convertCircuitJsonToPcbSvg } from "circuit-to-svg"
+import { fp } from "../src/footprinter"
+
+test("spdip28 resolves to the DIP-28 footprint", () => {
+ expect(fp.string("spdip28").json()).toEqual(fp.string("dip28").json())
+ expect(fp.string("SPDIP-28_W7.62mm").json()).toEqual(
+ fp.string("dip28_w7.62mm").json(),
+ )
+})
+
+test("spdip28 renders as a DIP-28 footprint", () => {
+ const circuitJson = fp.string("spdip28").circuitJson() as AnyCircuitElement[]
+ const svgContent = convertCircuitJsonToPcbSvg(circuitJson)
+ expect(svgContent).toMatchSvgSnapshot(import.meta.path, "spdip28")
+})