UNPKG

wiki-plugin-mech

Version:
31 lines (29 loc) 29.5 kB
/* wiki-plugin-mech - 0.1.33-0 - Thu, 20 Nov 2025 17:18:17 GMT */ (()=>{function tt(t,o){let i=[];for(let n of document.querySelectorAll(".item"))if(n.classList.contains(`${o}-source`)&&i.unshift(n),n===t)break;return i.map(n=>{let e=n[`${o}Data`],s=e?e():null;return{div:n,result:s}})}function et(t){let o=e=>Object.entries(e).filter(s=>s[1]).map(s=>`${s[0]}: ${s[1]}`).join("\\n"),i=t.nodes.map((e,s)=>{let r=e.type?`${e.type}\\n${e.props.name}`:e.props.name;return`${s} [label="${r}" ${e.props.url||e.props.tick?`URL="${e.props.url||"#"}" target="_blank"`:""} tooltip="${o(e.props)}"]`}),n=t.rels.map(e=>`${e.from}->${e.to} [label="${e.type}" labeltooltip="${o(e.props)}"]`);return["digraph {","rankdir=LR","node [shape=box style=filled fillcolor=palegreen]",...i,...n,"}"].join(` `)}function nt(t,o="steps",i,n={}){let e=(g,k)=>i.find(L=>L.slug==g&&(!k||L.domain==k)),s=g=>g?g.map(k=>e(k)):null,r=g=>Math.floor(g*Math.abs(Math.random()-Math.random())),c=g=>g[r(g.length)],l=g=>g.links&&Object.keys(g.links).length<10,u=g=>i.filter(k=>l(k)&&g in k.links),a=(g,k,L)=>L.findIndex(E=>E.slug==g.slug)===k,p=g=>g.toSorted((k,L)=>L.date-k.date).filter(a).slice(0,3),m=i.map(g=>g.domain).filter(B);function w(g){let k=new G,L=b=>k.addUniqNode("",{name:b.title.replaceAll(/ /g,` `),title:b.title,site:b.domain}),E=b=>s(b?.patterns?.up)??p(u(b.slug)),M=b=>b?.patterns?.down??Object.keys(b.links||{}),x=L(g);for(let b of E(g))k.addRel("",L(b),x);for(let b of M(g)){let A=e(b);if(A){let W=L(A);k.addRel("",x,W);for(let R of E(A))k.addRel("",L(R),W)}}return k}switch(o){case"steps":return d(t);case"days":return T(o,1,t);case"weeks":return T(o,7,t);case"months":return T(o,30,t);case"hubs":return H(t);case"references":return V();case"lineup":return F();case"topics":return Z(t)}function d(g=5){return m.map(k=>{let L=k.split(".").slice(0,3).join("."),E=new Set,M=new G,x=0,b=i.filter(f=>f.domain==k&&"links"in f);if(!b.length)return{name:L,graph:null};let A=f=>(x=M.addNode("",{name:f.title.replaceAll(/ /g,` `),title:f.title,site:k,links:Object.keys(f.links||{}).filter(h=>e(h))}),x),W=(f,h)=>M.addRel("",f,h),R=f=>M.nodes[f].props.links.filter(h=>!E.has(h)),j=c(b);E.add(j.slug),A(j);for(let f=5;f>0;f--)try{let h=R(x),O=c(h);E.add(O);let I=e(O);W(x,A(I))}catch{}return{name:L,graph:M}})}function T(g,k,L=12){let E=k*24*60*60*1e3,x=[...Array(Number(L)).keys()].map(A=>Date.now()-A*E),b=[];for(let A of x){let W=A-E,R=`${g.replace(/s$/,"")} ${new Date(W).toLocaleDateString()}`,j=i.filter(f=>f.date<A&&f.date>=W).filter(f=>!(f.links&&Object.keys(f.links).length>5));if(j.length){let f=j.reduce((h,O)=>(h.add(O.domain),h),new Set);for(let h of f){let O=new G,I=N=>O.addUniqNode("",{name:N.title.replaceAll(/ /g,` `),title:N.title,site:N.domain,date:N.date}),C=h.split(/\.|\:/)[0];for(let N of j.filter(K=>K.domain==h)){let K=I(N);for(let q in N.links||{}){let _=e(q);_&&O.addRel("",K,I(_))}}b.push({name:`${R} ${C}`,graph:O})}}}return b}function H(g=12){let k=[],L=new Set,E={};for(let x of i)if(x.links)if(Object.keys(x.links).length<=15)for(let b in x.links)e(b)&&(E[b]=(E[b]||0)+1);else L.add(x.slug);L.size>0&&console.log("hub links ignored for large pages:",[...L]);let M=Object.entries(E).sort((x,b)=>b[1]-x[1]).slice(0,g);console.log({hits:E,hubs:M});for(let x of M){let b=`hub ${x[1]} ${x[0]}`,A=w(e(x[0]));k.push({name:b,graph:A})}return k}function F(){let g=[],k=n.lineup();console.log({lineup:k});for(let L of k){let E=wiki.lineup.atKey(L.dataset.key),M=E.getSlug(),x=E.getRemoteSite(location.host),b=e(M,x);console.log({div:L,pageObject:E,site:x,slug:M,info:b}),g.push({name:E.getTitle(),graph:w(b)})}return g}function V(){let g=[],k=n.references();console.log({items:k});for(let L of k){let{title:E,site:M,slug:x}=L,b=e(x,M);console.log({site:M,slug:x,info:b}),g.push({name:E,graph:w(b)})}return console.log({aspects:g}),g}function Z(g=10){let k=[],M=R=>Date.now()-R*6048e5,x=0;for(;k.length<g&&x<g;){let R=M(x++),j=M(x),f=i.filter(h=>h.date>j&&h.date<=R).filter(h=>!!h.links).filter(h=>!h.title.endsWith(" Survey"));if(f.length){let h=b(f),O=new Date(R).toLocaleDateString();k.push(...W({name:O,graph:h},j,R))}}return k;function b(R){let j=new G,f=h=>{let O="",I=i.find(v=>v.slug==h),C=i.filter(v=>v.slug==h).length,N=I.title,K=I.domain,q=I.date,_=N.replaceAll(" ",` `),J=j.nodes.findIndex(v=>v.type==O&&v.props.name==_),S=J>=0?J:j.addNode(O,{name:_,site:K,date:q});return C>1&&(j.nodes[S].props.twins=C),S};for(let h of R){let O=f(h.slug);for(let I of A(Object.keys(h.links)))j.addRel("",O,f(I))}return j}function A(R){let j=f=>i.filter(h=>h.slug==f);return R.map(f=>[f,j(f)]).filter(f=>f[1].length).map(f=>[f[0],f[1].sort((h,O)=>O.date-h.date)[0]]).sort((f,h)=>h[1].date-f[1].date).map(f=>f[0]).slice(0,3)}function W(R,j,f){let h=R.graph,O=[],I={},C=h.nodes,N=h.rels,K=[...Array(C.length).keys()].map(S=>[S,Math.random()]).sort((S,v)=>S[1]-v[1]).map(S=>S[0]),q=S=>{if(S in I)return;K.splice(K.indexOf(S),1);let v=C[S];I[S]=O[0].addNode(v.type,v.props);for(let U of v.out)q(N[U].to);for(let U of v.in)q(N[U].from);for(let U of v.out)O[0].addRel("",I[S],I[N[U].to],{})};for(;K.length;){let S=K.shift();if(S in I)continue;let v=C[S],U=v.props.name.replaceAll(` `," ");v.in.length+v.out.length&&(O.unshift(new G),I={},q(S))}let _=S=>S.props.date||0,J=S=>{let v=S.nodes.slice(0).sort((z,ut)=>_(ut)-_(z)).filter(z=>_(z)>=j&&_(z)<=f)[0];return console.log({node:v,nodes:S.nodes,name:R.name}),v?v.props.name.split(/\s+/).slice(0,3).join(" "):R.name};return O.reverse().map((S,v)=>({name:J(S),graph:S}))}}}function ot(t,o,i){let n=o.filter(c=>c.match(/\t/)).map(r).flat().sort((c,l)=>c.word<l.word?-1:1),e="zzz".slice(0,t),s=[];for(let c of n){let l=c.word.toLowerCase().slice(0,t);l!=e&&(s.push({group:l,quotes:[]}),e=l),s[s.length-1].quotes.push(c)}return s;function r(c){let[l,u]=c.split(/\t/);return u.replaceAll(/'t\b/g,"t").replaceAll(/'s\b/g,"s").split(/[^a-zA-Z]+/).filter(p=>p.length>3&&!i.has(p.toLowerCase())).map(p=>({word:p,line:c,key:l}))}}var G=class{constructor(o=[],i=[]){this.nodes=o,this.rels=i}addNode(o,i={}){let n={type:o,in:[],out:[],props:i};return this.nodes.push(n),this.nodes.length-1}addUniqNode(o,i={}){let n=this.nodes.findIndex(e=>e.type==o&&e.props?.name==i?.name);return n>=0?n:this.addNode(o,i)}addRel(o,i,n,e={}){let s={type:o,from:i,to:n,props:e};this.rels.push(s);let r=this.rels.length-1;return this.nodes[i].out.push(r),this.nodes[n].in.push(r),r}stringify(...o){let i={nodes:this.nodes,rels:this.rels};return JSON.stringify(i,...o)}};function it(t,o){let i=()=>(t.story||[]).map(s=>s?.id),n=(s,r)=>{let c=i().indexOf(s)+1;t.story.splice(c,0,r)},e=()=>{let s=i().indexOf(o.id);s!==-1&&t.story.splice(s,1)};switch(t.story=t.story||[],o.type){case"create":o.item&&(o.item.title!=null&&(t.title=o.item.title),o.item.story!=null&&(t.story=o.item.story.slice()));break;case"add":n(o.after,o.item);break;case"edit":let s=i().indexOf(o.id);s!==-1?t.story.splice(s,1,o.item):t.story.push(o.item);break;case"move":let r=o.order.indexOf(o.id),c=o.order[r-1],l=t.story[i().indexOf(o.id)];e(),n(c,l);break;case"remove":e();break}t.journal=t.journal||[],o.fork&&t.journal.push({type:"fork",site:o.fork,date:o.date-1}),t.journal.push(o)}function X(t){if(!t.data)return;let{data:o}=t;if(o?.action=="publishSourceData"&&o?.name=="aspect"){wiki.debug&&console.log("soloListener - source update",{event:t,data:o});return}if(!t.source.opener||t.source.location.pathname!=="/plugins/solo/dialog/"){wiki.debug&&console.log("soloListener - not for us",{event:t});return}wiki.debug&&console.log("soloListener - ours",{event:t});let{action:i,keepLineup:n=!1,pageKey:e=null,title:s=null,context:r=null,page:c=null}=o,l=null;switch(e!=null&&(l=n?null:$(".page").filter((u,a)=>$(a).data("key")==e)),i){case"doInternalLink":wiki.pageHandler.context=r,wiki.doInternalLink(s,l);break;case"showResult":let u=n?{}:{$page:l};wiki.showResult(wiki.newPage(c),u);break;default:console.error({where:"soloListener",message:"unknown action",data:o})}}var dt=Number.MAX_SAFE_INTEGER;function Q(t,o=1e3,i=dt){let n=!1,e=Date.now(),s={stop:c,remainingTicks:i,minMS:o,ticksSoFar:0,timeSinceLastTick:0},r=l();return r.api=s,r;function c(){n=!0}async function l(){if(n||s.remainingTicks<1)return;s.remainingTicks-=1,s.ticksSoFar+=1,s.timeSinceLastTick=Date.now()-e,e=Date.now();let u=new Promise(a=>setTimeout(a,s.minMS));return await t(s),await u,l()}}var rt={trouble:y,inspect:P,response:ct,button:ft,element:gt,jfetch:ht,status:mt,sourceData:kt,showResult:wt,neighborhood:yt,publishSourceData:bt,newSVG:xt,SVGline:$t,ticker:Q};function y(t,o){t.innerText.match(/✖︎/)||(t.innerHTML+='<button style="border-width:0;color:red;">\u2716\uFE0E</button>',t.querySelector("button").addEventListener("click",i=>{t.outerHTML+=`<span style="width:80%;color:gray;">${o}</span>`}))}function P(t,o,i){let n=t.previousElementSibling;if(i.debug){let e=i[o];n.innerHTML=`${o} \u21D2 `,n.addEventListener("click",s=>{console.log({key:o,value:e});let r=n.previousElementSibling;if(!r?.classList.contains("look")){let u=document.createElement("div");u.classList.add("look"),n.insertAdjacentElement("beforebegin",u),r=n.previousElementSibling}let c=JSON.stringify(e,null,1);c.length>300&&(c=c.substring(0,400)+"...");let l="border:1px solid black; background-color:#f8f8f8; padding:8px; color:gray; word-break: break-all;";r.innerHTML=`<div style="${l}">${c}</div>`})}else n.innerHTML=""}function ct(t,o){t.innerHTML+=o}function ft(t,o,i){t.innerHTML.match(/button/)||(ct(t,`<button style="border-width:0;">${o}</button>`),t.querySelector("button").addEventListener("click",i))}function gt(t){return document.getElementById(t)}async function ht(t){return fetch(t).then(o=>o.ok?o.json():null)}function mt(t,o,i){t.innerHTML=o+i}function kt(t,o){let i=t.closest(".item"),n=tt(i,o).map(({div:e,result:s})=>({classList:[...e.classList],id:e.dataset.id,result:s}));return n.length?n:(y(t,`Expected source for "${o}" in the lineup.`),null)}function bt(t,o,i){let n=t.closest(".item");n.classList.add(`${o}-source`),n[`${o}Data`]=()=>i}function wt(t,o){let i={$page:$(t.closest(".page"))};wiki.showResult(wiki.newPage(o),i)}function yt(t){return Object.entries(wiki.neighborhoodObject.sites).filter(([o,i])=>!i.sitemapRequestInflight&&(!t||o.includes(t))).map(([o,i])=>(i.sitemap||[]).map(n=>Object.assign({domain:o},n)))}function xt(t){let o=document.createElement("div");return t.closest(".item").firstElementChild.prepend(o),o.outerHTML=` <div style="border:1px solid black; background-color:#f8f8f8; margin-bottom:16px;"> <svg viewBox="0 0 400 400" width=100% height=400> <circle id=dot r=5 cx=200 cy=200 stroke="#ccc"></circle> </svg> </div>`,t.closest(".item").getElementsByTagName("svg")[0]}function $t(t,[o,i],[n,e]){let s=document.createElementNS("http://www.w3.org/2000/svg","line"),r=(l,u)=>s.setAttribute(l,Math.round(u));r("x1",o),r("y1",400-i),r("x2",n),r("y2",400-e),s.style.stroke="black",s.style.strokeWidth="2px",t.appendChild(s);let c=t.getElementById("dot");c.setAttribute("cx",Math.round(n)),c.setAttribute("cy",Math.round(400-e))}async function D(t,o){let i=t.slice();for(;i.length;){let n=i.shift();if("command"in n){let e=n.command,s=o.api?o.api.element(n.key):document.getElementById(n.key),[r,...c]=n.command.split(/ +/),l=i[0],u=l&&"command"in l?null:i.shift(),a={command:e,op:r,args:c,body:u,elem:s,state:o};o.debug&&console.log(a),st[r]?await st[r].emit.apply(null,[a]):r.match(/^[A-Z]+$/)?o.api.trouble(s,`${r} doesn't name a block we know.`):n.command.match(/\S/)&&o.api.trouble(s,"Expected line to begin with all-caps keyword.")}}}function Lt({elem:t,body:o,state:i}){if(!o?.length)return i.api.trouble(t,"CLICK expects indented blocks to follow.");i.api.button(t,"\u25B6",n=>{i.debug=n.shiftKey,D(o,i)})}function St({elem:t,args:o,state:i}){let n=o[0]=="world"?" \u{1F30E}":" \u{1F600}";for(let e of Object.keys(i))i.api.inspect(t,e,i);i.api.response(t,n)}async function Et({elem:t,args:o,body:i,state:n}){if(!i?.length)return n.api.trouble(t,"FROM expects indented blocks to follow.");let e=o[0];n.api.response(t," \u23F3"),n.page=await n.api.jfetch(`//${e}.json`),n.api.response(t," \u231B"),D(i,n)}function vt({elem:t,command:o,args:i,body:n,state:e}){if(e.api.status(t,o,""),!("page"in e))return e.api.trouble(t,'Expect "page" as with FROM.');e.api.inspect(t,"page",e);let s=e.page.story.find(p=>p.type=="datalog");if(!s)return e.api.trouble(t,"Expect Datalog plugin in the page.");let r=i[0];if(!r)return e.api.trouble(t,"SENSOR needs a sensor name.");let c=s.text.split(/\n/).map(p=>p.split(/ +/)).filter(p=>p[0]=="SENSOR").find(p=>p[1]==r);if(!c)return e.api.trouble(t,`Expect to find "${r}" in Datalog.`);let l=c[2],u=p=>9/5*(p/16)+32,a=p=>p.reduce((m,w)=>m+w,0)/p.length;e.api.status(t,o," \u23F3"),e.api.jfetch(l).then(p=>{e.debug&&console.log({sensor:c,data:p}),e.api.status(t,o," \u231B");let m=u(a(Object.values(p)));e.temperature=`${m.toFixed(2)}\xB0F`,D(n,e)})}function Ot({elem:t,command:o,state:i}){let n=i?.temperature;if(!n)return i.api.trouble(t,"Expect data, as from SENSOR.");i.api.inspect(t,"temperature",i),i.api.response(t,`<br><font face=Arial size=32>${n}</font>`)}function Tt({elem:t,command:o,args:i,body:n,state:e}){if(!(i&&i.length))return e.api.trouble(t,'Expected Source topic, like "markers" for Map markers.');let s=i[0],r=e.api.sourceData(t,s);if(!r)return;e.debug&&console.log({topic:s,sources:r});let c=u=>{let a=r.filter(p=>p.classList.includes(u)).length;return a?`${a} ${u}`:null},l=[c("map"),c("image"),c("frame"),c("assets")].filter(u=>u).join(", ");e.api.status(t,o," \u21D2 "+l),e[s]=r.map(({id:u,result:a})=>({id:u,result:a})),n&&D(n,e)}function Mt({elem:t,command:o,args:i,state:n}){let e=p=>(+p).toFixed(7),s=[],r=i;for(let p of r)switch(p){case"map":if(!("marker"in n))return n.api.trouble(t,'"map" preview expects "marker" state, like from "SOURCE marker".');n.api.inspect(t,"marker",n);let m=n.marker.map(d=>[d.result]).flat(2).map(d=>`${e(d.lat)}, ${e(d.lon)} ${d.label||""}`).filter(B).join(` `);s.push({type:"map",text:m});break;case"graph":if(!("aspect"in n))return n.api.trouble(t,'"graph" preview expects "aspect" state, like from "SOURCE aspect".');n.api.inspect(t,"aspect",n);for(let{div:d,result:T}of n.aspect){for(let{name:H,graph:F}of T)n.debug&&console.log({div:d,result:T,name:H,graph:F}),s.push({type:"paragraph",text:H}),s.push({type:"graphviz",text:et(F)});s.push({type:"pagefold",text:"."})}break;case"items":if(!("items"in n))return n.api.trouble(t,'"graph" preview expects "items" state, like from "KWIC".');n.api.inspect(t,"items",n),s.push(...n.items);break;case"page":if(!("page"in n))return n.api.trouble(t,'"page" preview expects "page" state, like from "FROM".');n.api.inspect(t,"page",n),s.push(...n.page.story);break;case"synopsis":let w=`This page created with Mech command: "${o}". See [[${n.context.title}]].`;s.push({type:"paragraph",text:w,id:n.context.itemId});break;default:return n.api.trouble(t,`"${p}" doesn't name an item we can preview`)}let l={title:"Mech Preview"+(n.tick?` ${n.tick}`:""),story:s};for(let p of l.story)p.id||=(Math.random()*10**20).toFixed(0);let u=JSON.parse(JSON.stringify(l)),a=Date.now();l.journal=[{type:"create",date:a,item:u}],n.api.showResult(t,l)}async function Rt({elem:t,command:o,args:i,body:n,state:e}){let s=l=>e.api.element(l.key),r=i[0],c=e.api.neighborhood(r);for(let l of n||[]){if(!l.command.endsWith(" Survey")){e.api.trouble(s(l),"NEIGHBORS expects a Site Survey title, like Pattern Link Survey");continue}let u=c.filter(a=>a.find(p=>p.title==l.command));e.api.status(s(l),l.command,`\u21D2 ${u.length} sites`);for(let a of u){let p=`//${a[0].domain}/${at(l.command)}.json`,m=await e.api.jfetch(p);if(!m)continue;let w=m.story.find(d=>d.type=="frame")?.survey;if(w){for(let d of a){let T=Object.assign({},w.find(H=>H.slug==d.slug),d);Object.assign(d,T)}console.log({url:p,page:m,survey:w,todo:a})}}}e.neighborhood=c.flat().sort((l,u)=>u.date-l.date),e.api.status(t,o,`\u21D2 ${e.neighborhood.length} pages, ${c.length} sites`)}function jt({elem:t,command:o,args:i,state:n}){if(!("neighborhood"in n))return n.api.trouble(t,"WALK expects state.neighborhood, like from NEIGHBORS.");n.api.inspect(t,"neighborhood",n);let[,e,s]=o.match(/\b(\d+)? *(steps|days|weeks|months|hubs|lineup|references|topics)\b/)||[];if(!s&&o!="WALK")return n.api.trouble(t,"WALK can't understand rest of this block.");let r={lineup(){let a=[...document.querySelectorAll(".page")],p=a.indexOf(t.closest(".page"));return a.slice(0,p)},references(){let a=t.closest(".page"),p=wiki.lineup.atKey(a.dataset.key),m=p.getRawPage().story;return console.log({div:a,pageObject:p,story:m}),m.filter(w=>w.type=="reference")}},c=nt(e,s,n.neighborhood,r),l=c.filter(({graph:a})=>a);n.debug&&console.log({steps:c});let u=l.map(({graph:a})=>a.nodes).flat();if(n.api.status(t,o,` \u21D2 ${l.length} aspects, ${u.length} nodes`),c.find(({graph:a})=>!a)&&n.api.trouble(t,"WALK skipped sites with no links in sitemaps"),l.length){n.aspect=n.aspect||[];let a=n.aspect.find(p=>p.id==t.id);a?a.result=l:n.aspect.push({id:t.id,result:l,source:o}),n.api.publishSourceData(t,"aspect",n.aspect.map(p=>p.result).flat()),n.debug&&console.log({command:o,state:n.aspect,item:item.aspectData()})}}function It({elem:t,command:o,args:i,body:n,state:e}){if(console.log({command:o,args:i,body:n,state:e}),!n?.length)return e.api.trouble(t,"TICK expects indented blocks to follow.");let s=i[0]||"1";if(!s.match(/^[1-9][0-9]?$/))return e.api.trouble(t,"TICK expects a count from 1 to 99");let r,c;if(e.tick!=null)return c=e.tick,a({shiftKey:e.debug}),r;l();function l(){e.api.button(t,"\u25B6",a)}function u(p){e.api.status(t,o,` \u21D2 ${p} remaining`)}function a(p){e.debug=p.shiftKey,e.tick=+s,u(e.tick),r=e.api.ticker(async()=>{e.debug&&console.log({tick:e.tick,count:s}),"tick"in e&&--e.tick>=0?(u(e.tick),await D(n,e)):(r=r.api.stop(),e.tick=c,e.api.status(t,o,""),l())})}}function At({elem:t,command:o,args:i,body:n,state:e}){if(!i.length)return y(t,"UNTIL expects an argument, a word to stop running.");if(!e.tick)return y(t,"UNTIL expects to indented below an iterator, like TICKS.");if(!e.aspect)return y(t,'UNTIL expects "aspect", like from WALK.');P(t,"aspect",e),t.innerHTML=o+` \u21D2 ${e.tick}`;let s=i[0];for(let{div:r,result:c}of e.aspect)for(let{name:l,graph:u}of c)for(let a of u.nodes)if(a.type.includes(s)||a.props.name.includes(s)){e.debug&&console.log({div:r,result:c,name:l,graph:u,node:a}),delete e.tick,t.innerHTML+=" done",n&&D(n,e);return}}function Nt({elem:t,command:o,args:i,state:n}){if(i.length<1)return n.api.trouble(t,'FORWARD expects an argument, the number of steps to move a "turtle".');n.turtle??={svg:n.api.newSVG(t),position:[200,200],direction:0};let e=i[0],s=n.turtle.direction*2*Math.PI/360,[r,c]=n.turtle.position;n.turtle.position=[r+e*Math.sin(s),c+e*Math.cos(s)],n.api.SVGline(n.turtle.svg,[r,c],n.turtle.position),n.api.status(t,o,` \u21D2 ${n.turtle.position.map(l=>(l-200).toFixed(1)).join(", ")}`)}function Ht({elem:t,command:o,args:i,state:n}){if(i.length<1)return n.api.trouble(t,'TURN expects an argument, the number of degrees to turn a "turtle".');n.turtle??={svg:n.api.newSVG(t),position:[200,200],direction:0};let e=+i[0];n.turtle.direction+=e,n.api.status(t,o,` \u21D2 ${n.turtle.direction}\xB0`)}function Dt({elem:t,command:o,args:i,body:n,state:e}){if(!("assets"in e))return y(t,"FILE expects state.assets, like from SOURCE assets.");P(t,"assets",e);let s="//"+window.location.host,r=e.assets.map(({id:a,result:p})=>Object.entries(p).map(([m,w])=>Object.entries(w).map(([d,T])=>T.map(H=>{let F=d.startsWith("//")?d:`${s}${d}`,V=F.replace(/\/assets$/,""),Z=`${F}/${m}/${H}`;return{id:a,dir:m,path:d,host:V,file:H,url:Z}})))).flat(3);if(e.debug&&console.log({assets:r}),i.length<1)return y(t,"FILE expects an argument, the dot suffix for desired files.");if(!n?.length)return y(t,"FILE expects indented blocks to follow.");let c=i[0],l=r.filter(a=>a.file.endsWith(c)),u=a=>`<img width=12 src=${l[a].host+"/favicon.png"}>`;if(!l)return y(t,`FILE expects to find an asset with "${c}" suffix.`);t.innerHTML=o+`<br><div class=choices style="border:1px solid black; background-color:#f8f8f8; padding:8px;" >${l.map((a,p)=>`<span data-choice=${p} style="cursor:pointer;"> ${u(p)} ${a.file} \u25B6 </span>`).join(`<br> `)}</div>`,t.querySelector(".choices").addEventListener("click",a=>{if(!("choice"in a.target.dataset))return;let p=l[a.target.dataset.choice].url;fetch(p).then(m=>m.text()).then(m=>{t.innerHTML=o+` \u21D2 ${m.length} bytes`,e.tsv=m,console.log({text:m}),D(n,e)})})}function Kt({elem:t,command:o,args:i,body:n,state:e}){let s=n&&n[0]?.command;if(s&&!s.match(/\$[KW]/))return y(t,"KWIK expects $K or $W in link prototype.");if(!("tsv"in e))return y(t,"KWIC expects a .tsv file, like from ASSETS .tsv.");P(t,"tsv",e);let r=i[0]||1,c=e.tsv.trim().split(/\n/),l=new Set(["of","and","in","at"]),u=$(t.closest(".page")).data("data"),a=u.story.findIndex(w=>w.type=="pagefold"&&w.text=="stop");if(a>=0){let w=u.story.findIndex((d,T)=>T>a&&d.type=="pagefold");u.story.slice(a+1,w).map(d=>d.text.trim().split(/\s+/)).flat().forEach(d=>l.add(d))}let p=ot(r,c,l);t.innerHTML=o+` \u21D2 ${c.length} lines, ${p.length} groups`;let m=w=>{let d=w.line;if(s){let T=s.replaceAll(/\$K\+/g,w.key.replaceAll(/ /g,"+")).replaceAll(/\$K/g,w.key).replaceAll(/\$W/g,w.word),H=s.match(/\$W/)?w.word:w.key;d=d.replace(H,T)}return d};e.items=p.map(w=>({type:"markdown",text:`# ${w.group} ${w.quotes.map(T=>m(T)).join(` `)}`}))}function _t({elem:t,command:o,args:i,state:n}){t.innerHTML=o;let e,s;if(i.length<1)if(n.info)P(t,"info",n),e=n.info.domain,s=n.info.slug,t.innerHTML=o+` \u21D2 ${n.info.title}`;else return y(t,"SHOW expects a slug or site/slug to open in the lineup.");else{let l=i[0];[e,s]=l.includes("/")?l.split(/\//):[null,l]}if([...document.querySelectorAll(".page")].map(l=>l.id).includes(s))return y(t,"SHOW expects a page not already in the lineup.");let c=t.closest(".page");wiki.doInternalLink(s,c,e)}function Pt({elem:t,command:o,state:i}){if(!i.neighborhood)return y(t,"RANDOM expected a neighborhood, like from NEIGHBORS.");P(t,"neighborhood",i);let n=i.neighborhood,e=n.length,s=Math.floor(Math.random()*e);t.innerHTML=o+` \u21D2 ${s} of ${e}`,i.info=n[s]}function Wt({elem:t,command:o,args:i,body:n,state:e}){let s=i[0]||"1";return s.match(/^[1-9][0-9]?$/)?new Promise(r=>{n&&D(n,e).then(l=>{e.debug&&console.log(o,"children",l)}),t.innerHTML=o+` \u21D2 ${s} remain`;let c=setInterval(()=>{--s>0?t.innerHTML=o+` \u21D2 ${s} remain`:(clearInterval(c),t.innerHTML=o+" \u21D2 done",e.debug&&console.log(o,"done"),r())},1e3)}):y(t,"SLEEP expects seconds from 1 to 99")}function Ct({elem:t,command:o,args:i,body:n,state:e}){if(!n)return y(t,"TOGETHER expects indented commands to run together.");let s=n.map(r=>D([r],e));return Promise.all(s)}async function Ft({elem:t,command:o,args:i,body:n,state:e}){if(!n)return y(t,"GET expects indented commands to run on the server.");let s={},r=e.context.site;if(i.length)for(let d of i)if(d in e)P(t,d,e),s[d]=e[d];else if(d.match(/\./))r=d;else return y(t,`GET expected "${d}" to name state or site.`);let c=e.context.slug,l=e.context.itemId,u=`mech=${btoa(JSON.stringify(n))}&state=${btoa(JSON.stringify(s))}`,a=`//${r}/plugin/mech/run/${c}/${l}?${u}`;t.innerHTML=o+" \u21D2 in progress";let p=Date.now(),m;try{if(m=await fetch(a).then(d=>d.ok?d.json():d.status),"err"in m)return y(t,`RUN received error "${m.err}"`)}catch(d){return y(t,`RUN failed with "${d.message}"`)}e.result=m;for(let d of m.mech.flat(9)){let T=document.getElementById(d.key);"status"in d&&(T.innerHTML=d.command+` \u21D2 ${d.status}`),"trouble"in d&&y(T,d.trouble)}"debug"in m.state&&delete m.state.debug,Object.assign(e,m.state);let w=((Date.now()-p)/1e3).toFixed(3);t.innerHTML=o+` \u21D2 ${w} seconds`}function qt({elem:t,command:o,args:i,body:n,state:e}){let s=c=>JSON.parse(JSON.stringify(c)),r=c=>JSON.stringify(c).length;if(i.length<1)return y(t,'DELTA expects argument, "have" or "apply" on client.');if(n)return y(t,"DELTA doesn't expect indented input.");switch(i[0]){case"have":let c=e.context.page.journal.filter(p=>p.type!="fork");e.recent=c[c.length-1].date,t.innerHTML=o+` \u21D2 ${new Date(e.recent).toLocaleString()}`;break;case"apply":if(!("actions"in e))return y(t,'DELTA apply expect "actions" as input.');P(t,"actions",e);let l=s(e.context.page),u=r(l);for(let p of e.actions)it(l,p);e.page=l;let a=r(l);t.innerHTML=o+` \u21D2 \u2206 ${((a-u)/u*100).toFixed(1)}%`;break;default:y(t,`DELTA doesn't know "${i[0]}".`)}}function Ut({elem:t,command:o,state:i}){if(!i.neighborhood)return y(t,"ROSTER expected a neighborhood, like from NEIGHBORS.");P(t,"neighborhood",i);let n=i.neighborhood,e=n.map(c=>c.domain).filter(B),s=c=>c[Math.floor(Math.random()*c.length)];i.debug&&console.log(n);let r=[{type:"roster",text:`Mech `+e.join(` `)},{type:"activity",text:`ROSTER Mech SINCE 30 days`}];t.innerHTML=o+` \u21D2 ${e.length} sites`,i.items=r}function Gt({elem:t,command:o,state:i}){let n=[...document.querySelectorAll(".page")].map(e=>{let s=$(e),r=s.data("data"),c=s.data("site")||location.host,l=s.attr("id").split("_")[0],u=r.title||"Empty",a=r.story[0]?.text||"empty";return{type:"reference",site:c,slug:l,title:u,text:a}});t.innerHTML=o+` \u21D2 ${n.length} pages`,i.items=n}function Bt({elem:t,command:o,args:i,state:n}){if(i.length<1)return y(t,"LISTEN expects argument, an action.");let e=i[0],s=Date.now(),r=0,c=l;c.action="publishSourceData",c.id=t.id,window.addEventListener("message",l),$(".main").on("thumb",(u,a)=>console.log("jquery",{evt:u,thumb:a})),t.innerHTML=o+" \u21D2 ready";function l(u){console.log({event:u});let{data:a}=u;if(a.action=="publishSourceData"&&(a.name==e||a.topic==e))if(r++,c.count=r,n.debug&&console.log({count:r,data:a}),r<=100){let p=Date.now(),m=p-s;s=p,t.innerHTML=o+` \u21D2 ${r} events, ${m} ms`}else window.removeEventListener("message",l)}}function Jt({elem:t,command:o,args:i,state:n}){if(i.length<1)return y(t,"MESSAGE expects argument, an action.");let e=i[0],s={action:"publishSourceData",topic:e,name:e};window.postMessage(s,"*"),t.innerHTML=o+" \u21D2 sent"}async function zt({elem:t,command:o,state:i}){if(!("aspect"in i))return y(t,'"SOLO" expects "aspect" state, like from "WALK".');P(t,"aspect",i),t.innerHTML=o;let n=i.aspect.map(l=>({source:l.source||l.id,aspects:l.result})),e=n.reduce((l,u)=>l+u.aspects.length,0);t.innerHTML+=` \u21D2 ${n.length} sources, ${e} aspects`;let s=t.closest(".page").dataset.key,r={type:"batch",sources:n,pageKey:s};console.log({pageKey:s,doing:r}),(typeof window.soloListener>"u"||window.soloListener==null)&&(console.log("**** Adding solo listener"),window.soloListener=X,window.addEventListener("message",X)),await lt(750);let c=window.open("/plugins/solo/dialog/#","solo","popup,height=720,width=1280");c.location.pathname!="/plugins/solo/dialog/"?(console.log("launching new dialog"),c.addEventListener("load",l=>{console.log("launched and loaded"),c.postMessage(r,window.origin)})):(console.log("reusing existing dialog"),c.postMessage(r,window.origin))}function Vt({elem:t,args:o,state:i}){let n=[];switch(o[0]){case"state":for(let s in i)n.push(`<details> <summary>${s}</summary> <pre>${JSON.stringify(i[s],null,2)}</pre> </details>`);break;case"images":if(!i.commons)return y(t,'POPUP images expects "commons" state, like from "GET" "COMMONS"');let e=o[1]=="all"?i.commons.all:i.commons.here;for(let s of e.items)n.push(`<span><img height=200 src=/assets/plugins/image/${s}></span>`);break;default:return y(t,`POPUP doesn't know "${o[0]}".`)}wiki.dialog(t.innerText,n.join(` `))}var st={CLICK:{emit:Lt},HELLO:{emit:St},FROM:{emit:Et},SENSOR:{emit:vt},REPORT:{emit:Ot},SOURCE:{emit:Tt},PREVIEW:{emit:Mt},NEIGHBORS:{emit:Rt},WALK:{emit:jt},TICK:{emit:It},UNTIL:{emit:At},FORWARD:{emit:Nt},TURN:{emit:Ht},FILE:{emit:Dt},KWIC:{emit:Kt},SHOW:{emit:_t},RANDOM:{emit:Pt},SLEEP:{emit:Wt},TOGETHER:{emit:Ct},GET:{emit:Ft},DELTA:{emit:qt},ROSTER:{emit:Ut},LINEUP:{emit:Gt},LISTEN:{emit:Bt},MESSAGE:{emit:Jt},SOLO:{emit:zt},POPUP:{emit:Vt}};function Zt(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function Y(t,o,i){for(;t.length;){let e=t[0].match(/( *)(.*)/),s=e[1].length,r=e[2];if(s==i)o.push({command:r}),t.shift();else if(s>i){var n=[];o.push(n),Y(t,n,s)}else return o}return o}function pt(t){let o=Math.floor(Math.random()*1e6),i=(n,e)=>{let s=[];for(let r of n){let c=`${o}.${e.join(".")}`;r.key=c,"command"in r?s.push(`<font color=gray size=small></font><span style="display: block;" id=${c}>${Zt(r.command)}</span>`):s.push(`<div id=${c} style="padding-left:15px">${i(r,[...e,0])}</div>`),e[e.length-1]++}return s.join(` `)};return i(t,[0])}var B=(t,o,i)=>i.indexOf(t)===o,lt=t=>new Promise(o=>setTimeout(o,t)),at=t=>t.replace(/\s/g,"-").replace(/[^A-Za-z0-9-]/g,"").toLowerCase();function me(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function Xt(t,o){let i=o.text.split(/\n/),n=Y(i,[],0),e=pt(n),s=t.parents(".page"),r=s.data("key"),l={context:{item:o,itemId:o.id,pageKey:r,page:wiki.lineup.atKey(r).getRawPage(),origin:window.origin,site:s.data("site")||window.location.host,slug:s.attr("id"),title:s.data("data").title},api:rt};t.append(`<div style="background-color:#eee;padding:15px;border-top:8px;">${e}</div>`),D(n,l)}function Qt(t,o){return t.dblclick(()=>wiki.textEditor(t,o))}typeof window<"u"&&window!==null&&(window.plugins.mech={emit:Xt,bind:Qt});})(); //# sourceMappingURL=mech.js.map