wiki-plugin-mech 0.1.34 → 0.1.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/mech.css +27 -0
- package/client/mech.js +28 -18
- package/client/mech.js.map +3 -3
- package/package.json +1 -1
- package/pages/catalog-of-mech-blocks +666 -10
package/client/mech.css
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/* blocks and subtrees */
|
|
2
|
+
.mech span.block {
|
|
3
|
+
display: block;
|
|
4
|
+
}
|
|
5
|
+
.mech div.body {
|
|
6
|
+
display: block;
|
|
7
|
+
padding-left: 15px;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/* trouble found and explained */
|
|
11
|
+
.mech button.trouble {
|
|
12
|
+
border-width: 0;
|
|
13
|
+
color: red;
|
|
14
|
+
}
|
|
15
|
+
.mech span.trouble {
|
|
16
|
+
width: 80%;
|
|
17
|
+
color: gray;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* inspect look and seen */
|
|
21
|
+
.mech .see {
|
|
22
|
+
border: 1px solid black;
|
|
23
|
+
background-color: #f8f8f8;
|
|
24
|
+
padding: 8px;
|
|
25
|
+
color: gray;
|
|
26
|
+
word-break: break-all;
|
|
27
|
+
}
|
package/client/mech.js
CHANGED
|
@@ -1,30 +1,40 @@
|
|
|
1
|
-
/* wiki-plugin-mech - 0.1.
|
|
2
|
-
(()=>{function
|
|
3
|
-
`)}function
|
|
4
|
-
`),title:
|
|
5
|
-
`),title:
|
|
6
|
-
`),title:
|
|
7
|
-
`),
|
|
8
|
-
`," ");
|
|
1
|
+
/* wiki-plugin-mech - 0.1.36 - Sat, 14 Mar 2026 03:40:59 GMT */
|
|
2
|
+
(()=>{function ne(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 oe(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 c=t.type?`${t.type}\\n${t.props.name}`:t.props.name;return`${s} [label="${c}" ${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(`
|
|
3
|
+
`)}function ie(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,c=f=>Math.floor(f*Math.abs(Math.random()-Math.random())),r=f=>f[c(f.length)],l=f=>f.links&&Object.keys(f.links).length<10,u=f=>i.filter(k=>l(k)&&f in k.links),a=(f,k,y)=>y.findIndex(h=>h.slug==f.slug)===k,p=f=>f.toSorted((k,y)=>y.date-k.date).filter(a).slice(0,3),S=i.map(f=>f.domain).filter(V);function L(f){let k=new U,y=d=>k.addUniqNode("",{name:d.title.replaceAll(/ /g,`
|
|
4
|
+
`),title:d.title,site:d.domain}),h=d=>s(d?.patterns?.up)??p(u(d.slug)),w=d=>d?.patterns?.down??Object.keys(d.links||{}),x=y(f);for(let d of h(f))k.addRel("",y(d),x);for(let d of w(f)){let v=t(d);if(v){let N=y(v);k.addRel("",x,N);for(let R of h(v))k.addRel("",y(R),N)}}return k}switch(o){case"steps":return g(e);case"days":return I(o,1,e);case"weeks":return I(o,7,e);case"months":return I(o,30,e);case"hubs":return K(e);case"references":return z();case"lineup":return G();case"topics":return E(e);case"clicks":return P(e)}function g(f=5){return S.map(k=>{let y=k.split(".").slice(0,3).join("."),h=new Set,w=new U,x=0,d=i.filter(m=>m.domain==k&&"links"in m);if(!d.length)return{name:y,graph:null};let v=m=>(x=w.addNode("",{name:m.title.replaceAll(/ /g,`
|
|
5
|
+
`),title:m.title,site:k,links:Object.keys(m.links||{}).filter(b=>t(b))}),x),N=(m,b)=>w.addRel("",m,b),R=m=>w.nodes[m].props.links.filter(b=>!h.has(b)),M=r(d);h.add(M.slug),v(M);for(let m=5;m>0;m--)try{let b=R(x),A=r(b);h.add(A);let H=t(A);N(x,v(H))}catch{}return{name:y,graph:w}})}function I(f,k,y=12){let h=k*24*60*60*1e3,x=[...Array(Number(y)).keys()].map(v=>Date.now()-v*h),d=[];for(let v of x){let N=v-h,R=`${f.replace(/s$/,"")} ${new Date(N).toLocaleDateString()}`,M=i.filter(m=>m.date<v&&m.date>=N).filter(m=>!(m.links&&Object.keys(m.links).length>5));if(M.length){let m=M.reduce((b,A)=>(b.add(A.domain),b),new Set);for(let b of m){let A=new U,H=D=>A.addUniqNode("",{name:D.title.replaceAll(/ /g,`
|
|
6
|
+
`),title:D.title,site:D.domain,date:D.date}),F=b.split(/\.|\:/)[0];for(let D of M.filter(_=>_.domain==b)){let _=H(D);for(let B in D.links||{}){let q=t(B);q&&A.addRel("",_,H(q))}}d.push({name:`${R} ${F}`,graph:A})}}}return d}function K(f=12){let k=[],y=new Set,h={};for(let x of i)if(x.links)if(Object.keys(x.links).length<=15)for(let d in x.links)t(d)&&(h[d]=(h[d]||0)+1);else y.add(x.slug);y.size>0&&console.log("hub links ignored for large pages:",[...y]);let w=Object.entries(h).sort((x,d)=>d[1]-x[1]).slice(0,f);console.log({hits:h,hubs:w});for(let x of w){let d=`hub ${x[1]} ${x[0]}`,v=L(t(x[0]));k.push({name:d,graph:v})}return k}function G(){let f=[],k=n.lineup();console.log("library lineup",{scope:n,pageObjects:k});for(let y of k){let h=y.getSlug(),w=y.getRemoteSite(n.host()),x=t(h,w);f.push({name:y.getTitle(),graph:L(x)})}return f}function z(){let f=[],k=n.references();console.log("library references",{items:k});for(let y of k){let{title:h,site:w,slug:x}=y,d=t(x,w);d&&f.push({name:h,graph:L(d)})}return f}function E(f=10){let k=[],w=R=>Date.now()-R*6048e5,x=0;for(;k.length<f&&x<f;){let R=w(x++),M=w(x),m=i.filter(b=>b.date>M&&b.date<=R).filter(b=>!!b.links).filter(b=>!b.title.endsWith(" Survey"));if(m.length){let b=d(m),A=new Date(R).toLocaleDateString();k.push(...N({name:A,graph:b},M,R))}}return k;function d(R){let M=new U,m=b=>{let A="",H=i.find(j=>j.slug==b),F=i.filter(j=>j.slug==b).length,D=H.title,_=H.domain,B=H.date,q=D.replaceAll(" ",`
|
|
7
|
+
`),X=M.nodes.findIndex(j=>j.type==A&&j.props.name==q),O=X>=0?X:M.addNode(A,{name:q,site:_,date:B});return F>1&&(M.nodes[O].props.twins=F),O};for(let b of R){let A=m(b.slug);for(let H of v(Object.keys(b.links)))M.addRel("",A,m(H))}return M}function v(R){let M=m=>i.filter(b=>b.slug==m);return R.map(m=>[m,M(m)]).filter(m=>m[1].length).map(m=>[m[0],m[1].sort((b,A)=>A.date-b.date)[0]]).sort((m,b)=>b[1].date-m[1].date).map(m=>m[0]).slice(0,3)}function N(R,M,m){let b=R.graph,A=[],H={},F=b.nodes,D=b.rels,_=[...Array(F.length).keys()].map(O=>[O,Math.random()]).sort((O,j)=>O[1]-j[1]).map(O=>O[0]),B=O=>{if(O in H)return;_.splice(_.indexOf(O),1);let j=F[O];H[O]=A[0].addNode(j.type,j.props);for(let J of j.out)B(D[J].to);for(let J of j.in)B(D[J].from);for(let J of j.out)A[0].addRel("",H[O],H[D[J].to],{})};for(;_.length;){let O=_.shift();if(O in H)continue;let j=F[O],J=j.props.name.replaceAll(`
|
|
8
|
+
`," ");j.in.length+j.out.length&&(A.unshift(new U),H={},B(O))}let q=O=>O.props.date||0,X=O=>{let j=O.nodes.slice(0).sort((Q,fe)=>q(fe)-q(Q)).filter(Q=>q(Q)>=M&&q(Q)<=m)[0];return console.log({node:j,nodes:O.nodes,name:R.name}),j?j.props.name.split(/\s+/).slice(0,3).join(" "):R.name};return A.reverse().map((O,j)=>({name:X(O),graph:O}))}}function P(f=1){let k=(d,v,N={})=>d.addUniqNode("",Object.assign({name:v.title.replaceAll(/ /g,`
|
|
9
|
+
`),title:v.title,site:v.domain,date:v.date},N)),y=[],w=n.page().story.filter(d=>d.type=="reference").map(d=>d.slug);for(let d of w){let v=i.find(R=>R.slug==d),N=new U;if(v){let R=k(N,v,{color:"lightblue"});x(N,f,R,v)}else N.addNode("",{name:d.replaceAll(/-/g,`
|
|
10
|
+
`),color:"white"});y.push({name:d,graph:N})}return y;function x(d,v,N,R){if(!(v<1))for(let M in R.links){if(w.includes(M))return;let m=i.find(b=>b.slug==M);if(m){let b=k(d,m);d.addRel("",N,b,{}),x(d,v-1,b,m)}else{let b=d.addUniqNode("",{name:M.replaceAll(/-/g,`
|
|
11
|
+
`),color:"white"});d.addRel("",N,b,{})}}}}}function se(e,o,i){let n=o.filter(r=>r.match(/\t/)).map(c).flat().sort((r,l)=>r.word<l.word?-1:1),t="zzz".slice(0,e),s=[];for(let r of n){let l=r.word.toLowerCase().slice(0,e);l!=t&&(s.push({group:l,quotes:[]}),t=l),s[s.length-1].quotes.push(r)}return s;function c(r){let[l,u]=r.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:r,key:l}))}}var U=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 c=this.rels.length-1;return this.nodes[i].out.push(c),this.nodes[n].in.push(c),c}stringify(...o){let i={nodes:this.nodes,rels:this.rels};return JSON.stringify(i,...o)}};function re(e,o){let i=()=>(e.story||[]).map(s=>s?.id),n=(s,c)=>{let r=i().indexOf(s)+1;e.story.splice(r,0,c)},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 c=o.order.indexOf(o.id),r=o.order[c-1],l=e.story[i().indexOf(o.id)];t(),n(r,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 Y(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:c=null,page:r=null}=o,l=null;switch(t!=null&&(l=n?null:$(".page").filter((u,a)=>$(a).data("key")==t)),i){case"doInternalLink":wiki.pageHandler.context=c,wiki.doInternalLink(s,l);break;case"showResult":let u=n?{}:{$page:l};wiki.showResult(wiki.newPage(r),u);break;default:console.error({where:"soloListener",message:"unknown action",data:o})}}var ge=Number.MAX_SAFE_INTEGER;function ee(e,o=1e3,i=ge){let n=!1,t=Date.now(),s={stop:r,remainingTicks:i,minMS:o,ticksSoFar:0,timeSinceLastTick:0},c=l();return c.api=s,c;function r(){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 u=new Promise(a=>setTimeout(a,s.minMS));return await e(s),await u,l()}}var le={trouble:T,inspect:C,response:ae,button:he,element:me,jfetch:ke,status:be,sourceData:ye,showResult:xe,neighborhood:$e,publishSourceData:we,newSVG:Se,SVGline:Le,ticker:ee,lineupAtKey:pe,thisLineupKey:Te,lineupPages:Ee,host:ve,download:Oe,closeTags:Re,reset:Me};function T(e,o){e.innerText.match(/✖︎/)||(e.innerHTML+="<button class=trouble>\u2716\uFE0E</button>",e.querySelector("button").addEventListener("click",i=>{e.outerHTML+=`<span class=trouble>${o}</span>`}))}function C(e,o,i){let n=e.previousElementSibling;if(i.debug){let t=n.querySelector(`.look [data-key="${o}"]`);t||(t=document.createElement("div"),t.classList.add("look"),t.dataset.key=o,t.innerHTML=`<font color=gray size=small>${o} \u21D2</font>`,n.insertAdjacentElement("beforeend",t)),t.querySelector("font").addEventListener("click",s=>{let c=t.querySelector(".see");c||(c=document.createElement("div"),c.classList.add("see"),t.insertAdjacentElement("beforeend",c)),c.innerText=JSON.stringify(i[o]).substring(0,400)+" ..."})}}function ae(e,o){e.innerHTML+=o}function he(e,o,i){e.innerHTML.match(/button/)||(ae(e,`<button style="border-width:0;">${o}</button>`),e.querySelector("button").addEventListener("click",i))}function me(e){return document.getElementById(e)}async function ke(e){return fetch(e).then(o=>o.ok?o.json():null)}function be(e,o,i){e.innerHTML=o+i}function ye(e,o){let i=e.closest(".item"),n=ne(i,o).map(({div:t,result:s})=>({classList:[...t.classList],id:t.dataset.id,result:s}));return n.length?n:(T(e,`Expected source for "${o}" in the lineup.`),null)}function we(e,o,i){let n=e.closest(".item");n.classList.add(`${o}-source`),n[`${o}Data`]=()=>i}function xe(e,o){let i={$page:$(e.closest(".page"))};wiki.showResult(wiki.newPage(o),i)}function $e(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 Se(e){let o=document.createElement("div");return e.closest(".item").firstElementChild.prepend(o),o.outerHTML=`
|
|
9
12
|
<div style="border:1px solid black; background-color:#f8f8f8; margin-bottom:16px;">
|
|
10
13
|
<svg viewBox="0 0 400 400" width=100% height=400>
|
|
11
14
|
<circle id=dot r=5 cx=200 cy=200 stroke="#ccc"></circle>
|
|
12
15
|
</svg>
|
|
13
|
-
</div>`,e.closest(".item").getElementsByTagName("svg")[0]}function Le(e,[o,i],[t
|
|
14
|
-
`);s.push({type:"map",text:
|
|
16
|
+
</div>`,e.closest(".item").getElementsByTagName("svg")[0]}function Le(e,[o,i],[n,t]){let s=document.createElementNS("http://www.w3.org/2000/svg","line"),c=(l,u)=>s.setAttribute(l,Math.round(u));c("x1",o),c("y1",400-i),c("x2",n),c("y2",400-t),s.style.stroke="black",s.style.strokeWidth="2px",e.appendChild(s);let r=e.getElementById("dot");r.setAttribute("cx",Math.round(n)),r.setAttribute("cy",Math.round(400-t))}function pe(e){return wiki.lineup.atKey(e)}function Te(e){return e.closest(".page").dataset.key}function Ee(e){let o=[...document.querySelectorAll(".page")],i=o.indexOf(e.closest(".page"));return o.slice(0,i).map(t=>pe(t.dataset.key))}function ve(){location.host}function Oe(e,o,i="text/json"){var n=`data:${i};charset=utf-8,`+encodeURIComponent(e),t=document.createElement("a");t.setAttribute("href",n),t.setAttribute("download",o),document.body.appendChild(t),t.click(),t.remove()}function Re(e){let o=document.createElement("div");return o.innerHTML=e,o.innerHTML}function Me(e){let o=e.nextElementSibling;console.log("reset",o),o.querySelectorAll("div.look").forEach(i=>i.innerText="")}async function W(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),[c,...r]=n.command.split(/ +/),l=i[0],u=l&&"command"in l?null:i.shift(),a={command:t,op:c,args:r,body:u,elem:s,state:o};o.debug&&console.log(a),ce[c]?await ce[c].emit.apply(null,[a]):c.match(/^[A-Z]+$/)?o.api.trouble(s,`${c} doesn't name a block we know.`):n.command.match(/\S/)&&o.api.trouble(s,"Expected line to begin with all-caps keyword.")}}}function je({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.api.reset(e),i.debug=n.shiftKey,W(o,i)})}function Ae({elem:e,args:o,state:i}){let n=o[0]=="world"?" \u{1F30E}":" \u{1F600}",t=Object.keys(i).filter(s=>!["context","api","debug"].includes(s));for(let s of t)i.api.inspect(e,s,i);i.api.response(e,n)}async function Ie({elem:e,command:o,args:i,body:n,state:t}){if(!i[0])return t.api.trouble(e,"FROM expects site/slug as way to federated wiki page.");if(!n?.length)return t.api.trouble(e,"FROM expects indented blocks to follow.");let s=i[0];t.api.status(e,o," \u23F3");let c=await t.api.jfetch(`//${s}.json`);if(!c)return t.api.trouble(e,`FROM could not fetch "${s}" `);t.page=c,t.api.status(e,o," \u231B"),W(n,t)}function Ne({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(p=>p.type=="datalog");if(!s)return t.api.trouble(e,"Expect Datalog plugin in the page.");let c=i[0];if(!c)return t.api.trouble(e,"SENSOR needs a sensor name.");let r=s.text.split(/\n/).map(p=>p.split(/ +/)).filter(p=>p[0]=="SENSOR").find(p=>p[1]==c);if(!r)return t.api.trouble(e,`Expect to find "${c}" in Datalog.`);let l=r[2],u=p=>9/5*(p/16)+32,a=p=>p.reduce((S,L)=>S+L,0)/p.length;t.api.status(e,o," \u23F3"),t.api.jfetch(l).then(p=>{t.debug&&console.log({sensor:r,data:p}),t.api.status(e,o," \u231B");let S=u(a(Object.values(p)));t.temperature=`${S.toFixed(2)}\xB0F`,W(n,t)})}function He({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 Pe({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],c=t.api.sourceData(e,s);if(!c)return;t.debug&&console.log({topic:s,sources:c});let r=u=>{let a=c.filter(p=>p.classList.includes(u)).length;return a?`${a} ${u}`:null},l=[r("map"),r("image"),r("frame"),r("assets")].filter(u=>u).join(", ");t.api.status(e,o," \u21D2 "+l),t[s]=c.map(({id:u,result:a})=>({id:u,result:a})),n&&W(n,t)}function De({elem:e,command:o,args:i,state:n}){let t=p=>(+p).toFixed(7),s=[],c=i;for(let p of c)switch(p){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 S=n.marker.map(g=>[g.result]).flat(2).map(g=>`${t(g.lat)}, ${t(g.lon)} ${g.label||""}`).filter(V).join(`
|
|
17
|
+
`);s.push({type:"map",text:S});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{result:g}of n.aspect){for(let{name:I,graph:K}of g)n.debug&&console.log({name:I,graph:K}),s.push({type:"paragraph",text:I}),s.push({type:"graphviz",text:oe(K)});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 L=`This page created with Mech command: "${o}". See [[${n.context.title}]].`;s.push({type:"paragraph",text:L,id:n.context.itemId});break;default:return n.api.trouble(e,`"${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(e,l)}async function Ke({elem:e,command:o,args:i,body:n,state:t}){let s=r=>t.api.element(r.key),c=t.api.neighborhood(i[0]);for(let r=1;r<i.length;r++)c.push(...t.api.neighborhood(i[r]));c=c.filter((r,l)=>r.length&&!c.slice(0,l).find(u=>u[0]?.domain==r[0]?.domain)),console.log("Sites:",c.map(r=>r[0]?.domain));for(let r of n||[]){if(!r.command.endsWith(" Survey")){t.api.trouble(s(r),"NEIGHBORS expects a Site Survey title, like Pattern Link Survey");continue}let l=c.filter(u=>u.find(a=>a.title==r.command));t.api.status(s(r),r.command,`\u21D2 ${l.length} sites`);for(let u of l){let a=`//${u[0].domain}/${Z(r.command)}.json`,p=await t.api.jfetch(a);if(!p)continue;let S=p.story.find(L=>L.type=="frame")?.survey;if(S)for(let L of u){let g=Object.assign({},S.find(I=>I.slug==L.slug),L);Object.assign(L,g)}}}t.neighborhood=c.flat(),t.api.status(e,o,`\u21D2 ${t.neighborhood.length} pages, ${c.length} sites`)}function We({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|topics|clicks)\b/)||[];if(!s&&o!="WALK")return n.api.trouble(e,"WALK can't understand rest of this block.");let c={host(){return n.api.host()},lineup(){return n.api.lineupPages(e)},references(){let a=n.api.thisLineupKey(e);return n.api.lineupAtKey(a).getRawPage().story.filter(L=>L.type=="reference")},page(){return n.page||n.api.trouble(e,"WALK expects a page, like from FROM"),n.api.inspect(e,"page",n),n.page}},r=ie(t,s,n.neighborhood,c),l=r.filter(({graph:a})=>a);n.debug&&console.log({steps:r});let u=l.map(({graph:a})=>a.nodes).flat();if(n.api.status(e,o,` \u21D2 ${l.length} aspects, ${u.length} nodes`),r.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(p=>p.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(p=>p.result).flat()),n.debug&&console.log({command:o,state:n.aspect})}}function _e({elem:e,command:o,args:i,body:n,state:t}){if(!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 c,r;if(t.tick!=null)return r=t.tick,a({shiftKey:t.debug}),c;l();function l(){t.api.button(e,"\u25B6",a)}function u(p){t.api.status(e,o,` \u21D2 ${p} remaining`)}function a(p){t.debug=p.shiftKey,t.tick=+s,u(t.tick),c=t.api.ticker(async()=>{t.debug&&console.log({tick:t.tick,count:s}),"tick"in t&&--t.tick>=0?(u(t.tick),await W(n,t)):(c=c.api.stop(),t.tick=r,t.api.status(e,o,""),l())})}}function qe({elem:e,command:o,args:i,body:n,state:t}){if(!i.length)return T(e,"UNTIL expects an argument, a word to stop running.");if(!t.tick)return T(e,"UNTIL expects to indented below an iterator, like TICKS.");if(!t.aspect)return T(e,'UNTIL expects "aspect", like from WALK.');C(e,"aspect",t),e.innerHTML=o+` \u21D2 ${t.tick}`;let s=i[0];for(let{div:c,result:r}of t.aspect)for(let{name:l,graph:u}of r)for(let a of u.nodes)if(a.type.includes(s)||a.props.name.includes(s)){t.debug&&console.log({div:c,result:r,name:l,graph:u,node:a}),delete t.tick,e.innerHTML+=" done",n&&W(n,t);return}}function Ce({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,[c,r]=n.turtle.position;n.turtle.position=[c+t*Math.sin(s),r+t*Math.cos(s)],n.api.SVGline(n.turtle.svg,[c,r],n.turtle.position),n.api.status(e,o,` \u21D2 ${n.turtle.position.map(l=>(l-200).toFixed(1)).join(", ")}`)}function Fe({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 Ue({elem:e,command:o,args:i,body:n,state:t}){if(!("assets"in t))return T(e,"FILE expects state.assets, like from SOURCE assets.");C(e,"assets",t);let s="//"+window.location.host,c=t.assets.map(({id:a,result:p})=>Object.entries(p).map(([S,L])=>Object.entries(L).map(([g,I])=>I.map(K=>{let G=g.startsWith("//")?g:`${s}${g}`,z=G.replace(/\/assets$/,""),E=`${G}/${S}/${K}`;return{id:a,dir:S,path:g,host:z,file:K,url:E}})))).flat(3);if(t.debug&&console.log({assets:c}),i.length<1)return T(e,"FILE expects an argument, the dot suffix for desired files.");if(!n?.length)return T(e,"FILE expects indented blocks to follow.");let r=i[0],l=c.filter(a=>a.file.endsWith(r)),u=a=>`<img width=12 src=${l[a].host+"/favicon.png"}>`;if(!l)return T(e,`FILE expects to find an asset with "${r}" suffix.`);e.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;">
|
|
15
18
|
${u(p)}
|
|
16
19
|
${a.file} \u25B6
|
|
17
20
|
</span>`).join(`<br>
|
|
18
|
-
`)}</div>`,e.querySelector(".choices").addEventListener("click",a=>{if(!("choice"in a.target.dataset))return;let p=l[a.target.dataset.choice].url;fetch(p).then(
|
|
21
|
+
`)}</div>`,e.querySelector(".choices").addEventListener("click",a=>{if(!("choice"in a.target.dataset))return;let p=l[a.target.dataset.choice].url;fetch(p).then(S=>S.text()).then(S=>{e.innerHTML=o+` \u21D2 ${S.length} bytes`,t.tsv=S,W(n,t)})})}function Ge({elem:e,command:o,args:i,body:n,state:t}){let s=n&&n[0]?.command;if(s&&!s.match(/\$[KW]/))return T(e,"KWIK expects $K or $W in link prototype.");if(!("tsv"in t))return T(e,"KWIC expects a .tsv file, like from ASSETS .tsv.");C(e,"tsv",t);let c=i[0]||1,r=t.tsv.trim().split(/\n/),l=new Set(["of","and","in","at"]),u=$(e.closest(".page")).data("data"),a=u.story.findIndex(L=>L.type=="pagefold"&&L.text=="stop");if(a>=0){let L=u.story.findIndex((g,I)=>I>a&&g.type=="pagefold");u.story.slice(a+1,L).map(g=>g.text.trim().split(/\s+/)).flat().forEach(g=>l.add(g))}let p=se(c,r,l);e.innerHTML=o+` \u21D2 ${r.length} lines, ${p.length} groups`;let S=L=>{let g=L.line;if(s){let I=s.replaceAll(/\$K\+/g,L.key.replaceAll(/ /g,"+")).replaceAll(/\$K/g,L.key).replaceAll(/\$W/g,L.word),K=s.match(/\$W/)?L.word:L.key;g=g.replace(K,I)}return g};t.items=p.map(L=>({type:"markdown",text:`# ${L.group}
|
|
19
22
|
|
|
20
|
-
${
|
|
21
|
-
`)}`}))}function
|
|
22
|
-
`+
|
|
23
|
+
${L.quotes.map(I=>S(I)).join(`
|
|
24
|
+
`)}`}))}function Be({elem:e,command:o,args:i,state:n}){e.innerHTML=o;let t,s;if(i.length<1)if(n.info)C(e,"info",n),t=n.info.domain,s=n.info.slug,e.innerHTML=o+` \u21D2 ${n.info.title}`;else return T(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 T(e,"SHOW expects a page not already in the lineup.");let r=e.closest(".page");wiki.doInternalLink(s,r,t)}function Je({elem:e,command:o,state:i}){if(!i.neighborhood)return T(e,"RANDOM expected a neighborhood, like from NEIGHBORS.");C(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 ze({elem:e,command:o,args:i,body:n,state:t}){let s=i[0]||"1";return s.match(/^[1-9][0-9]?$/)?new Promise(c=>{n&&W(n,t).then(l=>{t.debug&&console.log(o,"children",l)}),e.innerHTML=o+` \u21D2 ${s} remain`;let r=setInterval(()=>{--s>0?e.innerHTML=o+` \u21D2 ${s} remain`:(clearInterval(r),e.innerHTML=o+" \u21D2 done",t.debug&&console.log(o,"done"),c())},1e3)}):T(e,"SLEEP expects seconds from 1 to 99")}function Ve({elem:e,command:o,args:i,body:n,state:t}){if(!n)return T(e,"TOGETHER expects indented commands to run together.");let s=n.map(c=>W([c],t));return Promise.all(s)}async function Ze({elem:e,command:o,args:i,body:n,state:t}){if(!n)return T(e,"GET expects indented commands to run on the server.");let s={},c=t.context.site;if(i.length)for(let g of i)if(g in t)C(e,g,t),s[g]=t[g];else if(g.match(/\./))c=g;else return T(e,`GET expected "${g}" to name state or site.`);let r=t.context.slug,l=t.context.itemId,u=`mech=${btoa(JSON.stringify(n))}&state=${btoa(JSON.stringify(s))}`,a=`//${c}/plugin/mech/run/${r}/${l}?${u}`;e.innerHTML=o+" \u21D2 in progress";let p=Date.now(),S;try{if(S=await fetch(a).then(g=>g.ok?g.json():g.status),"err"in S)return T(e,`RUN received error "${S.err}"`)}catch(g){return T(e,`RUN failed with "${g.message}"`)}t.result=S;for(let g of S.mech.flat(9)){let I=document.getElementById(g.key);"status"in g&&(I.innerHTML=g.command+` \u21D2 ${g.status}`),"trouble"in g&&T(I,g.trouble)}"debug"in S.state&&delete S.state.debug,Object.assign(t,S.state);let L=((Date.now()-p)/1e3).toFixed(3);e.innerHTML=o+` \u21D2 ${L} seconds`}function Xe({elem:e,command:o,args:i,body:n,state:t}){let s=r=>JSON.parse(JSON.stringify(r)),c=r=>JSON.stringify(r).length;if(i.length<1)return T(e,'DELTA expects argument, "have" or "apply" on client.');if(n)return T(e,"DELTA doesn't expect indented input.");switch(i[0]){case"have":let r=t.context.page.journal.filter(p=>p.type!="fork");t.recent=r[r.length-1].date,e.innerHTML=o+` \u21D2 ${new Date(t.recent).toLocaleString()}`;break;case"apply":if(!("actions"in t))return T(e,'DELTA apply expect "actions" as input.');C(e,"actions",t);let l=s(t.context.page),u=c(l);for(let p of t.actions)re(l,p);t.page=l;let a=c(l);e.innerHTML=o+` \u21D2 \u2206 ${((a-u)/u*100).toFixed(1)}%`;break;default:T(e,`DELTA doesn't know "${i[0]}".`)}}function Qe({elem:e,command:o,state:i}){if(!i.neighborhood)return i.api.trouble(e,"ROSTER expected a neighborhood, like from NEIGHBORS.");i.api.inspect(e,"neighborhood",i);let n=i.neighborhood,t=n.map(r=>r.domain).filter(V),s=r=>r[Math.floor(Math.random()*r.length)];i.debug&&console.log(n);let c=[{type:"roster",text:`Mech
|
|
25
|
+
`+t.join(`
|
|
23
26
|
`)},{type:"activity",text:`ROSTER Mech
|
|
24
|
-
SINCE 30 days`}];i.api.status(e,o,` \u21D2 ${
|
|
27
|
+
SINCE 30 days`}];i.api.status(e,o,` \u21D2 ${t.length} sites`),i.items=c}function Ye({elem:e,command:o,state:i}){let n=i.api.lineupPages(e).map(t=>{let s=t.getRawPage(),c=t.getRemoteSite(i.api.host()),r=s.title||"Empty",l=Z(r),u=s.story[0]?.text||"empty";return{type:"reference",site:c,slug:l,title:r,text:u}});i.api.status(e,o,` \u21D2 ${n.length} pages`),i.items=n}function et({elem:e,command:o,args:i,state:n}){if(i.length<1)return T(e,"LISTEN expects argument, an action.");let t=i[0],s=Date.now(),c=0,r=l;r.action="publishSourceData",r.id=e.id,window.addEventListener("message",l),$(".main").on("thumb",(u,a)=>console.log("jquery",{evt:u,thumb:a})),e.innerHTML=o+" \u21D2 ready";function l(u){console.log({event:u});let{data:a}=u;if(a.action=="publishSourceData"&&(a.name==t||a.topic==t))if(c++,r.count=c,n.debug&&console.log({count:c,data:a}),c<=100){let p=Date.now(),S=p-s;s=p,e.innerHTML=o+` \u21D2 ${c} events, ${S} ms`}else window.removeEventListener("message",l)}}function tt({elem:e,command:o,args:i,state:n}){if(i.length<1)return T(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 nt({elem:e,command:o,state:i}){if(!("aspect"in i))return T(e,'"SOLO" expects "aspect" state, like from "WALK".');C(e,"aspect",i),e.innerHTML=o;let n=i.aspect.map(l=>({source:l.source||l.id,aspects:l.result})),t=n.reduce((l,u)=>l+u.aspects.length,0);e.innerHTML+=` \u21D2 ${n.length} sources, ${t} aspects`;let s=e.closest(".page").dataset.key,c={type:"batch",sources:n,pageKey:s};(typeof window.soloListener>"u"||window.soloListener==null)&&(console.log("**** Adding solo listener"),window.soloListener=Y,window.addEventListener("message",Y)),await ue(750);let r=window.open("/plugins/solo/dialog/#","solo","popup,height=720,width=1280");r.location.pathname!="/plugins/solo/dialog/"?(console.log("launching new dialog"),r.addEventListener("load",l=>{console.log("launched and loaded"),r.postMessage(c,window.origin)})):(console.log("reusing existing dialog"),r.postMessage(c,window.origin))}function ot({elem:e,args:o,state:i}){let n=[];switch(o[0]){case"state":for(let s in i)n.push(`<details>
|
|
25
28
|
<summary>${s}</summary>
|
|
26
29
|
<pre>${JSON.stringify(i[s],null,2)}</pre>
|
|
27
|
-
</details>`);break;case"images":if(!i.commons)return
|
|
28
|
-
`))}
|
|
29
|
-
`)
|
|
30
|
+
</details>`);break;case"images":if(!i.commons)return T(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 T(e,`POPUP doesn't know "${o[0]}".`)}wiki.dialog(e.innerText,n.join(`
|
|
31
|
+
`))}async function it({elem:e,command:o,args:i,state:n}){if(!["outline","draft"].includes(i[0]))return n.api.trouble(e,"Expects PRINT outline or PRINT draft.");let t=i[0];if(!n.aspect)return n.api.trouble(e,'PRINT expects "aspect", like from WALK clicks.');if(n.api.inspect(e,"aspect",n),!n.neighborhood)return n.api.trouble(e,'PRINT expectes "neighborhood", like from NEIGHBORS.');n.api.inspect(e,"neighborhood",n);let s=n.aspect,c=n.neighborhood;console.log("print",{aspect:s,neighborhood:c});let r=[],l={missing:[],omitted:[],domains:[],forks:[],wishes:[],errors:[]},u={},a=(E,P,f)=>{P in E||(E[P]=[]),E[P].push(f)},p=(E,P)=>{let f=l[E];console.log("explain",E,u[E]);let k=h=>Math.abs(h.split("").reduce((w,x)=>x.charCodeAt(0)+(w<<6)+(w<<16)-w,0)).toString(16),y=Object.keys(f).toSorted((h,w)=>f[w].length-f[h].length);if(y.length){let h=[];for(let w of y){let x=f[w].filter(K).sort().map(d=>`[[${d}]]`).join(`
|
|
32
|
+
`);h.push(`<details><summary>${w} \xD7 ${f[w].length}</summary>
|
|
33
|
+
<pre>${x}</pre></details>`)}S.push({type:"markdown",text:`# ${P}
|
|
34
|
+
${u[E]||""}`,id:k(P)}),y[0].match(/\.\w+\.\w+$/)&&S.push({type:"roster",text:y.join(`
|
|
35
|
+
`)}),S.push({type:"html",text:h.join(`
|
|
36
|
+
`)})}},S=[];r.push("<h1>Story</h1>");let L=s.find(E=>E.source.match(/^WALK.*clicks/));if(!L)return n.api.trouble(e,"PRINT needs aspect from WALK clicks");let g=L.result.map(E=>E.name);await z(g,"story"),r.push("<h1>Garden</h1>");let I=L.result.map(E=>E.graph.nodes.map(P=>P.props)).flat(),K=(E,P,f)=>f.indexOf(E)===P,G=I.map(E=>Z(E.name.replaceAll(`
|
|
37
|
+
`," "))).filter(K).filter(E=>!g.includes(E)).sort();await z(G,"garden"),console.log({tally:l,explain:u}),p("domains","Sourced Sites"),p("missing","Missing Pages"),p("omitted","Omitted Links"),p("forks","Omitted Forks"),p("wishes","Unusual Plugins"),p("errors","Program Errors"),S.length&&(n.items=S),n.api.status(e,o,` \u21D2 ${g.length} story, ${G.length} garden`),n.api.download(r.join(`
|
|
38
|
+
`),`print-${t}.html`,"text/html");async function z(E,P){let f='style="width:640px"',k=y=>y.replaceAll(/\[\[(.*?)\]\]/g,(h,w)=>`<a href="#${Z(w)}">${w}</a>`).replaceAll(/\[.*? (.*?)\]/g,(h,w)=>`<i>${w}</i>`);for(let y of E){let h=c.find(w=>w.slug==y);if(!h){a(l.missing,P,y),u.missing="These pages weren't found in PRINT's neighborhood.";continue}if(a(l.domains,h.domain,h.slug),u.domains="Pages have been retrieved from these sites. Remove sites from the PRINT neighborhood if these should be found elsewhere.",P=="garden"){for(let w in h.links)E.includes(w)||a(l.omitted,y,w);u.omitted="Garden pages with links to pages omitted from the garden. These may show up with a deeper WALK into the garden'"}if(t=="outline")r.push(`<p id="${h.slug}" ${f}"><b title="${h.domain}">${h.title}</b> -- ${k(h.synopsis)}</p>`);else{let w=E.indexOf(y)+1;n.api.status(e,o,` \u21D2 ${w} of ${E.length} from ${P}`);try{console.log(h.domain,h.title);let x=await n.api.jfetch(`//${h.domain}/${h.slug}.json`);r.push(`<section id="${h.slug}"><h3 title="${h.domain}">${h.title}</h3>`);for(let d of x.story)switch(d.type!="paragraph"&&a(l.wishes,d.type,y),u.wishes='Items of type "paragraph" are expected. Types "markdown" and "html" may show without revision. The remainder appear as only a one-line note.',d.type){case"paragraph":case"markdown":r.push(`<p ${f}>${k(d.text)}</p>`);break;case"html":r.push(`<p ${f}>${k(n.api.closeTags(d.text))}</p>`);break;default:r.push(`<p ${f}>Item type "${d.type}" omitted.</p>`)}for(let d of x.journal)d.site&&!c.find(v=>v.domain==d.site)&&a(l.forks,d.site,y),u.forks="Wiki remembers where pages may once have lived but PRINT only looks for pages in the neighborhoods prvided.";r.push("</section>")}catch(x){a(l.errors,x.message,h.slug),u.errors="Any pages that lead to program errors should be explored by developers. Until then they will be ignored."}}}}}var ce={CLICK:{emit:je},HELLO:{emit:Ae},FROM:{emit:Ie},SENSOR:{emit:Ne},REPORT:{emit:He},SOURCE:{emit:Pe},PREVIEW:{emit:De},NEIGHBORS:{emit:Ke},WALK:{emit:We},TICK:{emit:_e},UNTIL:{emit:qe},FORWARD:{emit:Ce},TURN:{emit:Fe},FILE:{emit:Ue},KWIC:{emit:Ge},SHOW:{emit:Be},RANDOM:{emit:Je},SLEEP:{emit:ze},TOGETHER:{emit:Ve},GET:{emit:Ze},DELTA:{emit:Xe},ROSTER:{emit:Qe},LINEUP:{emit:Ye},LISTEN:{emit:et},MESSAGE:{emit:tt},SOLO:{emit:nt},POPUP:{emit:ot},PRINT:{emit:it}};function st(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function te(e,o,i){for(;e.length;){let t=e[0].match(/( *)(.*)/),s=t[1].length,c=t[2];if(s==i)o.push({command:c}),e.shift();else if(s>i){var n=[];o.push(n),te(e,n,s)}else return o}return o}function de(e){let o=Math.floor(Math.random()*1e6),i=(n,t)=>{let s=[];for(let c of n){let r=`${o}.${t.join(".")}`;c.key=r,"command"in c?s.push(`<div></div><span id=${r} class=block >${st(c.command)}</span>`):s.push(`<div id=${r} class=body>${i(c,[...t,0])}</div>`),t[t.length-1]++}return s.join(`
|
|
39
|
+
`)};return i(e,[0])}var V=(e,o,i)=>i.indexOf(e)===o,ue=e=>new Promise(o=>setTimeout(o,e)),Z=e=>e.replace(/\s/g,"-").replace(/[^A-Za-z0-9-]/g,"").toLowerCase();function Tt(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function rt(e,o){$("link[href='/plugins/mech/mech.css']").length||$('<link rel="stylesheet" href="/plugins/mech/mech.css" type="text/css">').appendTo("head");let i=o.text.split(/\n/),n=te(i,[],0),t=de(n),s=e.parents(".page"),c=s.data("key"),l={context:{item:o,itemId:o.id,pageKey:c,page:wiki.lineup.atKey(c).getRawPage(),origin:window.origin,site:s.data("site")||window.location.host,slug:s.attr("id"),title:s.data("data").title},api:le};e.append(`<div style="background-color:#eee;padding:15px;border-top:8px;">${t}</div>`),W(n,l)}function ct(e,o){return e.dblclick(()=>wiki.textEditor(e,o))}typeof window<"u"&&window!==null&&(window.plugins.mech={emit:rt,bind:ct});})();
|
|
30
40
|
//# sourceMappingURL=mech.js.map
|