UNPKG

wiki-plugin-mech

Version:
29 lines (27 loc) 27.8 kB
/* wiki-plugin-mech - 0.1.31 - Mon, 18 Aug 2025 21:43:51 GMT */ (()=>{function B(e,o){let i=[];for(let n of document.querySelectorAll(".item"))if(n.classList.contains(`${o}-source`)&&i.unshift(n),n===e)break;return i.map(n=>{let t=n[`${o}Data`],s=t?t():null;return{div:n,result:s}})}function J(e){let o=t=>Object.entries(t).filter(s=>s[1]).map(s=>`${s[0]}: ${s[1]}`).join("\\n"),i=e.nodes.map((t,s)=>{let r=t.type?`${t.type}\\n${t.props.name}`:t.props.name;return`${s} [label="${r}" ${t.props.url||t.props.tick?`URL="${t.props.url||"#"}" target="_blank"`:""} tooltip="${o(t.props)}"]`}),n=e.rels.map(t=>`${t.from}->${t.to} [label="${t.type}" labeltooltip="${o(t.props)}"]`);return["digraph {","rankdir=LR","node [shape=box style=filled fillcolor=palegreen]",...i,...n,"}"].join(` `)}function z(e,o="steps",i,n={}){let t=(f,k)=>i.find(y=>y.slug==f&&(!k||y.domain==k)),s=f=>f?f.map(k=>t(k)):null,r=f=>Math.floor(f*Math.abs(Math.random()-Math.random())),c=f=>f[r(f.length)],l=f=>f.links&&Object.keys(f.links).length<10,p=f=>i.filter(k=>l(k)&&f in k.links),a=(f,k,y)=>y.findIndex(x=>x.slug==f.slug)===k,u=f=>f.toSorted((k,y)=>y.date-k.date).filter(a).slice(0,3),g=i.map(f=>f.domain).filter(_);function m(f){let k=new K,y=h=>k.addUniqNode("",{name:h.title.replaceAll(/ /g,` `),title:h.title,site:h.domain}),x=h=>s(h?.patterns?.up)??u(p(h.slug)),E=h=>h?.patterns?.down??Object.keys(h.links||{}),w=y(f);for(let h of x(f))k.addRel("",y(h),w);for(let h of E(f)){let O=t(h);if(O){let N=y(O);k.addRel("",w,N);for(let D of x(O))k.addRel("",y(D),N)}}return k}switch(o){case"steps":return d(e);case"days":return S(o,1,e);case"weeks":return S(o,7,e);case"months":return S(o,30,e);case"hubs":return v(e);case"references":return W();case"lineup":return I()}function d(f=5){return g.map(k=>{let y=k.split(".").slice(0,3).join("."),x=new Set,E=new K,w=0,h=i.filter(L=>L.domain==k&&"links"in L);if(!h.length)return{name:y,graph:null};let O=L=>(w=E.addNode("",{name:L.title.replaceAll(/ /g,` `),title:L.title,site:k,links:Object.keys(L.links||{}).filter(T=>t(T))}),w),N=(L,T)=>E.addRel("",L,T),D=L=>E.nodes[L].props.links.filter(T=>!x.has(T)),H=c(h);x.add(H.slug),O(H);for(let L=5;L>0;L--)try{let T=D(w),j=c(T);x.add(j);let P=t(j);N(w,O(P))}catch{}return{name:y,graph:E}})}function S(f,k,y=12){let x=k*24*60*60*1e3,w=[...Array(Number(y)).keys()].map(O=>Date.now()-O*x),h=[];for(let O of w){let N=O-x,D=`${f.replace(/s$/,"")} ${new Date(N).toLocaleDateString()}`,H=i.filter(L=>L.date<O&&L.date>=N).filter(L=>!(L.links&&Object.keys(L.links).length>5));if(H.length){let L=H.reduce((T,j)=>(T.add(j.domain),T),new Set);for(let T of L){let j=new K,P=A=>j.addUniqNode("",{name:A.title.replaceAll(/ /g,` `),title:A.title,site:A.domain,date:A.date}),oe=T.split(/\.|\:/)[0];for(let A of H.filter(C=>C.domain==T)){let C=P(A);for(let ie in A.links||{}){let G=t(ie);G&&j.addRel("",C,P(G))}}h.push({name:`${D} ${oe}`,graph:j})}}}return h}function v(f=12){let k=[],y=new Set,x={};for(let w of i)if(w.links)if(Object.keys(w.links).length<=15)for(let h in w.links)t(h)&&(x[h]=(x[h]||0)+1);else y.add(w.slug);y.size>0&&console.log("hub links ignored for large pages:",[...y]);let E=Object.entries(x).sort((w,h)=>h[1]-w[1]).slice(0,f);console.log({hits:x,hubs:E});for(let w of E){let h=`hub ${w[1]} ${w[0]}`,O=m(t(w[0]));k.push({name:h,graph:O})}return k}function I(){let f=[],k=n.lineup();console.log({lineup:k});for(let y of k){let x=wiki.lineup.atKey(y.dataset.key),E=x.getSlug(),w=x.getRemoteSite(location.host),h=t(E,w);console.log({div:y,pageObject:x,site:w,slug:E,info:h}),f.push({name:x.getTitle(),graph:m(h)})}return f}function W(){let f=[],k=n.references();console.log({items:k});for(let y of k){let{title:x,site:E,slug:w}=y,h=t(w,E);console.log({site:E,slug:w,info:h}),f.push({name:x,graph:m(h)})}return console.log({aspects:f}),f}}function V(e,o,i){let n=o.filter(c=>c.match(/\t/)).map(r).flat().sort((c,l)=>c.word<l.word?-1:1),t="zzz".slice(0,e),s=[];for(let c of n){let l=c.word.toLowerCase().slice(0,e);l!=t&&(s.push({group:l,quotes:[]}),t=l),s[s.length-1].quotes.push(c)}return s;function r(c){let[l,p]=c.split(/\t/);return p.replaceAll(/'t\b/g,"t").replaceAll(/'s\b/g,"s").split(/[^a-zA-Z]+/).filter(u=>u.length>3&&!i.has(u.toLowerCase())).map(u=>({word:u,line:c,key:l}))}}var K=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(t=>t.type==o&&t.props?.name==i?.name);return n>=0?n:this.addNode(o,i)}addRel(o,i,n,t={}){let s={type:o,from:i,to:n,props:t};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 Z(e,o){let i=()=>(e.story||[]).map(s=>s?.id),n=(s,r)=>{let c=i().indexOf(s)+1;e.story.splice(c,0,r)},t=()=>{let s=i().indexOf(o.id);s!==-1&&e.story.splice(s,1)};switch(e.story=e.story||[],o.type){case"create":o.item&&(o.item.title!=null&&(e.title=o.item.title),o.item.story!=null&&(e.story=o.item.story.slice()));break;case"add":n(o.after,o.item);break;case"edit":let s=i().indexOf(o.id);s!==-1?e.story.splice(s,1,o.item):e.story.push(o.item);break;case"move":let r=o.order.indexOf(o.id),c=o.order[r-1],l=e.story[i().indexOf(o.id)];t(),n(c,l);break;case"remove":t();break}e.journal=e.journal||[],o.fork&&e.journal.push({type:"fork",site:o.fork,date:o.date-1}),e.journal.push(o)}function F(e){if(!e.data)return;let{data:o}=e;if(o?.action=="publishSourceData"&&o?.name=="aspect"){wiki.debug&&console.log("soloListener - source update",{event:e,data:o});return}if(!e.source.opener||e.source.location.pathname!=="/plugins/solo/dialog/"){wiki.debug&&console.log("soloListener - not for us",{event:e});return}wiki.debug&&console.log("soloListener - ours",{event:e});let{action:i,keepLineup:n=!1,pageKey:t=null,title:s=null,context:r=null,page:c=null}=o,l=null;switch(t!=null&&(l=n?null:$(".page").filter((p,a)=>$(a).data("key")==t)),i){case"doInternalLink":wiki.pageHandler.context=r,wiki.doInternalLink(s,l);break;case"showResult":let p=n?{}:{$page:l};wiki.showResult(wiki.newPage(c),p);break;default:console.error({where:"soloListener",message:"unknown action",data:o})}}var se=Number.MAX_SAFE_INTEGER;function q(e,o=1e3,i=se){let n=!1,t=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()-t,t=Date.now();let p=new Promise(a=>setTimeout(a,s.minMS));return await e(s),await p,l()}}var Q={trouble:b,inspect:R,response:Y,button:re,element:ce,jfetch:le,status:ae,sourceData:ue,showResult:de,neighborhood:fe,publishSourceData:pe,newSVG:ge,SVGline:he,ticker:q};function b(e,o){e.innerText.match(/✖︎/)||(e.innerHTML+='<button style="border-width:0;color:red;">\u2716\uFE0E</button>',e.querySelector("button").addEventListener("click",i=>{e.outerHTML+=`<span style="width:80%;color:gray;">${o}</span>`}))}function R(e,o,i){let n=e.previousElementSibling;if(i.debug){let t=i[o];n.innerHTML=`${o} \u21D2 `,n.addEventListener("click",s=>{console.log({key:o,value:t});let r=n.previousElementSibling;if(!r?.classList.contains("look")){let p=document.createElement("div");p.classList.add("look"),n.insertAdjacentElement("beforebegin",p),r=n.previousElementSibling}let c=JSON.stringify(t,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 Y(e,o){e.innerHTML+=o}function re(e,o,i){e.innerHTML.match(/button/)||(Y(e,`<button style="border-width:0;">${o}</button>`),e.querySelector("button").addEventListener("click",i))}function ce(e){return document.getElementById(e)}async function le(e){return fetch(e).then(o=>o.ok?o.json():null)}function ae(e,o,i){e.innerHTML=o+i}function ue(e,o){let i=e.closest(".item"),n=B(i,o).map(({div:t,result:s})=>({classList:[...t.classList],id:t.dataset.id,result:s}));return n.length?n:(b(e,`Expected source for "${o}" in the lineup.`),null)}function pe(e,o,i){let n=e.closest(".item");n.classList.add(`${o}-source`),n[`${o}Data`]=()=>i}function de(e,o){let i={$page:$(e.closest(".page"))};wiki.showResult(wiki.newPage(o),i)}function fe(e){return Object.entries(wiki.neighborhoodObject.sites).filter(([o,i])=>!i.sitemapRequestInflight&&(!e||o.includes(e))).map(([o,i])=>(i.sitemap||[]).map(n=>Object.assign({domain:o},n)))}function ge(e){let o=document.createElement("div");return e.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>`,e.closest(".item").getElementsByTagName("svg")[0]}function he(e,[o,i],[n,t]){let s=document.createElementNS("http://www.w3.org/2000/svg","line"),r=(l,p)=>s.setAttribute(l,Math.round(p));r("x1",o),r("y1",400-i),r("x2",n),r("y2",400-t),s.style.stroke="black",s.style.strokeWidth="2px",e.appendChild(s);let c=e.getElementById("dot");c.setAttribute("cx",Math.round(n)),c.setAttribute("cy",Math.round(400-t))}async function M(e,o){let i=e.slice();for(;i.length;){let n=i.shift();if("command"in n){let t=n.command,s=o.api?o.api.element(n.key):document.getElementById(n.key),[r,...c]=n.command.split(/ +/),l=i[0],p=l&&"command"in l?null:i.shift(),a={command:t,op:r,args:c,body:p,elem:s,state:o};o.debug&&console.log(a),X[r]?await X[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 me({elem:e,body:o,state:i}){if(!o?.length)return i.api.trouble(e,"CLICK expects indented blocks to follow.");i.api.button(e,"\u25B6",n=>{i.debug=n.shiftKey,M(o,i)})}function ke({elem:e,args:o,state:i}){let n=o[0]=="world"?" \u{1F30E}":" \u{1F600}";for(let t of Object.keys(i))i.api.inspect(e,t,i);i.api.response(e,n)}async function be({elem:e,args:o,body:i,state:n}){if(!i?.length)return n.api.trouble(e,"FROM expects indented blocks to follow.");let t=o[0];n.api.response(e," \u23F3"),n.page=await n.api.jfetch(`//${t}.json`),n.api.response(e," \u231B"),M(i,n)}function we({elem:e,command:o,args:i,body:n,state:t}){if(t.api.status(e,o,""),!("page"in t))return t.api.trouble(e,'Expect "page" as with FROM.');t.api.inspect(e,"page",t);let s=t.page.story.find(u=>u.type=="datalog");if(!s)return t.api.trouble(e,"Expect Datalog plugin in the page.");let r=i[0];if(!r)return t.api.trouble(e,"SENSOR needs a sensor name.");let c=s.text.split(/\n/).map(u=>u.split(/ +/)).filter(u=>u[0]=="SENSOR").find(u=>u[1]==r);if(!c)return t.api.trouble(e,`Expect to find "${r}" in Datalog.`);let l=c[2],p=u=>9/5*(u/16)+32,a=u=>u.reduce((g,m)=>g+m,0)/u.length;t.api.status(e,o," \u23F3"),t.api.jfetch(l).then(u=>{t.debug&&console.log({sensor:c,data:u}),t.api.status(e,o," \u231B");let g=p(a(Object.values(u)));t.temperature=`${g.toFixed(2)}\xB0F`,M(n,t)})}function ye({elem:e,command:o,state:i}){let n=i?.temperature;if(!n)return i.api.trouble(e,"Expect data, as from SENSOR.");i.api.inspect(e,"temperature",i),i.api.response(e,`<br><font face=Arial size=32>${n}</font>`)}function xe({elem:e,command:o,args:i,body:n,state:t}){if(!(i&&i.length))return t.api.trouble(e,'Expected Source topic, like "markers" for Map markers.');let s=i[0],r=t.api.sourceData(e,s);if(!r)return;t.debug&&console.log({topic:s,sources:r});let c=p=>{let a=r.filter(u=>u.classList.includes(p)).length;return a?`${a} ${p}`:null},l=[c("map"),c("image"),c("frame"),c("assets")].filter(p=>p).join(", ");t.api.status(e,o," \u21D2 "+l),t[s]=r.map(({id:p,result:a})=>({id:p,result:a})),n&&M(n,t)}function $e({elem:e,command:o,args:i,state:n}){let t=u=>(+u).toFixed(7),s=[],r=i;for(let u of r)switch(u){case"map":if(!("marker"in n))return n.api.trouble(e,'"map" preview expects "marker" state, like from "SOURCE marker".');n.api.inspect(e,"marker",n);let g=n.marker.map(d=>[d.result]).flat(2).map(d=>`${t(d.lat)}, ${t(d.lon)} ${d.label||""}`).filter(_).join(` `);s.push({type:"map",text:g});break;case"graph":if(!("aspect"in n))return n.api.trouble(e,'"graph" preview expects "aspect" state, like from "SOURCE aspect".');n.api.inspect(e,"aspect",n);for(let{div:d,result:S}of n.aspect){for(let{name:v,graph:I}of S)n.debug&&console.log({div:d,result:S,name:v,graph:I}),s.push({type:"paragraph",text:v}),s.push({type:"graphviz",text:J(I)});s.push({type:"pagefold",text:"."})}break;case"items":if(!("items"in n))return n.api.trouble(e,'"graph" preview expects "items" state, like from "KWIC".');n.api.inspect(e,"items",n),s.push(...n.items);break;case"page":if(!("page"in n))return n.api.trouble(e,'"page" preview expects "page" state, like from "FROM".');n.api.inspect(e,"page",n),s.push(...n.page.story);break;case"synopsis":let m=`This page created with Mech command: "${o}". See [[${n.context.title}]].`;s.push({type:"paragraph",text:m,id:n.context.itemId});break;default:return n.api.trouble(e,`"${u}" doesn't name an item we can preview`)}let l={title:"Mech Preview"+(n.tick?` ${n.tick}`:""),story:s};for(let u of l.story)u.id||=(Math.random()*10**20).toFixed(0);let p=JSON.parse(JSON.stringify(l)),a=Date.now();l.journal=[{type:"create",date:a,item:p}],n.api.showResult(e,l)}async function Le({elem:e,command:o,args:i,body:n,state:t}){let s=l=>t.api.element(l.key),r=i[0],c=t.api.neighborhood(r);for(let l of n||[]){if(!l.command.endsWith(" Survey")){t.api.trouble(s(l),"NEIGHBORS expects a Site Survey title, like Pattern Link Survey");continue}let p=c.filter(a=>a.find(u=>u.title==l.command));t.api.status(s(l),l.command,`\u21D2 ${p.length} sites`);for(let a of p){let u=`//${a[0].domain}/${te(l.command)}.json`,g=await t.api.jfetch(u);if(!g)continue;let m=g.story.find(d=>d.type=="frame")?.survey;if(m){for(let d of a){let S=Object.assign({},m.find(v=>v.slug==d.slug),d);Object.assign(d,S)}console.log({url:u,page:g,survey:m,todo:a})}}}t.neighborhood=c.flat().sort((l,p)=>p.date-l.date),t.api.status(e,o,`\u21D2 ${t.neighborhood.length} pages, ${c.length} sites`)}function Se({elem:e,command:o,args:i,state:n}){if(!("neighborhood"in n))return n.api.trouble(e,"WALK expects state.neighborhood, like from NEIGHBORS.");n.api.inspect(e,"neighborhood",n);let[,t,s]=o.match(/\b(\d+)? *(steps|days|weeks|months|hubs|lineup|references)\b/)||[];if(!s&&o!="WALK")return tate.api.trouble(e,"WALK can't understand rest of this block.");let r={lineup(){let a=[...document.querySelectorAll(".page")],u=a.indexOf(e.closest(".page"));return a.slice(0,u)},references(){let a=e.closest(".page"),u=wiki.lineup.atKey(a.dataset.key),g=u.getRawPage().story;return console.log({div:a,pageObject:u,story:g}),g.filter(m=>m.type=="reference")}},c=z(t,s,n.neighborhood,r),l=c.filter(({graph:a})=>a);n.debug&&console.log({steps:c});let p=l.map(({graph:a})=>a.nodes).flat();if(n.api.status(e,o,` \u21D2 ${l.length} aspects, ${p.length} nodes`),c.find(({graph:a})=>!a)&&n.api.trouble(e,"WALK skipped sites with no links in sitemaps"),l.length){n.aspect=n.aspect||[];let a=n.aspect.find(u=>u.id==e.id);a?a.result=l:n.aspect.push({id:e.id,result:l,source:o}),n.api.publishSourceData(e,"aspect",n.aspect.map(u=>u.result).flat()),n.debug&&console.log({command:o,state:n.aspect,item:item.aspectData()})}}function Ee({elem:e,command:o,args:i,body:n,state:t}){if(console.log({command:o,args:i,body:n,state:t}),!n?.length)return t.api.trouble(e,"TICK expects indented blocks to follow.");let s=i[0]||"1";if(!s.match(/^[1-9][0-9]?$/))return t.api.trouble(e,"TICK expects a count from 1 to 99");let r,c;if(t.tick!=null)return c=t.tick,a({shiftKey:t.debug}),r;l();function l(){t.api.button(e,"\u25B6",a)}function p(u){t.api.status(e,o,` \u21D2 ${u} remaining`)}function a(u){t.debug=u.shiftKey,t.tick=+s,p(t.tick),r=t.api.ticker(async()=>{t.debug&&console.log({tick:t.tick,count:s}),"tick"in t&&--t.tick>=0?(p(t.tick),await M(n,t)):(r=r.api.stop(),t.tick=c,t.api.status(e,o,""),l())})}}function Te({elem:e,command:o,args:i,body:n,state:t}){if(!i.length)return b(e,"UNTIL expects an argument, a word to stop running.");if(!t.tick)return b(e,"UNTIL expects to indented below an iterator, like TICKS.");if(!t.aspect)return b(e,'UNTIL expects "aspect", like from WALK.');R(e,"aspect",t),e.innerHTML=o+` \u21D2 ${t.tick}`;let s=i[0];for(let{div:r,result:c}of t.aspect)for(let{name:l,graph:p}of c)for(let a of p.nodes)if(a.type.includes(s)||a.props.name.includes(s)){t.debug&&console.log({div:r,result:c,name:l,graph:p,node:a}),delete t.tick,e.innerHTML+=" done",n&&M(n,t);return}}function Oe({elem:e,command:o,args:i,state:n}){if(i.length<1)return n.api.trouble(e,'FORWARD expects an argument, the number of steps to move a "turtle".');n.turtle??={svg:n.api.newSVG(e),position:[200,200],direction:0};let t=i[0],s=n.turtle.direction*2*Math.PI/360,[r,c]=n.turtle.position;n.turtle.position=[r+t*Math.sin(s),c+t*Math.cos(s)],n.api.SVGline(n.turtle.svg,[r,c],n.turtle.position),n.api.status(e,o,` \u21D2 ${n.turtle.position.map(l=>(l-200).toFixed(1)).join(", ")}`)}function ve({elem:e,command:o,args:i,state:n}){if(i.length<1)return n.api.trouble(e,'TURN expects an argument, the number of degrees to turn a "turtle".');n.turtle??={svg:n.api.newSVG(e),position:[200,200],direction:0};let t=+i[0];n.turtle.direction+=t,n.api.status(e,o,` \u21D2 ${n.turtle.direction}\xB0`)}function Me({elem:e,command:o,args:i,body:n,state:t}){if(!("assets"in t))return b(e,"FILE expects state.assets, like from SOURCE assets.");R(e,"assets",t);let s="//"+window.location.host,r=t.assets.map(({id:a,result:u})=>Object.entries(u).map(([g,m])=>Object.entries(m).map(([d,S])=>S.map(v=>{let I=d.startsWith("//")?d:`${s}${d}`,W=I.replace(/\/assets$/,""),f=`${I}/${g}/${v}`;return{id:a,dir:g,path:d,host:W,file:v,url:f}})))).flat(3);if(t.debug&&console.log({assets:r}),i.length<1)return b(e,"FILE expects an argument, the dot suffix for desired files.");if(!n?.length)return b(e,"FILE expects indented blocks to follow.");let c=i[0],l=r.filter(a=>a.file.endsWith(c)),p=a=>`<img width=12 src=${l[a].host+"/favicon.png"}>`;if(!l)return b(e,`FILE expects to find an asset with "${c}" suffix.`);e.innerHTML=o+`<br><div class=choices style="border:1px solid black; background-color:#f8f8f8; padding:8px;" >${l.map((a,u)=>`<span data-choice=${u} style="cursor:pointer;"> ${p(u)} ${a.file} \u25B6 </span>`).join(`<br> `)}</div>`,e.querySelector(".choices").addEventListener("click",a=>{if(!("choice"in a.target.dataset))return;let u=l[a.target.dataset.choice].url;fetch(u).then(g=>g.text()).then(g=>{e.innerHTML=o+` \u21D2 ${g.length} bytes`,t.tsv=g,console.log({text:g}),M(n,t)})})}function Re({elem:e,command:o,args:i,body:n,state:t}){let s=n&&n[0]?.command;if(s&&!s.match(/\$[KW]/))return b(e,"KWIK expects $K or $W in link prototype.");if(!("tsv"in t))return b(e,"KWIC expects a .tsv file, like from ASSETS .tsv.");R(e,"tsv",t);let r=i[0]||1,c=t.tsv.trim().split(/\n/),l=new Set(["of","and","in","at"]),p=$(e.closest(".page")).data("data"),a=p.story.findIndex(m=>m.type=="pagefold"&&m.text=="stop");if(a>=0){let m=p.story.findIndex((d,S)=>S>a&&d.type=="pagefold");p.story.slice(a+1,m).map(d=>d.text.trim().split(/\s+/)).flat().forEach(d=>l.add(d))}let u=V(r,c,l);e.innerHTML=o+` \u21D2 ${c.length} lines, ${u.length} groups`;let g=m=>{let d=m.line;if(s){let S=s.replaceAll(/\$K\+/g,m.key.replaceAll(/ /g,"+")).replaceAll(/\$K/g,m.key).replaceAll(/\$W/g,m.word),v=s.match(/\$W/)?m.word:m.key;d=d.replace(v,S)}return d};t.items=u.map(m=>({type:"markdown",text:`# ${m.group} ${m.quotes.map(S=>g(S)).join(` `)}`}))}function je({elem:e,command:o,args:i,state:n}){e.innerHTML=o;let t,s;if(i.length<1)if(n.info)R(e,"info",n),t=n.info.domain,s=n.info.slug,e.innerHTML=o+` \u21D2 ${n.info.title}`;else return b(e,"SHOW expects a slug or site/slug to open in the lineup.");else{let l=i[0];[t,s]=l.includes("/")?l.split(/\//):[null,l]}if([...document.querySelectorAll(".page")].map(l=>l.id).includes(s))return b(e,"SHOW expects a page not already in the lineup.");let c=e.closest(".page");wiki.doInternalLink(s,c,t)}function Ie({elem:e,command:o,state:i}){if(!i.neighborhood)return b(e,"RANDOM expected a neighborhood, like from NEIGHBORS.");R(e,"neighborhood",i);let n=i.neighborhood,t=n.length,s=Math.floor(Math.random()*t);e.innerHTML=o+` \u21D2 ${s} of ${t}`,i.info=n[s]}function Ne({elem:e,command:o,args:i,body:n,state:t}){let s=i[0]||"1";return s.match(/^[1-9][0-9]?$/)?new Promise(r=>{n&&M(n,t).then(l=>{t.debug&&console.log(o,"children",l)}),e.innerHTML=o+` \u21D2 ${s} remain`;let c=setInterval(()=>{--s>0?e.innerHTML=o+` \u21D2 ${s} remain`:(clearInterval(c),e.innerHTML=o+" \u21D2 done",t.debug&&console.log(o,"done"),r())},1e3)}):b(e,"SLEEP expects seconds from 1 to 99")}function Ae({elem:e,command:o,args:i,body:n,state:t}){if(!n)return b(e,"TOGETHER expects indented commands to run together.");let s=n.map(r=>M([r],t));return Promise.all(s)}async function He({elem:e,command:o,args:i,body:n,state:t}){if(!n)return b(e,"GET expects indented commands to run on the server.");let s={},r=t.context.site;if(i.length)for(let d of i)if(d in t)R(e,d,t),s[d]=t[d];else if(d.match(/\./))r=d;else return b(e,`GET expected "${d}" to name state or site.`);let c=t.context.slug,l=t.context.itemId,p=`mech=${btoa(JSON.stringify(n))}&state=${btoa(JSON.stringify(s))}`,a=`//${r}/plugin/mech/run/${c}/${l}?${p}`;e.innerHTML=o+" \u21D2 in progress";let u=Date.now(),g;try{if(g=await fetch(a).then(d=>d.ok?d.json():d.status),"err"in g)return b(e,`RUN received error "${g.err}"`)}catch(d){return b(e,`RUN failed with "${d.message}"`)}t.result=g;for(let d of g.mech.flat(9)){let S=document.getElementById(d.key);"status"in d&&(S.innerHTML=d.command+` \u21D2 ${d.status}`),"trouble"in d&&b(S,d.trouble)}"debug"in g.state&&delete g.state.debug,Object.assign(t,g.state);let m=((Date.now()-u)/1e3).toFixed(3);e.innerHTML=o+` \u21D2 ${m} seconds`}function De({elem:e,command:o,args:i,body:n,state:t}){let s=c=>JSON.parse(JSON.stringify(c)),r=c=>JSON.stringify(c).length;if(i.length<1)return b(e,'DELTA expects argument, "have" or "apply" on client.');if(n)return b(e,"DELTA doesn't expect indented input.");switch(i[0]){case"have":let c=t.context.page.journal.filter(u=>u.type!="fork");t.recent=c[c.length-1].date,e.innerHTML=o+` \u21D2 ${new Date(t.recent).toLocaleString()}`;break;case"apply":if(!("actions"in t))return b(e,'DELTA apply expect "actions" as input.');R(e,"actions",t);let l=s(t.context.page),p=r(l);for(let u of t.actions)Z(l,u);t.page=l;let a=r(l);e.innerHTML=o+` \u21D2 \u2206 ${((a-p)/p*100).toFixed(1)}%`;break;default:b(e,`DELTA doesn't know "${i[0]}".`)}}function Ke({elem:e,command:o,state:i}){if(!i.neighborhood)return b(e,"ROSTER expected a neighborhood, like from NEIGHBORS.");R(e,"neighborhood",i);let n=i.neighborhood,t=n.map(c=>c.domain).filter(_),s=c=>c[Math.floor(Math.random()*c.length)];i.debug&&console.log(n);let r=[{type:"roster",text:`Mech `+t.join(` `)},{type:"activity",text:`ROSTER Mech SINCE 30 days`}];e.innerHTML=o+` \u21D2 ${t.length} sites`,i.items=r}function _e({elem:e,command:o,state:i}){let n=[...document.querySelectorAll(".page")].map(t=>{let s=$(t),r=s.data("data"),c=s.data("site")||location.host,l=s.attr("id").split("_")[0],p=r.title||"Empty",a=r.story[0]?.text||"empty";return{type:"reference",site:c,slug:l,title:p,text:a}});e.innerHTML=o+` \u21D2 ${n.length} pages`,i.items=n}function Pe({elem:e,command:o,args:i,state:n}){if(i.length<1)return b(e,"LISTEN expects argument, an action.");let t=i[0],s=Date.now(),r=0,c=l;c.action="publishSourceData",c.id=e.id,window.addEventListener("message",l),$(".main").on("thumb",(p,a)=>console.log("jquery",{evt:p,thumb:a})),e.innerHTML=o+" \u21D2 ready";function l(p){console.log({event:p});let{data:a}=p;if(a.action=="publishSourceData"&&(a.name==t||a.topic==t))if(r++,c.count=r,n.debug&&console.log({count:r,data:a}),r<=100){let u=Date.now(),g=u-s;s=u,e.innerHTML=o+` \u21D2 ${r} events, ${g} ms`}else window.removeEventListener("message",l)}}function We({elem:e,command:o,args:i,state:n}){if(i.length<1)return b(e,"MESSAGE expects argument, an action.");let t=i[0],s={action:"publishSourceData",topic:t,name:t};window.postMessage(s,"*"),e.innerHTML=o+" \u21D2 sent"}async function Ce({elem:e,command:o,state:i}){if(!("aspect"in i))return b(e,'"SOLO" expects "aspect" state, like from "WALK".');R(e,"aspect",i),e.innerHTML=o;let n=i.aspect.map(l=>({source:l.source||l.id,aspects:l.result})),t=n.reduce((l,p)=>l+p.aspects.length,0);e.innerHTML+=` \u21D2 ${n.length} sources, ${t} aspects`;let s=e.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=F,window.addEventListener("message",F)),await ee(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 Fe({elem:e,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 b(e,'POPUP images expects "commons" state, like from "GET" "COMMONS"');let t=o[1]=="all"?i.commons.all:i.commons.here;for(let s of t.items)n.push(`<span><img height=200 src=/assets/plugins/image/${s}></span>`);break;default:return b(e,`POPUP doesn't know "${o[0]}".`)}wiki.dialog(e.innerText,n.join(` `))}var X={CLICK:{emit:me},HELLO:{emit:ke},FROM:{emit:be},SENSOR:{emit:we},REPORT:{emit:ye},SOURCE:{emit:xe},PREVIEW:{emit:$e},NEIGHBORS:{emit:Le},WALK:{emit:Se},TICK:{emit:Ee},UNTIL:{emit:Te},FORWARD:{emit:Oe},TURN:{emit:ve},FILE:{emit:Me},KWIC:{emit:Re},SHOW:{emit:je},RANDOM:{emit:Ie},SLEEP:{emit:Ne},TOGETHER:{emit:Ae},GET:{emit:He},DELTA:{emit:De},ROSTER:{emit:Ke},LINEUP:{emit:_e},LISTEN:{emit:Pe},MESSAGE:{emit:We},SOLO:{emit:Ce},POPUP:{emit:Fe}};function qe(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function U(e,o,i){for(;e.length;){let t=e[0].match(/( *)(.*)/),s=t[1].length,r=t[2];if(s==i)o.push({command:r}),e.shift();else if(s>i){var n=[];o.push(n),U(e,n,s)}else return o}return o}function ne(e){let o=Math.floor(Math.random()*1e6),i=(n,t)=>{let s=[];for(let r of n){let c=`${o}.${t.join(".")}`;r.key=c,"command"in r?s.push(`<font color=gray size=small></font><span style="display: block;" id=${c}>${qe(r.command)}</span>`):s.push(`<div id=${c} style="padding-left:15px">${i(r,[...t,0])}</div>`),t[t.length-1]++}return s.join(` `)};return i(e,[0])}var _=(e,o,i)=>i.indexOf(e)===o,ee=e=>new Promise(o=>setTimeout(o,e)),te=e=>e.replace(/\s/g,"-").replace(/[^A-Za-z0-9-]/g,"").toLowerCase();function at(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function Ue(e,o){let i=o.text.split(/\n/),n=U(i,[],0),t=ne(n),s=e.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:Q};e.append(`<div style="background-color:#eee;padding:15px;border-top:8px;">${t}</div>`),M(n,l)}function Ge(e,o){return e.dblclick(()=>wiki.textEditor(e,o))}typeof window<"u"&&window!==null&&(window.plugins.mech={emit:Ue,bind:Ge});})(); //# sourceMappingURL=mech.js.map