wiki-plugin-mech 0.1.12 → 0.1.14
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.js +112 -32
- package/package.json +1 -1
package/client/mech.js
CHANGED
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
function run (nest,state={},mock) {
|
|
86
|
+
async function run (nest,state={},mock) {
|
|
87
87
|
const scope = nest.slice()
|
|
88
88
|
while (scope.length) {
|
|
89
89
|
const code = scope.shift()
|
|
@@ -96,14 +96,15 @@
|
|
|
96
96
|
const stuff = {command,op,args,body,elem,state}
|
|
97
97
|
if(state.debug) console.log(stuff)
|
|
98
98
|
if (blocks[op])
|
|
99
|
-
blocks[op].emit.apply(null,[stuff])
|
|
99
|
+
await blocks[op].emit.apply(null,[stuff])
|
|
100
100
|
else
|
|
101
101
|
if (op.match(/^[A-Z]+$/))
|
|
102
102
|
trouble(elem,`${op} doesn't name a block we know.`)
|
|
103
103
|
else if (code.command.match(/\S/))
|
|
104
104
|
trouble(elem, `Expected line to begin with all-caps keyword.`)
|
|
105
105
|
} else if(typeof code == 'array') {
|
|
106
|
-
|
|
106
|
+
console.warn(`this can't happen.`)
|
|
107
|
+
run(code,state) // when does this even happen?
|
|
107
108
|
}
|
|
108
109
|
}
|
|
109
110
|
}
|
|
@@ -113,7 +114,7 @@
|
|
|
113
114
|
|
|
114
115
|
function click_emit ({elem,body,state}) {
|
|
115
116
|
if(elem.innerHTML.match(/button/)) return
|
|
116
|
-
if (!body?.length) return trouble(elem
|
|
117
|
+
if (!body?.length) return trouble(elem,`CLICK expects indented blocks to follow.`)
|
|
117
118
|
elem.innerHTML += '<button style="border-width:0;">▶</button>'
|
|
118
119
|
elem.querySelector('button').addEventListener('click',event => {
|
|
119
120
|
state.debug = event.shiftKey
|
|
@@ -121,15 +122,18 @@
|
|
|
121
122
|
})
|
|
122
123
|
}
|
|
123
124
|
|
|
124
|
-
function hello_emit ({elem,args}) {
|
|
125
|
-
const
|
|
126
|
-
|
|
125
|
+
function hello_emit ({elem,args,state}) {
|
|
126
|
+
const world = args[0] == 'world' ? ' 🌎' : ' 😀'
|
|
127
|
+
for (const key of Object.keys(state))
|
|
128
|
+
inspect(elem,key,state)
|
|
129
|
+
elem.innerHTML += world
|
|
127
130
|
}
|
|
128
131
|
|
|
129
132
|
function from_emit ({elem,args,body,state}) {
|
|
130
133
|
const line = elem.innerHTML
|
|
134
|
+
const url = args[0]
|
|
131
135
|
elem.innerHTML = line + ' ⏳'
|
|
132
|
-
fetch(`//${
|
|
136
|
+
fetch(`//${url}.json`)
|
|
133
137
|
.then(res => res.json())
|
|
134
138
|
.then(page => {
|
|
135
139
|
state.page = page
|
|
@@ -144,13 +148,13 @@
|
|
|
144
148
|
inspect(elem,'page',state)
|
|
145
149
|
const datalog = state.page.story.find(item => item.type == 'datalog')
|
|
146
150
|
if(!datalog) return trouble(elem, `Expect Datalog plugin in the page.`)
|
|
147
|
-
const
|
|
148
|
-
if(!
|
|
151
|
+
const device = args[0]
|
|
152
|
+
if(!device) return trouble(elem, `SENSOR needs a sensor name.`)
|
|
149
153
|
const sensor = datalog.text.split(/\n/)
|
|
150
154
|
.map(line => line.split(/ +/))
|
|
151
155
|
.filter(fields => fields[0] == 'SENSOR')
|
|
152
|
-
.find(fields => fields[1] ==
|
|
153
|
-
if(!sensor) return trouble(elem, `Expect to find "${
|
|
156
|
+
.find(fields => fields[1] == device)
|
|
157
|
+
if(!sensor) return trouble(elem, `Expect to find "${device}" in Datalog.`)
|
|
154
158
|
const url = sensor[2]
|
|
155
159
|
|
|
156
160
|
const f = c => 9/5*(c/16)+32
|
|
@@ -190,6 +194,10 @@
|
|
|
190
194
|
.join(", ")
|
|
191
195
|
if (state.debug) console.log({topic,sources})
|
|
192
196
|
elem.innerHTML = command + ' ⇒ ' + counts
|
|
197
|
+
// state.assets = ?
|
|
198
|
+
// state.aspect = ?
|
|
199
|
+
// state.region = ?
|
|
200
|
+
// state.marker = ?
|
|
193
201
|
state[topic] = sources.map(({div,result}) => ({id:div.dataset.id, result}))
|
|
194
202
|
if (body) run(body,state)
|
|
195
203
|
}
|
|
@@ -197,8 +205,9 @@
|
|
|
197
205
|
function preview_emit ({elem,command,args,state}) {
|
|
198
206
|
const round = digits => (+digits).toFixed(7)
|
|
199
207
|
const story = []
|
|
200
|
-
|
|
201
|
-
|
|
208
|
+
const types = args
|
|
209
|
+
for (const type of types) {
|
|
210
|
+
switch (type) {
|
|
202
211
|
case 'map':
|
|
203
212
|
if(!('marker' in state)) return trouble(elem,`"map" preview expects "marker" state, like from "SOURCE marker".`)
|
|
204
213
|
inspect(elem,'marker',state)
|
|
@@ -232,7 +241,7 @@
|
|
|
232
241
|
story.push({type:'paragraph',text})}
|
|
233
242
|
break
|
|
234
243
|
default:
|
|
235
|
-
return trouble(elem,`"${
|
|
244
|
+
return trouble(elem,`"${type}" doesn't name an item we can preview`)
|
|
236
245
|
}
|
|
237
246
|
}
|
|
238
247
|
const title = "Mech Preview" + (state.tick ? ` ${state.tick}` : '')
|
|
@@ -262,7 +271,7 @@
|
|
|
262
271
|
elem.innerHTML = command
|
|
263
272
|
const nodes = aspects.map(({graph}) => graph.nodes).flat()
|
|
264
273
|
elem.innerHTML += ` ⇒ ${aspects.length} aspects, ${nodes.length} nodes`
|
|
265
|
-
if(steps.find(({graph}) => !graph)) trouble(elem
|
|
274
|
+
if(steps.find(({graph}) => !graph)) trouble(elem,`WALK skipped sites with no links in sitemaps`)
|
|
266
275
|
const item = elem.closest('.item')
|
|
267
276
|
item.classList.add('aspect-source')
|
|
268
277
|
item.aspectData = () => aspects
|
|
@@ -271,9 +280,9 @@
|
|
|
271
280
|
|
|
272
281
|
function tick_emit ({elem,args,body,state}) {
|
|
273
282
|
if(elem.innerHTML.match(/button/)) return
|
|
274
|
-
if (!body?.length) return trouble(elem
|
|
283
|
+
if (!body?.length) return trouble(elem,`TICK expects indented blocks to follow.`)
|
|
275
284
|
const count = args[0] || '1'
|
|
276
|
-
if (!count.match(/^[1-9][0-9]?$/)) return trouble(elem
|
|
285
|
+
if (!count.match(/^[1-9][0-9]?$/)) return trouble(elem,`TICK expects a count from 1 to 99`)
|
|
277
286
|
let clock = null
|
|
278
287
|
elem.innerHTML += '<button style="border-width:0;">▶</button>'
|
|
279
288
|
elem.querySelector('button').addEventListener('click',event => {
|
|
@@ -317,37 +326,77 @@
|
|
|
317
326
|
function forward_emit ({elem,command,args,state}) {
|
|
318
327
|
if(args.length < 1) return trouble(elem,`FORWARD expects an argument, the number of steps to move a "turtle".`)
|
|
319
328
|
if(!('turtle' in state)) state.turtle = new Turtle(elem)
|
|
320
|
-
const
|
|
329
|
+
const steps = args[0]
|
|
330
|
+
const position = state.turtle.forward(+steps)
|
|
321
331
|
elem.innerHTML = command + ` ⇒ ${position.map(n => (n-200).toFixed(1)).join(', ')}`
|
|
322
332
|
}
|
|
323
333
|
|
|
324
334
|
function turn_emit ({elem,command,args,state}) {
|
|
325
335
|
if(args.length < 1) return trouble(elem,`TURN expects an argument, the number of degrees to turn a "turtle".`)
|
|
326
336
|
if(!('turtle' in state)) state.turtle = new Turtle(elem)
|
|
327
|
-
const
|
|
337
|
+
const degrees = args[0]
|
|
338
|
+
const direction = state.turtle.turn(+degrees)
|
|
328
339
|
elem.innerHTML = command + ` ⇒ ${direction}°`
|
|
329
340
|
}
|
|
330
341
|
|
|
331
342
|
function file_emit ({elem,command,args,body,state}) {
|
|
332
343
|
if(!('assets' in state)) return trouble(elem,`FILE expects state.assets, like from SOURCE assets.`)
|
|
333
344
|
inspect(elem,'assets',state)
|
|
345
|
+
|
|
346
|
+
// [ { "id": "b2d5831168b4706b", "result":
|
|
347
|
+
// { "pages/testing-file-mech":
|
|
348
|
+
// { "//ward.dojo.fed.wiki/assets":
|
|
349
|
+
// [ "KWIC-list+axe-files.txt", "KWIC-list-axe-files.tsv" ] } } } ]
|
|
350
|
+
|
|
351
|
+
const origin = '//'+window.location.host
|
|
352
|
+
const assets = state.assets.map(({id,result}) =>
|
|
353
|
+
Object.entries(result).map(([dir,paths]) =>
|
|
354
|
+
Object.entries(paths).map(([path,files]) =>
|
|
355
|
+
files.map(file => {
|
|
356
|
+
const assets = path.startsWith("//") ? path : `${origin}${path}`
|
|
357
|
+
const host = assets.replace(/\/assets$/,'')
|
|
358
|
+
const url = `${assets}/${dir}/${file}`
|
|
359
|
+
return {id,dir,path,host,file,url}
|
|
360
|
+
})))).flat(3)
|
|
361
|
+
if(state.debug) console.log({assets})
|
|
362
|
+
|
|
334
363
|
if(args.length < 1) return trouble(elem,`FILE expects an argument, the dot suffix for desired files.`)
|
|
335
364
|
if (!body?.length) return trouble(elem,'FILE expects indented blocks to follow.')
|
|
336
365
|
const suffix = args[0]
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
366
|
+
const choices = assets.filter(asset => asset.file.endsWith(suffix))
|
|
367
|
+
const flag = choice => `<img width=12 src=${choices[choice].host+'/favicon.png'}>`
|
|
368
|
+
if(!choices) return trouble(elem,`FILE expects to find an asset with "${suffix}" suffix.`)
|
|
369
|
+
elem.innerHTML = command +
|
|
370
|
+
`<br><div class=choices style="border:1px solid black; background-color:#f8f8f8; padding:8px;" >${choices
|
|
371
|
+
.map((choice,i) =>
|
|
372
|
+
`<span data-choice=${i} style="cursor:pointer;">
|
|
373
|
+
${flag(i)}
|
|
374
|
+
${choice.file} ▶
|
|
375
|
+
</span>`)
|
|
376
|
+
.join("<br>\n")
|
|
377
|
+
}</div>`
|
|
378
|
+
elem.querySelector('.choices').addEventListener('click',event => {
|
|
379
|
+
if (!('choice' in event.target.dataset)) return
|
|
380
|
+
const url = choices[event.target.dataset.choice].url
|
|
381
|
+
// console.log(event.target)
|
|
382
|
+
// console.log(event.target.dataset.file)
|
|
383
|
+
// const url = 'http://ward.dojo.fed.wiki/assets/pages/testing-file-mech/KWIC-list-axe-files.tsv'
|
|
384
|
+
fetch(url)
|
|
385
|
+
.then(res => res.text())
|
|
386
|
+
.then(text => {
|
|
387
|
+
elem.innerHTML = command + ` ⇒ ${text.length} bytes`
|
|
388
|
+
state.tsv = text
|
|
389
|
+
console.log({text})
|
|
390
|
+
run(body,state)
|
|
391
|
+
})
|
|
392
|
+
})
|
|
345
393
|
}
|
|
346
394
|
|
|
347
395
|
function kwic_emit ({elem,command,args,body,state}) {
|
|
348
396
|
const template = body && body[0]?.command
|
|
349
397
|
if(template && !template.match(/\$[KW]/)) return trouble(elem,`KWIK expects $K or $W in link prototype.`)
|
|
350
398
|
if(!('tsv' in state)) return trouble(elem,`KWIC expects a .tsv file, like from ASSETS .tsv.`)
|
|
399
|
+
inspect(elem,'tsv',state)
|
|
351
400
|
const prefix = args[0] || 1
|
|
352
401
|
const lines = state.tsv.trim().split(/\n/)
|
|
353
402
|
|
|
@@ -397,9 +446,10 @@
|
|
|
397
446
|
return trouble(elem,`SHOW expects a slug or site/slug to open in the lineup.`)
|
|
398
447
|
}
|
|
399
448
|
} else {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
449
|
+
const info = args[0]
|
|
450
|
+
[site,slug] = info.includes('/')
|
|
451
|
+
? info.split(/\//)
|
|
452
|
+
: [null,info]
|
|
403
453
|
}
|
|
404
454
|
const lineup = [...document.querySelectorAll('.page')].map(e => e.id)
|
|
405
455
|
if(lineup.includes(slug)) return trouble(elem,`SHOW expects a page not already in the lineup.`)
|
|
@@ -417,6 +467,34 @@
|
|
|
417
467
|
state.info = infos[one]
|
|
418
468
|
}
|
|
419
469
|
|
|
470
|
+
function sleep_emit({elem,command,args,body,state}) {
|
|
471
|
+
let count = args[0] || '1'
|
|
472
|
+
if (!count.match(/^[1-9][0-9]?$/)) return trouble(elem,`SLEEP expects seconds from 1 to 99`)
|
|
473
|
+
return new Promise(resolve => {
|
|
474
|
+
if(body)
|
|
475
|
+
run(body,state)
|
|
476
|
+
.then(result => if(state.debug) console.log(command,'children', result))
|
|
477
|
+
elem.innerHTML = command + ` ⇒ ${count} remain`
|
|
478
|
+
let clock = setInterval(()=> {
|
|
479
|
+
if(--count > 0)
|
|
480
|
+
elem.innerHTML = command + ` ⇒ ${count} remain`
|
|
481
|
+
else {
|
|
482
|
+
clearInterval(clock)
|
|
483
|
+
elem.innerHTML = command + ` ⇒ done`
|
|
484
|
+
if(state.debug) console.log(command, 'done')
|
|
485
|
+
resolve()
|
|
486
|
+
}
|
|
487
|
+
}, 1000)
|
|
488
|
+
})
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
function together_emit({elem,command,args,body,state}) {
|
|
492
|
+
if (!body) return trouble(elem,`TOGETHER expects indented commands to run together.`)
|
|
493
|
+
const children = body
|
|
494
|
+
.map(child => run([child],state))
|
|
495
|
+
return Promise.all(children)
|
|
496
|
+
}
|
|
497
|
+
|
|
420
498
|
|
|
421
499
|
// C A T A L O G
|
|
422
500
|
|
|
@@ -437,7 +515,9 @@
|
|
|
437
515
|
FILE: {emit:file_emit},
|
|
438
516
|
KWIC: {emit:kwic_emit},
|
|
439
517
|
SHOW: {emit:show_emit},
|
|
440
|
-
RANDOM: {emit:random_emit}
|
|
518
|
+
RANDOM: {emit:random_emit},
|
|
519
|
+
SLEEP: {emit:sleep_emit},
|
|
520
|
+
TOGETHER:{emit:together_emit}
|
|
441
521
|
}
|
|
442
522
|
|
|
443
523
|
|