wiki-plugin-mech 0.1.26 → 0.1.28

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.
Files changed (2) hide show
  1. package/client/mech.js +175 -37
  2. package/package.json +1 -1
package/client/mech.js CHANGED
@@ -2,6 +2,7 @@
2
2
  (function() {
3
3
  "use strict"
4
4
  const uniq = (value, index, self) => self.indexOf(value) === index
5
+ const delay = time => new Promise(res => setTimeout(res,time))
5
6
 
6
7
  function expand(text) {
7
8
  return text
@@ -274,8 +275,23 @@
274
275
  function walk_emit ({elem,command,args,state}) {
275
276
  if(!('neighborhood' in state)) return trouble(elem,`WALK expects state.neighborhood, like from NEIGHBORS.`)
276
277
  inspect(elem,'neighborhood',state)
277
- const [,count,way] = command.match(/\b(\d+)? *(steps|days|weeks|months|hubs)\b/) || []
278
- const steps = walks(count,way,state.neighborhood)
278
+ const [,count,way] = command.match(/\b(\d+)? *(steps|days|weeks|months|hubs|lineup|references)\b/) || []
279
+ if(!way && command != 'WALK') return trouble(elem, `WALK can't understand rest of this block.`)
280
+ const scope = {
281
+ lineup(){
282
+ const items = [...document.querySelectorAll('.page')]
283
+ const index = items.indexOf(elem.closest('.page'))
284
+ return items.slice(0,index)
285
+ },
286
+ references(){
287
+ const div = elem.closest('.page')
288
+ const pageObject = wiki.lineup.atKey(div.dataset.key)
289
+ const story = pageObject.getRawPage().story
290
+ console.log({div,pageObject,story})
291
+ return story.filter(item => item.type == 'reference')
292
+ }
293
+ }
294
+ const steps = walks(count,way,state.neighborhood,scope)
279
295
  const aspects = steps.filter(({graph})=>graph)
280
296
  if(state.debug) console.log({steps})
281
297
  elem.innerHTML = command
@@ -287,7 +303,7 @@
287
303
  state.aspect = state.aspect || []
288
304
  const obj = state.aspect.find(obj => obj.id == elem.id)
289
305
  if(obj) obj.result = aspects
290
- else state.aspect.push({id:elem.id, result:aspects})
306
+ else state.aspect.push({id:elem.id, result:aspects, source:command})
291
307
  item.classList.add('aspect-source')
292
308
  item.aspectData = () => state.aspect.map(obj => obj.result).flat()
293
309
  if(state.debug) console.log({command,state:state.aspect,item:item.aspectData()})
@@ -674,17 +690,29 @@
674
690
  elem.innerHTML = command + ` ⇒ sent`
675
691
  }
676
692
 
677
- function solo_emit({elem,command,state}) {
693
+ async function solo_emit({elem,command,state}) {
678
694
  if(!('aspect' in state)) return trouble(elem,`"SOLO" expects "aspect" state, like from "WALK".`)
679
695
  inspect(elem,'aspect',state)
696
+ elem.innerHTML = command
680
697
  const todo = state.aspect.map(each => ({
681
- source:each.id,
698
+ source:each.source || each.id,
682
699
  aspects:each.result
683
700
  }))
701
+ const aspects = todo.reduce((sum,each) => sum+each.aspects.length, 0)
702
+ elem.innerHTML += ` ⇒ ${todo.length} sources, ${aspects} aspects`
703
+
684
704
  // from Solo plugin, client/solo.js
685
705
  const pageKey = elem.closest('.page').dataset.key
686
706
  const doing = {type:'batch', sources:todo, pageKey}
687
707
  console.log({pageKey,doing})
708
+
709
+ if (typeof window.soloListener == "undefined" || window.soloListener == null) {
710
+ console.log('**** Adding solo listener')
711
+ window.soloListener = soloListener
712
+ window.addEventListener("message", soloListener)
713
+ }
714
+
715
+ await delay(750)
688
716
  const popup = window.open('/plugins/solo/dialog/#','solo','popup,height=720,width=1280')
689
717
  if (popup.location.pathname != '/plugins/solo/dialog/'){
690
718
  console.log('launching new dialog')
@@ -811,19 +839,66 @@
811
839
  }
812
840
 
813
841
  // inspired by aspects-of-recent-changes/roster-graphs.html
814
- function walks(count,way='steps',neighborhood) {
815
- const find = slug => neighborhood.find(info => info.slug == slug)
842
+ function walks(count,way='steps',neighborhood,scope={}) {
843
+ const find = (slug,site) => neighborhood.find(info => info.slug == slug && (!site || info.domain == site))
816
844
  const prob = n => Math.floor(n * Math.abs(Math.random()-Math.random()))
817
845
  const rand = a => a[prob(a.length)]
846
+ const good = info => info.links && Object.keys(info.links).length < 10
847
+ const back = slug => neighborhood.filter(info => good(info) && slug in info.links)
848
+ const newr = infos => infos.toSorted((a,b)=>b.date-a.date).slice(0,3)
818
849
  const domains = neighborhood
819
850
  .map(info => info.domain)
820
851
  .filter(uniq)
852
+
853
+ function blanket(info) {
854
+
855
+ // hub[0] => slug
856
+ // find(slug) => info
857
+ // node(info) => nid
858
+ // back(slug) => infos
859
+ // newr(infos) => infos
860
+
861
+ const graph = new Graph()
862
+ const node = info => {
863
+ return graph.addUniqNode('',{
864
+ name:info.title.replaceAll(/ /g,"\n"),
865
+ title:info.title,
866
+ site:info.domain
867
+ })
868
+ }
869
+
870
+ // hub
871
+ const nid = node(info)
872
+
873
+ // parents of hub
874
+ for(const parent of newr(back(info.slug))) {
875
+ graph.addRel('',node(parent),nid)
876
+ }
877
+
878
+ // children of hub
879
+ for(const link in (info.links||{})) {
880
+ const child = find(link)
881
+ if(child) {
882
+ const cid = node(child)
883
+ graph.addRel('',nid,cid)
884
+
885
+ // parents of children of hub
886
+ for(const parent of newr(back(child.slug))) {
887
+ graph.addRel('',node(parent),cid)
888
+ }
889
+ }
890
+ }
891
+ return graph
892
+ }
893
+
821
894
  switch(way) {
822
895
  case 'steps': return steps(count)
823
896
  case 'days': return periods(way,1,count)
824
897
  case 'weeks': return periods(way,7,count)
825
898
  case 'months': return periods(way,30,count)
826
899
  case 'hubs': return hubs(count)
900
+ case 'references': return references()
901
+ case 'lineup': return lineup()
827
902
  }
828
903
 
829
904
  function steps(count=5) {
@@ -869,27 +944,32 @@
869
944
  for(const stop of dates) {
870
945
  const start = stop-interval
871
946
  const name = `${way.replace(/s$/,'')} ${new Date(start).toLocaleDateString()}`
872
- const graph = new Graph()
873
- const node = info => {
874
- return graph.addUniqNode('',{
875
- name:info.title.replaceAll(/ /g,"\n"),
876
- title:info.title,
877
- site:info.domain
878
- })
879
- }
880
947
  const here = neighborhood
881
948
  .filter(info => info.date < stop && info.date >= start)
882
949
  .filter(info => !(info.links && Object.keys(info.links).length > 5))
883
950
  if(here.length) {
884
- for (const info of here) {
885
- const nid = node(info)
886
- for (const link in (info.links||{})) {
887
- const linked = find(link)
888
- if(linked)
889
- graph.addRel('',nid,node(linked))
951
+ const domains = here.reduce((set,info) => {set.add(info.domain); return set}, new Set())
952
+ for (const domain of domains) {
953
+ const graph = new Graph()
954
+ const node = info => {
955
+ return graph.addUniqNode('',{
956
+ name:info.title.replaceAll(/ /g,"\n"),
957
+ title:info.title,
958
+ site:info.domain,
959
+ date:info.date
960
+ })
961
+ }
962
+ const author = domain.split(/\.|\:/)[0]
963
+ for (const info of here.filter(info => info.domain == domain)) {
964
+ const nid = node(info)
965
+ for (const link in (info.links||{})) {
966
+ const linked = find(link)
967
+ if(linked)
968
+ graph.addRel('',nid,node(linked))
969
+ }
890
970
  }
971
+ aspects.push({name:`${name} ${author}`,graph})
891
972
  }
892
- aspects.push({name,graph})
893
973
  }
894
974
  }
895
975
  return aspects
@@ -917,26 +997,40 @@
917
997
 
918
998
  for(const hub of hubs) {
919
999
  const name = `hub ${hub[1]} ${hub[0]}`
920
- const graph = new Graph()
921
- const node = info => {
922
- return graph.addUniqNode('',{
923
- name:info.title.replaceAll(/ /g,"\n"),
924
- title:info.title,
925
- site:info.domain
926
- })
927
- }
928
- const info = find(hub[0])
929
- const nid = node(info)
930
- for(const link in (info.links||{})) {
931
- const linked = find(link)
932
- if(linked)
933
- graph.addRel('',nid,node(linked))
934
- }
1000
+ const graph = blanket(find(hub[0]))
935
1001
  aspects.push({name,graph})
936
1002
  }
937
1003
  return aspects
938
1004
  }
939
1005
 
1006
+ function lineup() {
1007
+ const aspects = []
1008
+ const lineup = scope.lineup()
1009
+ console.log({lineup})
1010
+ for(const div of lineup){
1011
+ const pageObject = wiki.lineup.atKey(div.dataset.key)
1012
+ const slug = pageObject.getSlug()
1013
+ const site = pageObject.getRemoteSite(location.host)
1014
+ const info = find(slug,site)
1015
+ console.log({div,pageObject,site,slug,info})
1016
+ aspects.push({name:pageObject.getTitle(), graph:blanket(info)})
1017
+ }
1018
+ return aspects
1019
+ }
1020
+
1021
+ function references() {
1022
+ const aspects = []
1023
+ const items = scope.references()
1024
+ console.log({items})
1025
+ for(const item of items){
1026
+ const {title,site,slug} = item
1027
+ const info = find(slug,site)
1028
+ console.log({site,slug,info})
1029
+ aspects.push({name:title, graph:blanket(info)})
1030
+ }
1031
+ console.log({aspects})
1032
+ return aspects
1033
+ }
940
1034
  }
941
1035
 
942
1036
 
@@ -1114,6 +1208,50 @@
1114
1208
  page.journal.push(action);
1115
1209
  }
1116
1210
 
1211
+
1212
+ // adapted from Solo client
1213
+
1214
+ function soloListener(event) {
1215
+
1216
+ if (!event.data) return
1217
+ const { data } = event
1218
+ if (data?.action == "publishSourceData" && data?.name == "aspect") {
1219
+ if (wiki.debug) console.log('soloListener - source update', {event,data})
1220
+ return
1221
+ }
1222
+
1223
+ // only continue if event is from a solo popup.
1224
+ // events from a popup window will have an opener
1225
+ // ensure that the popup window is one of ours
1226
+
1227
+ if (!event.source.opener || event.source.location.pathname !== '/plugins/solo/dialog/') {
1228
+ if (wiki.debug) {console.log('soloListener - not for us', {event})}
1229
+ return
1230
+ }
1231
+ if (wiki.debug) {console.log('soloListener - ours', {event})}
1232
+
1233
+ const { action, keepLineup=false, pageKey=null, title=null, context=null, page=null} = data;
1234
+
1235
+ let $page = null
1236
+ if (pageKey != null) {
1237
+ $page = keepLineup ? null : $('.page').filter((i, el) => $(el).data('key') == pageKey)
1238
+ }
1239
+
1240
+ switch (action) {
1241
+ case 'doInternalLink':
1242
+ wiki.pageHandler.context = context
1243
+ wiki.doInternalLink(title, $page)
1244
+ break
1245
+ case 'showResult':
1246
+ const options = keepLineup ? {} : {$page}
1247
+ wiki.showResult(wiki.newPage(page), options)
1248
+ break
1249
+ default:
1250
+ console.error({ where:'soloListener', message: "unknown action", data })
1251
+ }
1252
+ }
1253
+
1254
+
1117
1255
  function create(revIndex, data) {
1118
1256
  revIndex = +revIndex;
1119
1257
  const revJournal = data.journal.slice(0, revIndex + 1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wiki-plugin-mech",
3
- "version": "0.1.26",
3
+ "version": "0.1.28",
4
4
  "description": "Federated Wiki - Mechanism Scripting Plugin",
5
5
  "keywords": [
6
6
  "mech",