@jlcpcb/core 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.
- package/CHANGELOG.md +10 -0
- package/README.md +474 -0
- package/package.json +48 -0
- package/src/api/easyeda-community.ts +259 -0
- package/src/api/easyeda.ts +153 -0
- package/src/api/index.ts +7 -0
- package/src/api/jlc.ts +185 -0
- package/src/constants/design-rules.ts +119 -0
- package/src/constants/footprints.ts +68 -0
- package/src/constants/index.ts +7 -0
- package/src/constants/kicad.ts +147 -0
- package/src/converter/category-router.ts +638 -0
- package/src/converter/footprint-mapper.ts +236 -0
- package/src/converter/footprint.ts +949 -0
- package/src/converter/global-lib-table.ts +394 -0
- package/src/converter/index.ts +46 -0
- package/src/converter/lib-table.ts +181 -0
- package/src/converter/svg-arc.ts +179 -0
- package/src/converter/symbol-templates.ts +214 -0
- package/src/converter/symbol.ts +1682 -0
- package/src/converter/value-normalizer.ts +262 -0
- package/src/index.ts +25 -0
- package/src/parsers/easyeda-shapes.ts +628 -0
- package/src/parsers/http-client.ts +96 -0
- package/src/parsers/index.ts +38 -0
- package/src/parsers/utils.ts +29 -0
- package/src/services/component-service.ts +100 -0
- package/src/services/fix-service.ts +50 -0
- package/src/services/index.ts +9 -0
- package/src/services/library-service.ts +696 -0
- package/src/types/component.ts +61 -0
- package/src/types/easyeda-community.ts +78 -0
- package/src/types/easyeda.ts +356 -0
- package/src/types/index.ts +12 -0
- package/src/types/jlc.ts +84 -0
- package/src/types/kicad.ts +136 -0
- package/src/types/mcp.ts +77 -0
- package/src/types/project.ts +60 -0
- package/src/utils/conversion.ts +104 -0
- package/src/utils/file-system.ts +143 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/logger.ts +96 -0
- package/src/utils/validation.ts +110 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KiCad Standard Footprint Mapper
|
|
3
|
+
* Maps common package names to KiCad built-in footprints for hybrid approach
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { getLibraryCategory, type LibraryCategory } from './category-router.js';
|
|
7
|
+
|
|
8
|
+
export interface FootprintMapping {
|
|
9
|
+
library: string; // KiCad library name (e.g., "Resistor_SMD")
|
|
10
|
+
footprint: string; // Footprint name (e.g., "R_0603_1608Metric")
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// SMD passive size mappings (Imperial to KiCad naming)
|
|
14
|
+
const SMD_SIZES: Record<string, { metric: string; imperialMm: string }> = {
|
|
15
|
+
'0201': { metric: '0603', imperialMm: '0.6x0.3' },
|
|
16
|
+
'0402': { metric: '1005', imperialMm: '1.0x0.5' },
|
|
17
|
+
'0603': { metric: '1608', imperialMm: '1.6x0.8' },
|
|
18
|
+
'0805': { metric: '2012', imperialMm: '2.0x1.2' },
|
|
19
|
+
'1206': { metric: '3216', imperialMm: '3.2x1.6' },
|
|
20
|
+
'1210': { metric: '3225', imperialMm: '3.2x2.5' },
|
|
21
|
+
'1812': { metric: '4532', imperialMm: '4.5x3.2' },
|
|
22
|
+
'2010': { metric: '5025', imperialMm: '5.0x2.5' },
|
|
23
|
+
'2512': { metric: '6332', imperialMm: '6.3x3.2' },
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Prefix to library mapping for passives
|
|
27
|
+
const PASSIVE_LIBRARIES: Record<string, string> = {
|
|
28
|
+
R: 'Resistor_SMD',
|
|
29
|
+
C: 'Capacitor_SMD',
|
|
30
|
+
L: 'Inductor_SMD',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// LED/Diode libraries
|
|
34
|
+
const LED_LIBRARY = 'LED_SMD';
|
|
35
|
+
const DIODE_LIBRARY = 'Diode_SMD';
|
|
36
|
+
|
|
37
|
+
// Map library categories to footprint prefixes (for category-based fallback)
|
|
38
|
+
const CATEGORY_TO_PREFIX: Partial<Record<LibraryCategory, string>> = {
|
|
39
|
+
Resistors: 'R',
|
|
40
|
+
Capacitors: 'C',
|
|
41
|
+
Inductors: 'L',
|
|
42
|
+
Diodes: 'D',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// SOIC package mappings
|
|
46
|
+
const SOIC_MAPPINGS: Record<string, string> = {
|
|
47
|
+
'SOIC-8': 'SOIC-8_3.9x4.9mm_P1.27mm',
|
|
48
|
+
'SOP-8': 'SOIC-8_3.9x4.9mm_P1.27mm',
|
|
49
|
+
'SOIC-14': 'SOIC-14_3.9x8.7mm_P1.27mm',
|
|
50
|
+
'SOIC-16': 'SOIC-16_3.9x9.9mm_P1.27mm',
|
|
51
|
+
'SOIC-16W': 'SOIC-16W_7.5x10.3mm_P1.27mm',
|
|
52
|
+
'SOIC-20': 'SOIC-20W_7.5x12.8mm_P1.27mm',
|
|
53
|
+
'SOIC-24': 'SOIC-24W_7.5x15.4mm_P1.27mm',
|
|
54
|
+
'SOIC-28': 'SOIC-28W_7.5x17.9mm_P1.27mm',
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// TSSOP package mappings
|
|
58
|
+
const TSSOP_MAPPINGS: Record<string, string> = {
|
|
59
|
+
'TSSOP-8': 'TSSOP-8_3x3mm_P0.65mm',
|
|
60
|
+
'TSSOP-14': 'TSSOP-14_4.4x5mm_P0.65mm',
|
|
61
|
+
'TSSOP-16': 'TSSOP-16_4.4x5mm_P0.65mm',
|
|
62
|
+
'TSSOP-20': 'TSSOP-20_4.4x6.5mm_P0.65mm',
|
|
63
|
+
'TSSOP-24': 'TSSOP-24_4.4x7.8mm_P0.65mm',
|
|
64
|
+
'TSSOP-28': 'TSSOP-28_4.4x9.7mm_P0.65mm',
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// SOT package mappings
|
|
68
|
+
const SOT_MAPPINGS: Record<string, { library: string; footprint: string }> = {
|
|
69
|
+
'SOT-23': { library: 'Package_TO_SOT_SMD', footprint: 'SOT-23' },
|
|
70
|
+
'SOT-23-3': { library: 'Package_TO_SOT_SMD', footprint: 'SOT-23' },
|
|
71
|
+
'SOT-23-5': { library: 'Package_TO_SOT_SMD', footprint: 'SOT-23-5' },
|
|
72
|
+
'SOT-23-6': { library: 'Package_TO_SOT_SMD', footprint: 'SOT-23-6' },
|
|
73
|
+
'SOT-89': { library: 'Package_TO_SOT_SMD', footprint: 'SOT-89-3' },
|
|
74
|
+
'SOT-223': { library: 'Package_TO_SOT_SMD', footprint: 'SOT-223-3_TabPin2' },
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// SOD diode package mappings
|
|
78
|
+
const SOD_MAPPINGS: Record<string, { library: string; footprint: string }> = {
|
|
79
|
+
'SOD-123': { library: 'Diode_SMD', footprint: 'D_SOD-123' },
|
|
80
|
+
'SOD-123F': { library: 'Diode_SMD', footprint: 'D_SOD-123F' },
|
|
81
|
+
'SOD-323': { library: 'Diode_SMD', footprint: 'D_SOD-323' },
|
|
82
|
+
'SOD-523': { library: 'Diode_SMD', footprint: 'D_SOD-523' },
|
|
83
|
+
'SOD-923': { library: 'Diode_SMD', footprint: 'D_SOD-923' },
|
|
84
|
+
'SOD-128': { library: 'Diode_SMD', footprint: 'D_SOD-128' },
|
|
85
|
+
'SOD-80': { library: 'Diode_SMD', footprint: 'D_SOD-80' },
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// SMA/SMB/SMC diode package mappings
|
|
89
|
+
const DIODE_PACKAGE_MAPPINGS: Record<string, { library: string; footprint: string }> = {
|
|
90
|
+
'SMA': { library: 'Diode_SMD', footprint: 'D_SMA' },
|
|
91
|
+
'SMB': { library: 'Diode_SMD', footprint: 'D_SMB' },
|
|
92
|
+
'SMC': { library: 'Diode_SMD', footprint: 'D_SMC' },
|
|
93
|
+
'MELF': { library: 'Diode_SMD', footprint: 'D_MELF' },
|
|
94
|
+
'MINIMELF': { library: 'Diode_SMD', footprint: 'D_MiniMELF' },
|
|
95
|
+
'MICROMELF': { library: 'Diode_SMD', footprint: 'D_MicroMELF' },
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Normalize package name for matching
|
|
100
|
+
* - Uppercase
|
|
101
|
+
* - Remove common variations in naming
|
|
102
|
+
*/
|
|
103
|
+
function normalizePackageName(name: string): string {
|
|
104
|
+
return name
|
|
105
|
+
.toUpperCase()
|
|
106
|
+
.replace(/[_\s-]+/g, '-')
|
|
107
|
+
.replace(/\(.*?\)/g, '') // Remove parenthetical info like "(1608)"
|
|
108
|
+
.trim();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Extract imperial size code from package name
|
|
113
|
+
* Handles variations like "0603", "SMD0603", "LED0603-RD", "0603(1608)"
|
|
114
|
+
*/
|
|
115
|
+
function extractSmdSize(packageName: string): string | null {
|
|
116
|
+
const normalized = normalizePackageName(packageName);
|
|
117
|
+
|
|
118
|
+
// Direct match
|
|
119
|
+
for (const size of Object.keys(SMD_SIZES)) {
|
|
120
|
+
if (normalized === size || normalized === `SMD${size}`) {
|
|
121
|
+
return size;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Pattern match for sizes anywhere in name
|
|
126
|
+
// Allows prefixes like LED, SMD, etc. and suffixes like -RD, -BL
|
|
127
|
+
const sizePattern = /(0201|0402|0603|0805|1206|1210|1812|2010|2512)(?![0-9])/;
|
|
128
|
+
const match = normalized.match(sizePattern);
|
|
129
|
+
return match ? match[1] : null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Map package name to KiCad standard footprint
|
|
134
|
+
* Returns null if no standard mapping exists (will fall back to generated)
|
|
135
|
+
*/
|
|
136
|
+
export function mapToKicadFootprint(
|
|
137
|
+
packageName: string,
|
|
138
|
+
componentPrefix: string,
|
|
139
|
+
category?: string,
|
|
140
|
+
description?: string
|
|
141
|
+
): FootprintMapping | null {
|
|
142
|
+
const normalized = normalizePackageName(packageName);
|
|
143
|
+
let prefix = componentPrefix.toUpperCase();
|
|
144
|
+
|
|
145
|
+
// Category-based prefix fallback: if prefix doesn't match known mappings,
|
|
146
|
+
// try to detect the correct prefix from category/description
|
|
147
|
+
const isKnownPrefix = PASSIVE_LIBRARIES[prefix] || prefix === 'D' || prefix === 'LED';
|
|
148
|
+
if (!isKnownPrefix && (category || description)) {
|
|
149
|
+
const detectedCategory = getLibraryCategory(prefix, category, description);
|
|
150
|
+
const categoryPrefix = CATEGORY_TO_PREFIX[detectedCategory];
|
|
151
|
+
if (categoryPrefix) {
|
|
152
|
+
prefix = categoryPrefix;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// 1. Check SMD passive sizes (R, C, L)
|
|
157
|
+
const smdSize = extractSmdSize(packageName);
|
|
158
|
+
if (smdSize && PASSIVE_LIBRARIES[prefix]) {
|
|
159
|
+
const sizeInfo = SMD_SIZES[smdSize];
|
|
160
|
+
const library = PASSIVE_LIBRARIES[prefix];
|
|
161
|
+
// KiCad naming: R_0603_1608Metric, C_0603_1608Metric, L_0603_1608Metric
|
|
162
|
+
const footprint = `${prefix}_${smdSize}_${sizeInfo.metric}Metric`;
|
|
163
|
+
return { library, footprint };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// 2. Check LED SMD sizes (for LED prefix or components detected as LEDs)
|
|
167
|
+
if (smdSize && prefix === 'LED') {
|
|
168
|
+
const sizeInfo = SMD_SIZES[smdSize];
|
|
169
|
+
// KiCad naming: LED_0805_2012Metric
|
|
170
|
+
const footprint = `LED_${smdSize}_${sizeInfo.metric}Metric`;
|
|
171
|
+
return { library: LED_LIBRARY, footprint };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// 3. Check Diode SMD sizes (D prefix)
|
|
175
|
+
if (smdSize && prefix === 'D') {
|
|
176
|
+
const sizeInfo = SMD_SIZES[smdSize];
|
|
177
|
+
// KiCad naming: D_0805_2012Metric
|
|
178
|
+
const footprint = `D_${smdSize}_${sizeInfo.metric}Metric`;
|
|
179
|
+
return { library: DIODE_LIBRARY, footprint };
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// 4. Check SOD diode packages
|
|
183
|
+
for (const [pattern, mapping] of Object.entries(SOD_MAPPINGS)) {
|
|
184
|
+
if (normalized.includes(pattern) || normalized.startsWith(pattern.replace(/-/g, ''))) {
|
|
185
|
+
return mapping;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// 5. Check SMA/SMB/SMC diode packages
|
|
190
|
+
for (const [pattern, mapping] of Object.entries(DIODE_PACKAGE_MAPPINGS)) {
|
|
191
|
+
// Match exact package type or with suffix (e.g., "SMA" in "SMA_L4.3...")
|
|
192
|
+
if (normalized === pattern || normalized.startsWith(pattern + '-') || normalized.startsWith(pattern + '_')) {
|
|
193
|
+
return mapping;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// 6. Check SOIC packages
|
|
198
|
+
for (const [pattern, footprint] of Object.entries(SOIC_MAPPINGS)) {
|
|
199
|
+
if (normalized.includes(pattern) || normalized.startsWith(pattern.replace(/-/g, ''))) {
|
|
200
|
+
return { library: 'Package_SO', footprint };
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// 7. Check TSSOP packages
|
|
205
|
+
for (const [pattern, footprint] of Object.entries(TSSOP_MAPPINGS)) {
|
|
206
|
+
if (normalized.includes(pattern) || normalized.startsWith(pattern.replace(/-/g, ''))) {
|
|
207
|
+
return { library: 'Package_SO', footprint };
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// 8. Check SOT packages
|
|
212
|
+
for (const [pattern, mapping] of Object.entries(SOT_MAPPINGS)) {
|
|
213
|
+
if (normalized.includes(pattern) || normalized === pattern.replace(/-/g, '')) {
|
|
214
|
+
return mapping;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// No standard mapping found - will use generated footprint
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Get full KiCad footprint reference string
|
|
224
|
+
* Format: "Library:Footprint"
|
|
225
|
+
*/
|
|
226
|
+
export function getKicadFootprintRef(mapping: FootprintMapping): string {
|
|
227
|
+
return `${mapping.library}:${mapping.footprint}`;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Check if a package is likely a standard passive that can use KiCad footprints
|
|
232
|
+
*/
|
|
233
|
+
export function isStandardPassive(packageName: string, prefix: string): boolean {
|
|
234
|
+
const smdSize = extractSmdSize(packageName);
|
|
235
|
+
return smdSize !== null && PASSIVE_LIBRARIES[prefix.toUpperCase()] !== undefined;
|
|
236
|
+
}
|