@jlcpcb/core 0.1.0 → 0.2.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.
Files changed (114) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/api/easyeda-community.d.ts +36 -0
  3. package/dist/api/easyeda-community.d.ts.map +1 -0
  4. package/dist/api/easyeda.d.ts +23 -0
  5. package/dist/api/easyeda.d.ts.map +1 -0
  6. package/dist/api/index.d.ts +7 -0
  7. package/dist/api/index.d.ts.map +1 -0
  8. package/dist/api/jlc.d.ts +41 -0
  9. package/dist/api/jlc.d.ts.map +1 -0
  10. package/dist/assets/search.html +528 -0
  11. package/dist/browser/index.d.ts +8 -0
  12. package/dist/browser/index.d.ts.map +1 -0
  13. package/dist/browser/kicad-renderer.d.ts +13 -0
  14. package/dist/browser/kicad-renderer.d.ts.map +1 -0
  15. package/dist/browser/sexpr-parser.d.ts +84 -0
  16. package/dist/browser/sexpr-parser.d.ts.map +1 -0
  17. package/dist/constants/design-rules.d.ts +34 -0
  18. package/dist/constants/design-rules.d.ts.map +1 -0
  19. package/dist/constants/footprints.d.ts +134 -0
  20. package/dist/constants/footprints.d.ts.map +1 -0
  21. package/dist/constants/index.d.ts +7 -0
  22. package/dist/constants/index.d.ts.map +1 -0
  23. package/dist/constants/kicad.d.ts +67 -0
  24. package/dist/constants/kicad.d.ts.map +1 -0
  25. package/dist/converter/category-router.d.ts +47 -0
  26. package/dist/converter/category-router.d.ts.map +1 -0
  27. package/dist/converter/footprint-mapper.d.ts +40 -0
  28. package/dist/converter/footprint-mapper.d.ts.map +1 -0
  29. package/dist/converter/footprint-mapper.test.d.ts +2 -0
  30. package/dist/converter/footprint-mapper.test.d.ts.map +1 -0
  31. package/dist/converter/footprint.d.ts +116 -0
  32. package/dist/converter/footprint.d.ts.map +1 -0
  33. package/dist/converter/global-lib-table.d.ts +29 -0
  34. package/dist/converter/global-lib-table.d.ts.map +1 -0
  35. package/dist/converter/index.d.ts +12 -0
  36. package/dist/converter/index.d.ts.map +1 -0
  37. package/dist/converter/lib-table.d.ts +61 -0
  38. package/dist/converter/lib-table.d.ts.map +1 -0
  39. package/dist/converter/svg-arc.d.ts +45 -0
  40. package/dist/converter/svg-arc.d.ts.map +1 -0
  41. package/dist/converter/symbol-templates.d.ts +34 -0
  42. package/dist/converter/symbol-templates.d.ts.map +1 -0
  43. package/dist/converter/symbol.d.ts +223 -0
  44. package/dist/converter/symbol.d.ts.map +1 -0
  45. package/dist/converter/value-normalizer.d.ts +33 -0
  46. package/dist/converter/value-normalizer.d.ts.map +1 -0
  47. package/dist/http/index.d.ts +5 -0
  48. package/dist/http/index.d.ts.map +1 -0
  49. package/dist/http/routes.d.ts +12 -0
  50. package/dist/http/routes.d.ts.map +1 -0
  51. package/dist/http/server.d.ts +18 -0
  52. package/dist/http/server.d.ts.map +1 -0
  53. package/dist/index.d.ts +13 -0
  54. package/dist/index.d.ts.map +1 -0
  55. package/dist/index.js +9633 -0
  56. package/dist/parsers/easyeda-shapes.d.ts +115 -0
  57. package/dist/parsers/easyeda-shapes.d.ts.map +1 -0
  58. package/dist/parsers/http-client.d.ts +16 -0
  59. package/dist/parsers/http-client.d.ts.map +1 -0
  60. package/dist/parsers/index.d.ts +11 -0
  61. package/dist/parsers/index.d.ts.map +1 -0
  62. package/dist/parsers/utils.d.ts +17 -0
  63. package/dist/parsers/utils.d.ts.map +1 -0
  64. package/dist/services/component-service.d.ts +31 -0
  65. package/dist/services/component-service.d.ts.map +1 -0
  66. package/dist/services/fix-service.d.ts +40 -0
  67. package/dist/services/fix-service.d.ts.map +1 -0
  68. package/dist/services/index.d.ts +8 -0
  69. package/dist/services/index.d.ts.map +1 -0
  70. package/dist/services/library-service.d.ts +112 -0
  71. package/dist/services/library-service.d.ts.map +1 -0
  72. package/dist/types/component.d.ts +56 -0
  73. package/dist/types/component.d.ts.map +1 -0
  74. package/dist/types/easyeda-community.d.ts +74 -0
  75. package/dist/types/easyeda-community.d.ts.map +1 -0
  76. package/dist/types/easyeda.d.ts +326 -0
  77. package/dist/types/easyeda.d.ts.map +1 -0
  78. package/dist/types/index.d.ts +12 -0
  79. package/dist/types/index.d.ts.map +1 -0
  80. package/dist/types/jlc.d.ts +78 -0
  81. package/dist/types/jlc.d.ts.map +1 -0
  82. package/dist/types/kicad.d.ts +141 -0
  83. package/dist/types/kicad.d.ts.map +1 -0
  84. package/dist/types/mcp.d.ts +66 -0
  85. package/dist/types/mcp.d.ts.map +1 -0
  86. package/dist/types/project.d.ts +60 -0
  87. package/dist/types/project.d.ts.map +1 -0
  88. package/dist/utils/conversion.d.ts +59 -0
  89. package/dist/utils/conversion.d.ts.map +1 -0
  90. package/dist/utils/file-system.d.ts +59 -0
  91. package/dist/utils/file-system.d.ts.map +1 -0
  92. package/dist/utils/index.d.ts +8 -0
  93. package/dist/utils/index.d.ts.map +1 -0
  94. package/dist/utils/logger.d.ts +26 -0
  95. package/dist/utils/logger.d.ts.map +1 -0
  96. package/dist/utils/validation.d.ts +259 -0
  97. package/dist/utils/validation.d.ts.map +1 -0
  98. package/package.json +5 -3
  99. package/scripts/build-search-page.ts +68 -0
  100. package/src/assets/search-built.html +528 -0
  101. package/src/assets/search.html +458 -0
  102. package/src/browser/index.ts +389 -0
  103. package/src/browser/kicad-renderer.ts +813 -0
  104. package/src/browser/sexpr-parser.ts +333 -0
  105. package/src/converter/footprint-mapper.test.ts +159 -0
  106. package/src/converter/footprint-mapper.ts +42 -134
  107. package/src/converter/footprint.ts +208 -36
  108. package/src/converter/global-lib-table.ts +71 -0
  109. package/src/http/index.ts +5 -0
  110. package/src/http/routes.ts +266 -0
  111. package/src/http/server.ts +83 -0
  112. package/src/index.ts +3 -0
  113. package/src/parsers/easyeda-shapes.ts +2 -1
  114. package/src/services/library-service.ts +73 -22
@@ -0,0 +1,528 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>EasyEDA Component Browser</title>
7
+ <style>
8
+ * {
9
+ box-sizing: border-box;
10
+ margin: 0;
11
+ padding: 0;
12
+ }
13
+
14
+ :root {
15
+ --bg-primary: #1a1a1a;
16
+ --bg-secondary: #2a2a2a;
17
+ --bg-card: #333333;
18
+ --text-primary: #ffffff;
19
+ --text-secondary: #aaaaaa;
20
+ --accent: #4a9eff;
21
+ --accent-hover: #6ab0ff;
22
+ --success: #22c55e;
23
+ --error: #ef4444;
24
+ --border: #444444;
25
+ }
26
+
27
+ body {
28
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
29
+ background: var(--bg-primary);
30
+ color: var(--text-primary);
31
+ min-height: 100vh;
32
+ }
33
+
34
+ header {
35
+ background: var(--bg-secondary);
36
+ padding: 20px;
37
+ border-bottom: 1px solid var(--border);
38
+ position: sticky;
39
+ top: 0;
40
+ z-index: 100;
41
+ }
42
+
43
+ .header-content {
44
+ max-width: 1400px;
45
+ margin: 0 auto;
46
+ }
47
+
48
+ h1 {
49
+ font-size: 1.5rem;
50
+ margin-bottom: 16px;
51
+ color: var(--text-primary);
52
+ }
53
+
54
+ .search-bar {
55
+ display: flex;
56
+ gap: 12px;
57
+ flex-wrap: wrap;
58
+ }
59
+
60
+ #search-input {
61
+ flex: 1;
62
+ min-width: 200px;
63
+ padding: 12px 16px;
64
+ font-size: 16px;
65
+ background: var(--bg-primary);
66
+ border: 1px solid var(--border);
67
+ border-radius: 8px;
68
+ color: var(--text-primary);
69
+ outline: none;
70
+ }
71
+
72
+ #search-input:focus {
73
+ border-color: var(--accent);
74
+ }
75
+
76
+ #source-select {
77
+ padding: 12px 16px;
78
+ font-size: 16px;
79
+ background: var(--bg-primary);
80
+ border: 1px solid var(--border);
81
+ border-radius: 8px;
82
+ color: var(--text-primary);
83
+ cursor: pointer;
84
+ }
85
+
86
+ #search-btn {
87
+ padding: 12px 24px;
88
+ font-size: 16px;
89
+ background: var(--accent);
90
+ border: none;
91
+ border-radius: 8px;
92
+ color: white;
93
+ cursor: pointer;
94
+ font-weight: 500;
95
+ transition: background 0.2s;
96
+ }
97
+
98
+ #search-btn:hover {
99
+ background: var(--accent-hover);
100
+ }
101
+
102
+ main {
103
+ max-width: 1400px;
104
+ margin: 0 auto;
105
+ padding: 24px;
106
+ }
107
+
108
+ #loading {
109
+ display: flex;
110
+ justify-content: center;
111
+ padding: 48px;
112
+ }
113
+
114
+ #loading.hidden {
115
+ display: none;
116
+ }
117
+
118
+ .spinner {
119
+ width: 40px;
120
+ height: 40px;
121
+ border: 3px solid var(--border);
122
+ border-top-color: var(--accent);
123
+ border-radius: 50%;
124
+ animation: spin 1s linear infinite;
125
+ }
126
+
127
+ @keyframes spin {
128
+ to { transform: rotate(360deg); }
129
+ }
130
+
131
+ #results-grid {
132
+ display: grid;
133
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
134
+ gap: 20px;
135
+ }
136
+
137
+ .card {
138
+ background: var(--bg-card);
139
+ border-radius: 12px;
140
+ overflow: hidden;
141
+ border: 1px solid var(--border);
142
+ transition: transform 0.2s, border-color 0.2s;
143
+ }
144
+
145
+ .card:hover {
146
+ transform: translateY(-2px);
147
+ border-color: var(--accent);
148
+ }
149
+
150
+ .card-images {
151
+ display: flex;
152
+ gap: 2px;
153
+ background: var(--border);
154
+ }
155
+
156
+ .image-container {
157
+ flex: 1;
158
+ aspect-ratio: 1;
159
+ background: #000;
160
+ display: flex;
161
+ flex-direction: column;
162
+ align-items: center;
163
+ justify-content: center;
164
+ position: relative;
165
+ cursor: pointer;
166
+ overflow: hidden;
167
+ }
168
+
169
+ .image-container img,
170
+ .image-container svg {
171
+ max-width: 100%;
172
+ max-height: 100%;
173
+ object-fit: contain;
174
+ }
175
+
176
+ .image-label {
177
+ position: absolute;
178
+ bottom: 4px;
179
+ left: 4px;
180
+ font-size: 10px;
181
+ color: var(--text-secondary);
182
+ background: rgba(0,0,0,0.7);
183
+ padding: 2px 6px;
184
+ border-radius: 4px;
185
+ }
186
+
187
+ .symbol-placeholder,
188
+ .footprint-placeholder,
189
+ .no-preview {
190
+ color: var(--text-secondary);
191
+ font-size: 12px;
192
+ }
193
+
194
+ .card-info {
195
+ padding: 12px;
196
+ }
197
+
198
+ .card-title {
199
+ font-weight: 600;
200
+ margin-bottom: 8px;
201
+ white-space: nowrap;
202
+ overflow: hidden;
203
+ text-overflow: ellipsis;
204
+ }
205
+
206
+ .card-package,
207
+ .card-owner {
208
+ font-size: 13px;
209
+ color: var(--text-secondary);
210
+ margin-bottom: 4px;
211
+ }
212
+
213
+ .card-uuid {
214
+ display: flex;
215
+ padding: 8px 12px;
216
+ background: var(--bg-secondary);
217
+ gap: 8px;
218
+ }
219
+
220
+ .card-uuid input {
221
+ flex: 1;
222
+ background: var(--bg-primary);
223
+ border: 1px solid var(--border);
224
+ border-radius: 4px;
225
+ padding: 6px 10px;
226
+ font-size: 11px;
227
+ font-family: monospace;
228
+ color: var(--text-secondary);
229
+ }
230
+
231
+ .copy-btn {
232
+ background: var(--accent);
233
+ border: none;
234
+ border-radius: 4px;
235
+ padding: 6px 10px;
236
+ cursor: pointer;
237
+ color: white;
238
+ display: flex;
239
+ align-items: center;
240
+ justify-content: center;
241
+ transition: background 0.2s;
242
+ }
243
+
244
+ .copy-btn:hover {
245
+ background: var(--accent-hover);
246
+ }
247
+
248
+ .copy-btn.copied {
249
+ background: var(--success);
250
+ }
251
+
252
+ #pagination {
253
+ display: flex;
254
+ justify-content: center;
255
+ align-items: center;
256
+ gap: 16px;
257
+ margin-top: 32px;
258
+ }
259
+
260
+ .page-btn {
261
+ padding: 10px 20px;
262
+ background: var(--bg-card);
263
+ border: 1px solid var(--border);
264
+ border-radius: 8px;
265
+ color: var(--text-primary);
266
+ cursor: pointer;
267
+ transition: background 0.2s, border-color 0.2s;
268
+ }
269
+
270
+ .page-btn:hover:not(:disabled) {
271
+ background: var(--bg-secondary);
272
+ border-color: var(--accent);
273
+ }
274
+
275
+ .page-btn:disabled {
276
+ opacity: 0.5;
277
+ cursor: not-allowed;
278
+ }
279
+
280
+ .page-info {
281
+ color: var(--text-secondary);
282
+ }
283
+
284
+ .no-results,
285
+ .error {
286
+ grid-column: 1 / -1;
287
+ text-align: center;
288
+ padding: 48px;
289
+ color: var(--text-secondary);
290
+ }
291
+
292
+ .error {
293
+ color: var(--error);
294
+ }
295
+
296
+ /* Modal */
297
+ #preview-modal {
298
+ position: fixed;
299
+ inset: 0;
300
+ background: rgba(0, 0, 0, 0.8);
301
+ display: flex;
302
+ align-items: center;
303
+ justify-content: center;
304
+ z-index: 1000;
305
+ padding: 20px;
306
+ }
307
+
308
+ #preview-modal.hidden {
309
+ display: none;
310
+ }
311
+
312
+ .modal-wrapper {
313
+ background: var(--bg-secondary);
314
+ border-radius: 16px;
315
+ max-width: 900px;
316
+ width: 100%;
317
+ max-height: 90vh;
318
+ overflow: auto;
319
+ position: relative;
320
+ }
321
+
322
+ #modal-close {
323
+ position: absolute;
324
+ top: 16px;
325
+ right: 16px;
326
+ background: var(--bg-card);
327
+ border: 1px solid var(--border);
328
+ border-radius: 8px;
329
+ padding: 8px 12px;
330
+ color: var(--text-primary);
331
+ cursor: pointer;
332
+ font-size: 18px;
333
+ z-index: 10;
334
+ }
335
+
336
+ #modal-close:hover {
337
+ background: var(--bg-primary);
338
+ }
339
+
340
+ #modal-content {
341
+ padding: 24px;
342
+ }
343
+
344
+ .modal-loading {
345
+ text-align: center;
346
+ padding: 48px;
347
+ color: var(--text-secondary);
348
+ }
349
+
350
+ .modal-error {
351
+ text-align: center;
352
+ padding: 48px;
353
+ color: var(--error);
354
+ }
355
+
356
+ .modal-header {
357
+ margin-bottom: 24px;
358
+ }
359
+
360
+ .modal-header h2 {
361
+ margin-bottom: 12px;
362
+ }
363
+
364
+ .modal-uuid {
365
+ display: flex;
366
+ align-items: center;
367
+ gap: 12px;
368
+ }
369
+
370
+ .modal-uuid code {
371
+ background: var(--bg-primary);
372
+ padding: 8px 12px;
373
+ border-radius: 6px;
374
+ font-size: 14px;
375
+ color: var(--text-secondary);
376
+ }
377
+
378
+ .modal-copy {
379
+ padding: 8px 16px;
380
+ font-size: 14px;
381
+ }
382
+
383
+ .modal-previews {
384
+ display: grid;
385
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
386
+ gap: 24px;
387
+ margin-bottom: 24px;
388
+ }
389
+
390
+ .modal-preview h3 {
391
+ margin-bottom: 12px;
392
+ font-size: 14px;
393
+ color: var(--text-secondary);
394
+ }
395
+
396
+ .preview-svg {
397
+ background: #000;
398
+ border-radius: 8px;
399
+ aspect-ratio: 1;
400
+ display: flex;
401
+ align-items: center;
402
+ justify-content: center;
403
+ overflow: hidden;
404
+ }
405
+
406
+ .preview-svg svg {
407
+ width: 100%;
408
+ height: 100%;
409
+ }
410
+
411
+ .preview-svg .no-preview {
412
+ color: var(--text-secondary);
413
+ }
414
+
415
+ .modal-info {
416
+ display: flex;
417
+ gap: 24px;
418
+ color: var(--text-secondary);
419
+ font-size: 14px;
420
+ }
421
+ </style>
422
+ </head>
423
+ <body>
424
+ <header>
425
+ <div class="header-content">
426
+ <h1>EasyEDA Component Browser</h1>
427
+ <div class="search-bar">
428
+ <input type="text" id="search-input" placeholder="Search components (e.g., ESP32, STM32, LM7805)..." autofocus />
429
+ <select id="source-select">
430
+ <option value="user">Community</option>
431
+ <option value="lcsc">LCSC</option>
432
+ <option value="all">All Sources</option>
433
+ </select>
434
+ <button id="search-btn">Search</button>
435
+ </div>
436
+ </div>
437
+ </header>
438
+
439
+ <main>
440
+ <div id="loading" class="hidden">
441
+ <div class="spinner"></div>
442
+ </div>
443
+ <div id="results-grid"></div>
444
+ <div id="pagination"></div>
445
+ </main>
446
+
447
+ <div id="preview-modal" class="hidden">
448
+ <div class="modal-wrapper">
449
+ <button id="modal-close">&times;</button>
450
+ <div id="modal-content"></div>
451
+ </div>
452
+ </div>
453
+
454
+ <script>
455
+ function EJ(Z){let $=[],J=0;while(J<Z.length){let K=Z[J];if(/\s/.test(K)){J++;continue}if(K==="("||K===")"){$.push(K),J++;continue}if(K==='"'){let V="";J++;while(J<Z.length)if(Z[J]==="\\"&&J+1<Z.length)V+=Z[J+1],J+=2;else if(Z[J]==='"'){J++;break}else V+=Z[J],J++;$.push(`"${V}"`);continue}let U="";while(J<Z.length&&!/[\s()]/.test(Z[J]))U+=Z[J],J++;if(U)$.push(U)}return $}function ZJ(Z){if(Z.length===0)return{expr:[],remaining:[]};let $=Z[0];if($==="("){let K=[],U=Z.slice(1);while(U.length>0&&U[0]!==")"){let{expr:V,remaining:j}=ZJ(U);K.push(V),U=j}if(U[0]===")")U=U.slice(1);return{expr:K,remaining:U}}if($===")")return{expr:[],remaining:Z.slice(1)};let J=$;if(J.startsWith('"')&&J.endsWith('"'))J=J.slice(1,-1);return{expr:J,remaining:Z.slice(1)}}function d(Z){let $=EJ(Z),{expr:J}=ZJ($);return J}function A(Z){return Array.isArray(Z)}function X(Z){return typeof Z==="string"}function T(Z){if(A(Z)&&Z.length>0&&X(Z[0]))return Z[0];return}function z(Z,$){if(!A(Z))return;for(let J of Z)if(A(J)&&T(J)===$)return J;return}function I(Z,$){if(!A(Z))return[];let J=[];for(let K of Z)if(A(K)&&T(K)===$)J.push(K);return J}function y(Z,$){let J=z(Z,$);if(J&&J.length>=2&&X(J[1]))return J[1];return}function g(Z,$){let J=y(Z,$);if(J!==void 0){let K=parseFloat(J);if(!isNaN(K))return K}return}function _(Z,$){let J=z(Z,$);if(J&&J.length>=3){let K=parseFloat(X(J[1])?J[1]:""),U=parseFloat(X(J[2])?J[2]:"");if(!isNaN(K)&&!isNaN(U))return{x:K,y:U}}return}function c(Z,$){let J=z(Z,$);if(J&&J.length>=3){let K=parseFloat(X(J[1])?J[1]:""),U=parseFloat(X(J[2])?J[2]:"");if(!isNaN(K)&&!isNaN(U)){let V={x:K,y:U};if(J.length>=4&&X(J[3])){let j=parseFloat(J[3]);if(!isNaN(j))V.rotation=j}return V}}return}function o(Z){let $=z(Z,"size");if($&&$.length>=3){let J=parseFloat(X($[1])?$[1]:""),K=parseFloat(X($[2])?$[2]:"");if(!isNaN(J)&&!isNaN(K))return{width:J,height:K}}return}function P(Z){let $=z(Z,"stroke");if(!$)return;let J=g($,"width")??0.254,K=y($,"type")??"default";return{width:J,type:K}}function L(Z){let $=z(Z,"fill");if(!$)return;let J=y($,"type");if(J)return J;if($.length>=2&&X($[1]))return $[1];return}function u(Z){let $=z(Z,"pts");if(!$)return[];let J=[];for(let K of $)if(A(K)&&T(K)==="xy"&&K.length>=3){let U=parseFloat(X(K[1])?K[1]:""),V=parseFloat(X(K[2])?K[2]:"");if(!isNaN(U)&&!isNaN(V))J.push({x:U,y:V})}return J}function v(Z){let $=y(Z,"layer");if($)return[$];let J=z(Z,"layers");if(!J)return[];let K=[];for(let U=1;U<J.length;U++){let V=J[U];if(X(V))K.push(V)}return K}var B={background:"#FFFFF8",body:"#840000",bodyFill:"#FFFFC4",pin:"#840000",pinText:"#008484",text:"#000000"},w={background:"#000000",fCu:"#840000",bCu:"#008400",in1Cu:"#C2C200",in2Cu:"#C200C2",fSilkS:"#008484",bSilkS:"#840084",fMask:"#840084",bMask:"#848400",fPaste:"#840000",bPaste:"#00C2C2",fFab:"#848484",bFab:"#000084",fCrtYd:"#C2C2C2",bCrtYd:"#848484",edgeCuts:"#C2C200",dwgsUser:"#C2C2C2",cmtsUser:"#848484",margin:"#C200C2",padFront:"#840000",padBack:"#008400",padThruHole:"#C2C200",drill:"#848484"},f=10;function b(Z){return Z.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function a(Z){if(!Z||Z.trim()==="")return S("No symbol data");try{let $=d(Z);if(!A($)||T($)!=="symbol")return S("Invalid symbol format");let J=[],K={minX:1/0,maxX:-1/0,minY:1/0,maxY:-1/0},U=I($,"symbol");for(let D of U){for(let H of I(D,"rectangle")){let W=XJ(H,K);if(W)J.push(W)}for(let H of I(D,"polyline")){let W=wJ(H,K);if(W)J.push(W)}for(let H of I(D,"circle")){let W=MJ(H,K);if(W)J.push(W)}for(let H of I(D,"arc")){let W=IJ(H,K);if(W)J.push(W)}for(let H of I(D,"pin")){let W=YJ(H,K);if(W)J.push(W)}}let V=5;if(!isFinite(K.minX))K.minX=-20,K.maxX=20,K.minY=-20,K.maxY=20;let j=(K.maxX-K.minX+V*2)*f,Q=(K.maxY-K.minY+V*2)*f;return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="${`${(K.minX-V)*f} ${(-K.maxY-V)*f} ${j} ${Q}`}" width="100%" height="100%" style="background-color: ${B.background}">
456
+ <g transform="scale(${f}, ${-f})">
457
+ ${J.join(`
458
+ `)}
459
+ </g>
460
+ </svg>`}catch($){return S(`Parse error: ${$}`)}}function XJ(Z,$){let J=_(Z,"start"),K=_(Z,"end");if(!J||!K)return"";let U=P(Z),j=L(Z)==="background"?B.bodyFill:"none";E($,J.x,J.y),E($,K.x,K.y);let Q=Math.min(J.x,K.x),G=Math.min(J.y,K.y),D=Math.abs(K.x-J.x),H=Math.abs(K.y-J.y);return`<rect x="${Q}" y="${G}" width="${D}" height="${H}" fill="${j}" stroke="${B.body}" stroke-width="${U?.width??0.254}"/>`}function wJ(Z,$){let J=u(Z);if(J.length<2)return"";let K=P(Z),V=L(Z)==="background"?B.bodyFill:"none";return`<polyline points="${J.map((Q)=>{return E($,Q.x,Q.y),`${Q.x},${Q.y}`}).join(" ")}" fill="${V}" stroke="${B.body}" stroke-width="${K?.width??0.254}" stroke-linecap="round" stroke-linejoin="round"/>`}function MJ(Z,$){let J=_(Z,"center"),K=g(Z,"radius");if(!J||K===void 0)return"";let U=P(Z),j=L(Z)==="background"?B.bodyFill:"none";return E($,J.x-K,J.y-K),E($,J.x+K,J.y+K),`<circle cx="${J.x}" cy="${J.y}" r="${K}" fill="${j}" stroke="${B.body}" stroke-width="${U?.width??0.254}"/>`}function IJ(Z,$){let J=_(Z,"start"),K=_(Z,"mid"),U=_(Z,"end");if(!J||!K||!U)return"";let V=P(Z);return E($,J.x,J.y),E($,K.x,K.y),E($,U.x,U.y),`<path d="${jJ(J,K,U)}" fill="none" stroke="${B.body}" stroke-width="${V?.width??0.254}" stroke-linecap="round"/>`}function jJ(Z,$,J){let{x:K,y:U}=Z,V=$.x,j=$.y,Q=J.x,G=J.y,D=2*(K*(j-G)+V*(G-U)+Q*(U-j));if(Math.abs(D)<0.0001)return`M ${Z.x} ${Z.y} L ${J.x} ${J.y}`;let H=((K*K+U*U)*(j-G)+(V*V+j*j)*(G-U)+(Q*Q+G*G)*(U-j))/D,W=((K*K+U*U)*(Q-V)+(V*V+j*j)*(K-Q)+(Q*Q+G*G)*(V-K))/D,q=Math.sqrt((K-H)**2+(U-W)**2),M=(V-K)*(G-U)-(j-U)*(Q-K)>0?0:1,N=0;return`M ${Z.x} ${Z.y} A ${q} ${q} 0 ${N} ${M} ${J.x} ${J.y}`}function YJ(Z,$){let J=c(Z,"at"),K=g(Z,"length")??2.54;if(!J)return"";let U=z(Z,"name"),V=z(Z,"number"),j=U&&U.length>=2&&X(U[1])?U[1]:"",Q=V&&V.length>=2&&X(V[1])?V[1]:"",G=J.rotation??0,D=G*Math.PI/180,H=J.x+K*Math.cos(D),W=J.y+K*Math.sin(D);E($,J.x,J.y),E($,H,W);let q=[];if(q.push(`<line x1="${J.x}" y1="${J.y}" x2="${H}" y2="${W}" stroke="${B.pin}" stroke-width="0.254"/>`),q.push(`<circle cx="${J.x}" cy="${J.y}" r="0.3" fill="${B.pin}"/>`),j&&j!=="~"){let M=H,N=W,k="start",F="middle";if(G===0)M=H+0.5,k="start";else if(G===180)M=H-0.5,k="end";else if(G===90)N=W+0.5,F="hanging",k="middle";else if(G===270)N=W-0.5,F="alphabetic",k="middle";q.push(`<text x="${M}" y="${N}" fill="${B.pinText}" font-size="1" font-family="sans-serif" text-anchor="${k}" dominant-baseline="${F}" transform="scale(1,-1) translate(0,${-2*N})">${b(j)}</text>`)}if(Q){let Y=(J.x+H)/2,M=(J.y+W)/2,N=G===0||G===180?0.8:0;q.push(`<text x="${Y}" y="${M+N}" fill="${B.pinText}" font-size="0.8" font-family="sans-serif" text-anchor="middle" dominant-baseline="middle" transform="scale(1,-1) translate(0,${-2*(M+N)})">${b(Q)}</text>`)}return q.join(`
461
+ `)}function s(Z){if(!Z||Z.trim()==="")return S("No footprint data");try{let $=d(Z);if(!A($)||T($)!=="footprint")return S("Invalid footprint format");let J=[],K={minX:1/0,maxX:-1/0,minY:1/0,maxY:-1/0};for(let G of I($,"pad")){let D=NJ(G,K);if(D)J.push(D)}for(let G of I($,"fp_line")){let D=$J(G,K);if(D)J.push(D)}for(let G of I($,"fp_circle")){let D=KJ(G,K);if(D)J.push(D)}for(let G of I($,"fp_arc")){let D=UJ(G,K);if(D)J.push(D)}for(let G of I($,"fp_rect")){let D=DJ(G,K);if(D)J.push(D)}for(let G of I($,"fp_poly")){let D=VJ(G,K);if(D)J.push(D)}for(let G of I($,"gr_line")){let D=$J(G,K);if(D)J.push(D)}for(let G of I($,"gr_circle")){let D=KJ(G,K);if(D)J.push(D)}for(let G of I($,"gr_arc")){let D=UJ(G,K);if(D)J.push(D)}for(let G of I($,"gr_rect")){let D=DJ(G,K);if(D)J.push(D)}for(let G of I($,"gr_poly")){let D=VJ(G,K);if(D)J.push(D)}for(let G of I($,"fp_text")){let D=zJ(G,K);if(D)J.push(D)}let U=1;if(!isFinite(K.minX))K.minX=-5,K.maxX=5,K.minY=-5,K.maxY=5;let V=K.maxX-K.minX+U*2,j=K.maxY-K.minY+U*2;return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="${`${K.minX-U} ${K.minY-U} ${V} ${j}`}" width="100%" height="100%" style="background-color: ${w.background}">
462
+ <g>
463
+ ${J.join(`
464
+ `)}
465
+ </g>
466
+ </svg>`}catch($){return S(`Parse error: ${$}`)}}function C(Z){if(Z.includes("F.Cu"))return w.fCu;if(Z.includes("B.Cu"))return w.bCu;if(/In\d+\.Cu/.test(Z))return w.in1Cu;if(Z.includes("F.SilkS"))return w.fSilkS;if(Z.includes("B.SilkS"))return w.bSilkS;if(Z.includes("F.Mask"))return w.fMask;if(Z.includes("B.Mask"))return w.bMask;if(Z.includes("F.Paste"))return w.fPaste;if(Z.includes("B.Paste"))return w.bPaste;if(Z.includes("F.Fab"))return w.fFab;if(Z.includes("B.Fab"))return w.bFab;if(Z.includes("F.CrtYd"))return w.fCrtYd;if(Z.includes("B.CrtYd"))return w.bCrtYd;if(Z.includes("Edge.Cuts"))return w.edgeCuts;if(Z.includes("Dwgs.User"))return w.dwgsUser;if(Z.includes("Cmts.User"))return w.cmtsUser;if(Z.includes("Margin"))return w.margin;return w.fSilkS}function NJ(Z,$){if(!A(Z)||Z.length<4)return"";let J=X(Z[1])?Z[1]:"",K=X(Z[2])?Z[2]:"",U=X(Z[3])?Z[3]:"",V=c(Z,"at"),j=o(Z);if(!V||!j)return"";E($,V.x-j.width/2,V.y-j.height/2),E($,V.x+j.width/2,V.y+j.height/2);let Q=[],G=v(Z),D;if(K==="thru_hole"||K==="np_thru_hole")D=w.padThruHole;else if(G.some((q)=>q.includes("B.")))D=w.padBack;else D=w.padFront;let H=V.rotation??0,W=H!==0?` transform="rotate(${H}, ${V.x}, ${V.y})"`:"";if(U==="circle"){let q=Math.min(j.width,j.height)/2;Q.push(`<circle cx="${V.x}" cy="${V.y}" r="${q}" fill="${D}"${W}/>`)}else if(U==="oval"){let q=j.width/2,Y=j.height/2;Q.push(`<ellipse cx="${V.x}" cy="${V.y}" rx="${q}" ry="${Y}" fill="${D}"${W}/>`)}else if(U==="roundrect"){let q=g(Z,"roundrect_rratio")??0.25,Y=Math.min(j.width,j.height)*q/2,M=V.x-j.width/2,N=V.y-j.height/2;Q.push(`<rect x="${M}" y="${N}" width="${j.width}" height="${j.height}" rx="${Y}" fill="${D}"${W}/>`)}else if(U==="custom"){let q=z(Z,"primitives");if(q)for(let Y of I(q,"gr_poly")){let M=u(Y);if(M.length>=3){let N=M.map((k)=>{let F=V.x+k.x,m=V.y+k.y;return E($,F,m),`${F},${m}`}).join(" ");Q.push(`<polygon points="${N}" fill="${D}"${W}/>`)}}if(Q.length===0){let Y=V.x-j.width/2,M=V.y-j.height/2;Q.push(`<rect x="${Y}" y="${M}" width="${j.width}" height="${j.height}" fill="${D}"${W}/>`)}}else{let q=V.x-j.width/2,Y=V.y-j.height/2;Q.push(`<rect x="${q}" y="${Y}" width="${j.width}" height="${j.height}" fill="${D}"${W}/>`)}if(K==="thru_hole"||K==="np_thru_hole"){let q=z(Z,"drill");if(q&&q.length>=2)if(X(q[1])&&q[1]==="oval"&&q.length>=4){let M=parseFloat(X(q[2])?q[2]:"0"),N=parseFloat(X(q[3])?q[3]:"0");Q.push(`<ellipse cx="${V.x}" cy="${V.y}" rx="${M/2}" ry="${N/2}" fill="${w.drill}"${W}/>`)}else{let M=parseFloat(X(q[1])?q[1]:"0");Q.push(`<circle cx="${V.x}" cy="${V.y}" r="${M/2}" fill="${w.drill}"/>`)}}if(J){let q=Math.min(j.width,j.height)*0.5;Q.push(`<text x="${V.x}" y="${V.y}" fill="#FFFFFF" font-size="${q}" font-family="sans-serif" text-anchor="middle" dominant-baseline="central">${b(J)}</text>`)}return Q.join(`
467
+ `)}function $J(Z,$){let J=_(Z,"start"),K=_(Z,"end");if(!J||!K)return"";let U=P(Z),j=v(Z)[0]??"F.SilkS";if(j.includes("CrtYd"))return"";let Q=C(j);return E($,J.x,J.y),E($,K.x,K.y),`<line x1="${J.x}" y1="${J.y}" x2="${K.x}" y2="${K.y}" stroke="${Q}" stroke-width="${U?.width??0.15}" stroke-linecap="round"/>`}function KJ(Z,$){let J=_(Z,"center"),K=_(Z,"end");if(!J||!K)return"";let U=Math.sqrt((K.x-J.x)**2+(K.y-J.y)**2),V=P(Z),Q=v(Z)[0]??"F.SilkS";if(Q.includes("CrtYd"))return"";let G=C(Q);return E($,J.x-U,J.y-U),E($,J.x+U,J.y+U),`<circle cx="${J.x}" cy="${J.y}" r="${U}" fill="none" stroke="${G}" stroke-width="${V?.width??0.15}"/>`}function UJ(Z,$){let J=_(Z,"start"),K=_(Z,"mid"),U=_(Z,"end");if(!J||!K||!U)return"";let V=P(Z),Q=v(Z)[0]??"F.SilkS";if(Q.includes("CrtYd"))return"";let G=C(Q);return E($,J.x,J.y),E($,K.x,K.y),E($,U.x,U.y),`<path d="${jJ(J,K,U)}" fill="none" stroke="${G}" stroke-width="${V?.width??0.15}" stroke-linecap="round"/>`}function VJ(Z,$){let J=u(Z);if(J.length<3)return"";let U=v(Z)[0]??"F.Cu";if(U.includes("CrtYd"))return"";let V=C(U),j=P(Z),Q=L(Z),G=Q==="solid"||Q==="yes"?V:"none",D=J.map((q)=>{return E($,q.x,q.y),`${q.x},${q.y}`}).join(" "),H=j?.width??0,W=H>0?` stroke="${V}" stroke-width="${H}"`:"";return`<polygon points="${D}" fill="${G}"${W}/>`}function DJ(Z,$){let J=_(Z,"start"),K=_(Z,"end");if(!J||!K)return"";let V=v(Z)[0]??"F.SilkS";if(V.includes("CrtYd"))return"";let j=C(V),Q=P(Z),D=L(Z)==="solid"?j:"none";E($,J.x,J.y),E($,K.x,K.y);let H=Math.min(J.x,K.x),W=Math.min(J.y,K.y),q=Math.abs(K.x-J.x),Y=Math.abs(K.y-J.y);return`<rect x="${H}" y="${W}" width="${q}" height="${Y}" fill="${D}" stroke="${j}" stroke-width="${Q?.width??0.15}"/>`}function zJ(Z,$){if(!A(Z)||Z.length<3)return"";let J=X(Z[1])?Z[1]:"",K=X(Z[2])?Z[2]:"";if(J==="reference"||J==="value")return"";let U=c(Z,"at");if(!U)return"";let j=v(Z)[0]??"F.SilkS",Q=C(j),G=z(Z,"effects"),D=1,H="middle";if(G){let N=z(G,"font");if(N){let F=o(N);if(F)D=F.height}let k=z(G,"justify");if(k)for(let F=1;F<k.length;F++){let m=X(k[F])?k[F]:"";if(m==="left")H="start";else if(m==="right")H="end"}}let W=K.length*D*0.6,q=D;if(H==="start")E($,U.x,U.y-q/2),E($,U.x+W,U.y+q/2);else if(H==="end")E($,U.x-W,U.y-q/2),E($,U.x,U.y+q/2);else E($,U.x-W/2,U.y-q/2),E($,U.x+W/2,U.y+q/2);let Y=U.rotation??0,M=Y!==0?` transform="rotate(${Y}, ${U.x}, ${U.y})"`:"";return`<text x="${U.x}" y="${U.y}" dy="0.35em" fill="${Q}" font-size="${D}" font-family="sans-serif" text-anchor="${H}"${M}>${b(K)}</text>`}function E(Z,$,J){Z.minX=Math.min(Z.minX,$),Z.maxX=Math.max(Z.maxX,$),Z.minY=Math.min(Z.minY,J),Z.maxY=Math.max(Z.maxY,J)}function S(Z){return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" width="100%" height="100%">
468
+ <rect width="200" height="100" fill="#FFF0F0"/>
469
+ <text x="100" y="50" fill="#CC0000" font-size="12" font-family="sans-serif" text-anchor="middle" dominant-baseline="central">${b(Z)}</text>
470
+ </svg>`}var JJ=1,h="",WJ="user",i=!1,n=null,O=document.getElementById("search-input"),GJ=document.getElementById("source-select"),_J=document.getElementById("search-btn"),e=document.getElementById("results-grid"),r=document.getElementById("pagination"),FJ=document.getElementById("loading"),l=document.getElementById("preview-modal"),p=document.getElementById("modal-content"),kJ=document.getElementById("modal-close");function qJ(){let Z=window.__INITIAL_QUERY__;if(Z)O.value=Z,h=Z,R();else{let J=new URLSearchParams(window.location.search).get("q");if(J)O.value=J,h=J,R()}O.addEventListener("input",BJ),O.addEventListener("keydown",($)=>{if($.key==="Enter")$.preventDefault(),R()}),_J.addEventListener("click",R),GJ.addEventListener("change",()=>{if(WJ=GJ.value,h)R()}),kJ.addEventListener("click",t),l.addEventListener("click",($)=>{if($.target===l)t()}),document.addEventListener("keydown",($)=>{if($.key==="Escape")t()})}function BJ(){if(n)clearTimeout(n);n=window.setTimeout(()=>{let Z=O.value.trim();if(Z&&Z!==h)h=Z,JJ=1,R()},300)}async function R(){let Z=O.value.trim();if(!Z||i)return;h=Z,i=!0,QJ(!0);try{let $=new URLSearchParams({q:Z,source:WJ,page:String(JJ),limit:"20"}),J=await fetch(`/api/search?${$}`);if(!J.ok)throw Error("Search failed");let K=await J.json();AJ(K.results),RJ(K.pagination)}catch($){console.error("Search error:",$),e.innerHTML='<div class="error">Search failed. Please try again.</div>'}finally{i=!1,QJ(!1)}}function AJ(Z){if(Z.length===0){e.innerHTML='<div class="no-results">No components found. Try a different search term.</div>';return}e.innerHTML=Z.map(($)=>`
471
+ <div class="card" data-uuid="${$.uuid}">
472
+ <div class="card-images">
473
+ <div class="image-container symbol-container" data-uuid="${$.uuid}">
474
+ <div class="symbol-placeholder">Loading...</div>
475
+ <div class="image-label">Symbol</div>
476
+ </div>
477
+ <div class="image-container footprint-container" data-uuid="${$.uuid}">
478
+ <div class="footprint-placeholder">Loading...</div>
479
+ <div class="image-label">Footprint</div>
480
+ </div>
481
+ </div>
482
+ <div class="card-info">
483
+ <div class="card-title" title="${x($.title)}">${x($.title)}</div>
484
+ <div class="card-package">Package: ${x($.package||"Unknown")}</div>
485
+ <div class="card-owner">By: ${x($.owner.nickname||$.owner.username)}</div>
486
+ </div>
487
+ <div class="card-uuid">
488
+ <input type="text" value="${$.uuid}" readonly />
489
+ <button class="copy-btn" data-uuid="${$.uuid}" title="Copy UUID">
490
+ <svg viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>
491
+ </button>
492
+ </div>
493
+ </div>
494
+ `).join(""),document.querySelectorAll(".copy-btn").forEach(($)=>{$.addEventListener("click",(J)=>{J.stopPropagation();let K=$.dataset.uuid;if(K)HJ(K,$)})}),document.querySelectorAll(".image-container").forEach(($)=>{$.addEventListener("click",async()=>{let J=$.dataset.uuid;if(J)vJ(J)})}),Z.forEach(($)=>PJ($.uuid))}async function PJ(Z){let $=document.querySelector(`.symbol-container[data-uuid="${Z}"]`),J=document.querySelector(`.footprint-container[data-uuid="${Z}"]`);if(!$&&!J)return;try{let K=await fetch(`/api/component/${Z}`);if(!K.ok){if($)$.innerHTML='<div class="no-preview">Error</div><div class="image-label">Symbol</div>';if(J)J.innerHTML='<div class="no-preview">Error</div><div class="image-label">Footprint</div>';return}let U=await K.json();if($)if(U.symbolSexpr){let V=a(U.symbolSexpr);$.innerHTML=V+'<div class="image-label">Symbol</div>'}else $.innerHTML='<div class="no-preview">No preview</div><div class="image-label">Symbol</div>';if(J)if(U.footprintSexpr){let V=s(U.footprintSexpr);J.innerHTML=V+'<div class="image-label">Footprint</div>'}else J.innerHTML='<div class="no-preview">No preview</div><div class="image-label">Footprint</div>'}catch{if($)$.innerHTML='<div class="no-preview">Error</div><div class="image-label">Symbol</div>';if(J)J.innerHTML='<div class="no-preview">Error</div><div class="image-label">Footprint</div>'}}async function vJ(Z){l.classList.remove("hidden"),p.innerHTML='<div class="modal-loading">Loading...</div>';try{let $=await fetch(`/api/component/${Z}`);if(!$.ok)throw Error("Failed to fetch component");let J=await $.json(),K=J.symbolSexpr?a(J.symbolSexpr):"",U=J.footprintSexpr?s(J.footprintSexpr):"";p.innerHTML=`
495
+ <div class="modal-header">
496
+ <h2>${x(J.title)}</h2>
497
+ <div class="modal-uuid">
498
+ <code>${J.uuid}</code>
499
+ <button class="copy-btn modal-copy" data-uuid="${J.uuid}">Copy UUID</button>
500
+ </div>
501
+ </div>
502
+ <div class="modal-previews">
503
+ <div class="modal-preview">
504
+ <h3>Symbol (KiCad)</h3>
505
+ <div class="preview-svg">${K||'<div class="no-preview">No symbol preview</div>'}</div>
506
+ </div>
507
+ <div class="modal-preview">
508
+ <h3>Footprint (KiCad)</h3>
509
+ <div class="preview-svg">${U||'<div class="no-preview">No footprint preview</div>'}</div>
510
+ </div>
511
+ </div>
512
+ <div class="modal-info">
513
+ <p><strong>Description:</strong> ${x(J.description||"N/A")}</p>
514
+ ${J.model3d?"<p><strong>3D Model:</strong> Available</p>":""}
515
+ </div>
516
+ `;let V=p.querySelector(".modal-copy");if(V)V.addEventListener("click",()=>{HJ(J.uuid,V)})}catch($){console.error("Modal error:",$),p.innerHTML='<div class="modal-error">Failed to load component details</div>'}}function t(){l.classList.add("hidden")}function RJ(Z){if(Z.totalPages<=1){r.innerHTML="";return}r.innerHTML=`
517
+ <button class="page-btn" ${Z.hasPrev?"":"disabled"} data-page="${Z.page-1}">
518
+ ← Prev
519
+ </button>
520
+ <span class="page-info">Page ${Z.page} of ${Z.totalPages}</span>
521
+ <button class="page-btn" ${Z.hasNext?"":"disabled"} data-page="${Z.page+1}">
522
+ Next →
523
+ </button>
524
+ `,r.querySelectorAll(".page-btn").forEach(($)=>{$.addEventListener("click",()=>{let J=parseInt($.dataset.page||"1",10);if(J>0)JJ=J,R(),window.scrollTo(0,0)})})}async function HJ(Z,$){try{await navigator.clipboard.writeText(Z),$.classList.add("copied"),setTimeout(()=>$.classList.remove("copied"),1500)}catch{let J=document.createElement("input");J.value=Z,document.body.appendChild(J),J.select(),document.execCommand("copy"),document.body.removeChild(J),$.classList.add("copied"),setTimeout(()=>$.classList.remove("copied"),1500)}}function QJ(Z){FJ.classList.toggle("hidden",!Z)}function x(Z){let $=document.createElement("div");return $.textContent=Z,$.innerHTML}if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",qJ);else qJ();
525
+
526
+ </script>
527
+ </body>
528
+ </html>
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Browser app for EasyEDA Component Browser
3
+ * Handles search, rendering, and user interactions
4
+ *
5
+ * Uses KiCad S-expression renderer for symbol/footprint previews
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * KiCad S-Expression to SVG Renderer
3
+ * Renders KiCad symbols and footprints from S-expression format
4
+ */
5
+ /**
6
+ * Render KiCad symbol S-expression to SVG
7
+ */
8
+ export declare function renderSymbolSvg(sexpr: string): string;
9
+ /**
10
+ * Render KiCad footprint S-expression to SVG
11
+ */
12
+ export declare function renderFootprintSvg(sexpr: string): string;
13
+ //# sourceMappingURL=kicad-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kicad-renderer.d.ts","sourceRoot":"","sources":["../../src/browser/kicad-renderer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAuFH;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAwErD;AA2LD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAoGxD"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * S-Expression Parser for KiCad format
3
+ * Parses KiCad symbol and footprint S-expressions for browser-side rendering
4
+ */
5
+ export type SExpr = string | SExpr[];
6
+ /**
7
+ * Parse S-expression string into nested structure
8
+ */
9
+ export declare function parseSExpr(input: string): SExpr;
10
+ /**
11
+ * Check if expression is a list
12
+ */
13
+ export declare function isList(expr: SExpr): expr is SExpr[];
14
+ /**
15
+ * Check if expression is an atom (string)
16
+ */
17
+ export declare function isAtom(expr: SExpr): expr is string;
18
+ /**
19
+ * Get the first element of a list (the tag/type)
20
+ */
21
+ export declare function getTag(expr: SExpr): string | undefined;
22
+ /**
23
+ * Find a child element by its tag name
24
+ * Returns first match or undefined
25
+ */
26
+ export declare function findChild(expr: SExpr, tag: string): SExpr[] | undefined;
27
+ /**
28
+ * Find all child elements with a given tag
29
+ */
30
+ export declare function findChildren(expr: SExpr, tag: string): SExpr[][];
31
+ /**
32
+ * Get a simple attribute value: (tag value) -> value
33
+ */
34
+ export declare function getAttr(expr: SExpr, tag: string): string | undefined;
35
+ /**
36
+ * Get a numeric attribute value
37
+ */
38
+ export declare function getNumericAttr(expr: SExpr, tag: string): number | undefined;
39
+ /**
40
+ * Get a point from (tag x y) format
41
+ */
42
+ export declare function getPoint(expr: SExpr, tag: string): {
43
+ x: number;
44
+ y: number;
45
+ } | undefined;
46
+ /**
47
+ * Get point with optional rotation: (tag x y [rotation])
48
+ */
49
+ export declare function getPointWithRotation(expr: SExpr, tag: string): {
50
+ x: number;
51
+ y: number;
52
+ rotation?: number;
53
+ } | undefined;
54
+ /**
55
+ * Get size from (size w h) format
56
+ */
57
+ export declare function getSize(expr: SExpr): {
58
+ width: number;
59
+ height: number;
60
+ } | undefined;
61
+ /**
62
+ * Get stroke properties from (stroke ...) element
63
+ */
64
+ export declare function getStroke(expr: SExpr): {
65
+ width: number;
66
+ type: string;
67
+ } | undefined;
68
+ /**
69
+ * Get fill type from (fill ...) element
70
+ * Handles both (fill solid) and (fill (type solid)) formats
71
+ */
72
+ export declare function getFillType(expr: SExpr): string | undefined;
73
+ /**
74
+ * Get all XY points from (pts (xy x y) (xy x y) ...) structure
75
+ */
76
+ export declare function getPoints(expr: SExpr): Array<{
77
+ x: number;
78
+ y: number;
79
+ }>;
80
+ /**
81
+ * Get layers from (layers "Layer1" "Layer2" ...) or (layer "Layer")
82
+ */
83
+ export declare function getLayers(expr: SExpr): string[];
84
+ //# sourceMappingURL=sexpr-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sexpr-parser.d.ts","sourceRoot":"","sources":["../../src/browser/sexpr-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,KAAK,EAAE,CAAA;AAyGpC;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAI/C;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,IAAI,KAAK,EAAE,CAEnD;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,IAAI,MAAM,CAElD;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,CAKtD;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,SAAS,CASvE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,EAAE,EAAE,CAUhE;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMpE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO3E;AAED;;GAEG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,KAAK,EACX,GAAG,EAAE,MAAM,GACV;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAUtC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,KAAK,EACX,GAAG,EAAE,MAAM,GACV;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAiBzD;AAED;;GAEG;AACH,wBAAgB,OAAO,CACrB,IAAI,EAAE,KAAK,GACV;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAU/C;AAED;;GAEG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,KAAK,GACV;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAQ7C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,CAc3D;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAgBtE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,EAAE,CAiB/C"}