main
John Lauer Publish 0.2.3 6e27c4b
// Render the dashboard's design-rule card (presentation.json rulesCard) with stub elements: no browser, no dashboard.
import fs from 'node:fs';
import vm from 'node:vm';
import assert from 'node:assert/strict';
const html=fs.readFileSync(new URL('../tools/timeline/index.html',import.meta.url),'utf8');
const start=html.indexOf('  // Design-rule sanity card');
const end=html.indexOf('  let presentation = null;',start);
assert(start>0 && end>start);
assert(html.includes('id="rules-card"'),'the card section is in the page');
const elements=new Map();
const node=()=>({hidden:true,children:[],attrs:{},textContent:'',innerHTML:'',replaceChildren(){this.children=[]},appendChild(c){this.children.push(c)},setAttribute(k,v){this.attrs[k]=v}});
const $=id=>{if(!elements.has(id))elements.set(id,node());return elements.get(id)};
const svgEl=(tag,attrs)=>{const n=node();n.tag=tag;n.attrs={...attrs};return n};
const esc=s=>String(s==null?'':s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
const ctx={$,svgEl,esc};
vm.createContext(ctx);vm.runInContext(html.slice(start,end)+'\nglobalThis.renderCard=renderRulesCard;',ctx);
ctx.renderCard(undefined);assert.equal($('rules-card').hidden,true,'no card, no section');
const card={lane:'fab',board:{widthMm:40,heightMm:30,outline:[[0,0],[40,0],[40,30],[0,30]]},draw:{traceMm:0.025,clearanceMm:0.2,viaPadMm:0.6,drillMm:0.3},
  items:[{key:'minTrace',label:'min trace',value:0.025,unit:'mm',source:'spec track',flag:'min trace 0.025 mm (spec track) is below the fab lane\'s 0.1 mm'}],
  loads:[{net:'+5V',amps:2,widestMm:0.5}],flags:['min trace 0.025 mm (spec track) is below the fab lane\'s 0.1 mm <b>'],note:'Read-only: this card changes no gate.'};
ctx.renderCard(card);
assert.equal($('rules-card').hidden,false);
assert($('rc-board').children.some(c=>c.tag==='polygon'),'board outline drawn');
assert.equal($('rc-board').attrs.viewBox.split(' ').length,4);
const traces=$('rc-detail').children.filter(c=>c.tag==='rect'&&c.attrs.width===0.025);
assert.equal(traces.length,2,'two min traces at their own width, to scale');
assert($('rc-detail').children.some(c=>c.tag==='circle'&&c.attrs.r===0.3),'via pad radius to scale');
assert($('rc-flags').innerHTML.includes('&lt;b&gt;'),'flag text is escaped');
assert($('rc-facts').innerHTML.includes('class="flag"'));
assert.match($('rc-note').textContent,/changes no gate/);
console.log('PASS: rules card hidden without data, outline and features to scale, flags escaped, read-only note');