← Commit history

pinout: keep every pin inside the body, and make the JSON button work

Ray ·f49a8f49d1 ·1mo ago ·parent ead7c46
Two fixes that shipped in adom-widget on Aug 24 (28e23c3) but never reached this page, because sections/pinout.html carries its own inline copy of the widget. The corner overhang: the pin run was distributed across the full inner..outer span while the body is drawn inset from the outermost pins, so the first and last pin of every side landed 4.33px past the corner and crossed its neighbour (1 into 48, 12 into 13, 24 into 25, 36 into 37). Measured on this page: body spans 76..324, the pin run spanned 71.67..328.33. With the corner keep-out the run is 95.5..304.5, inside the body on every side. The JSON button: it built a blob: URL, and this renders inside the readme's sandboxed frame whose CSP has no blob:, so the button did nothing and said nothing. Now a data: URL, verified to produce 8769 chars instead of a refused 46-char blob: href.
1 file changed +20−10
sections/pinout.html+20−10
@@ -314,22 +314,30 @@ body{margin:0;padding:4px 0 10px;background:transparent;         return { ...p, x, y, side };       });     } else {+      // The body is drawn inset from the outermost pins, so a run distributed+      // across the whole inner..outer span puts the FIRST and LAST pin of each+      // side OUTSIDE the body: at 12 per side they land 4.3px past each corner+      // and cross the end pin of the neighbouring side (1 into 48, 12 into 13,+      // 24 into 25, 36 into 37). Real quad packages have a corner keep-out+      // anyway, which is why the explicit-xy path never showed this. Inset the+      // run to match the body. Ported from adom-widget 28e23c3.       const N = edge.length, inner = pad, outer = S - pad, at = (a, b, t) => a + (b - a) * t;+      const CORNER = 26, runLo = inner + CORNER, runHi = outer - CORNER;       const quad = forced === 'quad' || (forced !== 'dual' && /QF|BGA|LGA|LCC|QFN|QFP/i.test(pkg || ''));       if (quad) {         const per = Math.ceil(N / 4);         laid = edge.map((p, i) => {           const s = Math.floor(i / per), t = ((i % per) + 0.5) / per;-          if (s === 0) return { ...p, x: inner, y: at(inner, outer, t), side: 'left' };-          if (s === 1) return { ...p, x: at(inner, outer, t), y: outer, side: 'bottom' };-          if (s === 2) return { ...p, x: outer, y: at(outer, inner, t), side: 'right' };-          return { ...p, x: at(outer, inner, t), y: inner, side: 'top' };+          if (s === 0) return { ...p, x: inner, y: at(runLo, runHi, t), side: 'left' };+          if (s === 1) return { ...p, x: at(runLo, runHi, t), y: outer, side: 'bottom' };+          if (s === 2) return { ...p, x: outer, y: at(runHi, runLo, t), side: 'right' };+          return { ...p, x: at(runHi, runLo, t), y: inner, side: 'top' };         });       } else {         const half = Math.ceil(N / 2); // DIP-style: left top→bottom, right bottom→top         laid = edge.map((p, i) => i < half-          ? { ...p, x: inner, y: at(inner, outer, (i + 0.5) / half), side: 'left' }-          : { ...p, x: outer, y: at(outer, inner, (i - half + 0.5) / (N - half)), side: 'right' });+          ? { ...p, x: inner, y: at(runLo, runHi, (i + 0.5) / half), side: 'left' }+          : { ...p, x: outer, y: at(runHi, runLo, (i - half + 0.5) / (N - half)), side: 'right' });       }     }     centers.forEach(p => laid.push({ ...p, x: mid, y: mid, side: 'center' }));@@ -459,10 +467,12 @@ body{margin:0;padding:4px 0 10px;background:transparent;     _exportJson() { return JSON.stringify(this.toJSON(), null, 2); }     _exportName() { const d = this._data || {}; return ((d.mpn || 'pinout') + (d.package ? '-' + d.package : '')).replace(/[^\w.-]+/g, '_') + '.pins.json'; }     _download() {-      const blob = new Blob([this._exportJson()], { type: 'application/json' });-      const url = URL.createObjectURL(blob), a = document.createElement('a');-      a.href = url; a.download = this._exportName(); document.body.appendChild(a); a.click();-      a.remove(); setTimeout(() => URL.revokeObjectURL(url), 1000);+      // data:, not blob:. This renders inside the readme's sandboxed frame,+      // whose CSP carries no blob:, so createObjectURL was refused and the+      // button did nothing at all without saying so.+      const a = document.createElement('a');+      a.href = 'data:application/json;charset=utf-8,' + encodeURIComponent(this._exportJson());+      a.download = this._exportName(); document.body.appendChild(a); a.click(); a.remove();     }     async _copy(btn) {       const txt = this._exportJson(), done = () => { if (!btn) return; const o = btn.textContent; btn.textContent = 'copied'; btn.classList.add('ok'); setTimeout(() => { btn.textContent = o; btn.classList.remove('ok'); }, 1100); };