app
Adom Library
Public Made by Adomby adom
adom-lbr — the EDA library translator. Bring a component in from any supported EDA tool and convert it to any other (KiCad ⇄ Altium ⇄ EAGLE/Fusion) through one canonical adom-lbr JSON — symbol + footprint + 3D + pin↔pad map. Altium is written natively (no Altium needed). Includes the adom-lbr Manager: browse wiki components and view symbol/footprint/3D + the per-EDA layer stackup.
← Commit history
Manager: symbol/footprint columns now render via CANONICAL adom-symbol/adom-footprint embed (trustworthy witnesses, no home-grown SVG); declare deps (2.2.0)
2 files changed
+51−12
src/manage.html+7−12@@ -32,6 +32,8 @@ .cols{display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px} .card{background:var(--panel);border:1px solid var(--edge);border-radius:12px;overflow:hidden;display:flex;flex-direction:column} .card h3{margin:0;padding:9px 12px;font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:var(--mut);border-bottom:1px solid var(--edge)}+ .card h3 small{text-transform:none;letter-spacing:0;color:#5b6675;font-weight:400}+ .card iframe.embed{width:100%;height:440px;border:0;background:#161b22;display:block} .card .body{aspect-ratio:1;width:100%;display:flex;align-items:center;justify-content:center;padding:10px;background:#161b22;overflow:hidden;cursor:grab;touch-action:none;position:relative} .card .body svg{max-width:100%;max-height:100%;will-change:transform} .card .hint2{position:absolute;bottom:6px;right:8px;font-size:10px;color:#b9c0cc;background:#0d0f14aa;border-radius:5px;padding:1px 6px;pointer-events:none}@@ -114,23 +116,16 @@ async function openPart(slug,el){ v.innerHTML=` <h2 class="title">${p.mpn} <small>· ${p.pins} pins · ${p.pads} pads</small></h2> <div class="cols">- <div class="card"><h3>Schematic Symbol</h3><div class="body">${p.symbol_svg}<span class="hint2">drag · scroll to zoom</span></div></div>- <div class="card"><h3>Footprint</h3>- <div class="lfilter">${(p.layers||[]).map(l=>`<label class="chip"><input type="checkbox" checked data-key="${l.key}"><span class="sw" style="background:${COLORS[l.role]||'#888'}"></span>${l.role}</label>`).join('')}</div>- <div class="body" id="fpbody">${p.footprint_svg}<span class="hint2">drag · scroll to zoom</span></div></div>+ <div class="card"><h3>Schematic Symbol <small>· via adom-symbol</small></h3><iframe class="embed" src="embed/symbol/${slug}" loading="lazy" title="symbol viewer"></iframe></div>+ <div class="card"><h3>Footprint <small>· via adom-footprint</small></h3><iframe class="embed" src="embed/footprint/${slug}" loading="lazy" title="footprint viewer"></iframe></div> <div class="card"><h3>3D Model</h3>${glb}</div> </div> <div class="stacktitle">Footprint layer stackup — what each element becomes per EDA tool</div> <table><thead><tr><th>Element (neutral role)</th><th>KiCad layer</th><th>Altium layer</th></tr></thead> <tbody>${rows}</tbody></table>`;- v.querySelectorAll('.card .body').forEach(makePannable);- // footprint layer filter — toggle visibility of each layer's SVG elements- v.querySelectorAll('.lfilter input').forEach(cb=>{- cb.onchange=()=>{- v.querySelectorAll('#fpbody svg .ly-'+cb.dataset.key).forEach(el=>{el.style.display=cb.checked?'':'none';});- };- });- setupHighlight(v);+ // Symbol + footprint are now canonical interactive iframes (adom-symbol /+ // adom-footprint embed) with their OWN pan/zoom + layer/pin panels — nothing+ // to wire here. The 3D column keeps its own viewer. } // Hover a pin (symbol) or pad (footprint) → highlight it + show its number and
src/manage.rs+44@@ -64,6 +64,16 @@ fn route(method: &Method, url: &str) -> Response<Cursor<Vec<u8>>> { None => Response::from_string("no glb").with_status_code(404), } }+ // Canonical interactive viewers — the symbol/footprint columns render via+ // the AUTHORITATIVE tools (adom-symbol / adom-footprint `embed`) so the+ // Manager faithfully shows what the real pipeline produces, not a+ // home-grown SVG that could quietly diverge from ground truth.+ (Method::Get, p) if p.starts_with("/embed/symbol/") => {+ embed_view(&p["/embed/symbol/".len()..], "kicad_sym", "adom-symbol")+ }+ (Method::Get, p) if p.starts_with("/embed/footprint/") => {+ embed_view(&p["/embed/footprint/".len()..], "kicad_mod", "adom-footprint")+ } _ => Response::from_string("not found").with_status_code(404), } }@@ -124,6 +134,40 @@ fn list_components() -> Value { "hints": ["click a component to open its viewer"] }) } +/// Render a component's canonical INTERACTIVE viewer by shelling out to the+/// authoritative tool's `embed` (`adom-symbol` / `adom-footprint`) on the wiki+/// source file. Self-contained HTML, iframed by the Manager — no external assets,+/// no home-grown SVG. Requires the tool to be installed (declared as a dep).+fn embed_view(slug: &str, ext: &str, tool: &str) -> Response<Cursor<Vec<u8>>> {+ let page = |msg: &str, code: u16| {+ Response::from_string(format!(+ "<body style='margin:0;background:#0d1117;color:#8b949e;font:13px -apple-system,sans-serif;display:flex;align-items:center;justify-content:center;height:100vh'><div>{msg}</div></body>"+ )).with_header(hdr("text/html; charset=utf-8")).with_status_code(code)+ };+ let mpn = up(slug);+ let src = match wiki_text(slug, &format!("{mpn}.{ext}")) {+ Some(t) if !t.trim_start().starts_with('<') && !t.contains("\"error\"") => t,+ _ => return page(&format!("no {ext} on the wiki for {mpn}"), 200),+ };+ let base = std::env::temp_dir().join(format!("adomlbr-mgr-{slug}"));+ let infile = base.with_extension(ext);+ let outfile = base.with_extension("embed.html");+ if std::fs::write(&infile, src.as_bytes()).is_err() {+ return page("temp write failed", 500);+ }+ let ok = Command::new(tool)+ .args(["embed", "--file", infile.to_str().unwrap_or(""),+ "--out", outfile.to_str().unwrap_or("")])+ .output().map(|o| o.status.success()).unwrap_or(false);+ if !ok {+ return page(&format!("{tool} embed unavailable — is {tool} installed?"), 200);+ }+ match std::fs::read(&outfile) {+ Ok(b) => Response::from_data(b).with_header(hdr("text/html; charset=utf-8")),+ Err(_) => page("embed read failed", 500),+ }+}+ /// Fetch a component and build its adom-lbr part FRESH on every call (nothing is /// cached), then render symbol/footprint SVG on the fly. The canonical adom-lbr /// JSON is the primary source; if the page has none, we import the KiCad files.