wiki-plugin-mech 0.1.4 → 0.1.5

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 +108 -2
  2. package/package.json +1 -1
package/client/mech.js CHANGED
@@ -1,6 +1,8 @@
1
1
 
2
2
  (function() {
3
3
 
4
+ const uniq = (value, index, self) => self.indexOf(value) === index
5
+
4
6
  function expand(text) {
5
7
  return text
6
8
  .replace(/&/g, '&')
@@ -115,12 +117,73 @@
115
117
  elem.innerHTML = command + `<br><font face=Arial size=32>${value}</font>`
116
118
  }
117
119
 
120
+ function source_emit ({elem,command,args,body,state}) {
121
+ if (!(args && args.length)) return trouble(elem,`Expected Source topic, like "markers" for Map markers.`)
122
+ const topic = args[0]
123
+ const sources = requestSourceData(state.$item, topic)
124
+ if(!sources.length) return trouble(elem,`Expected source for "${topic}" in the lineup.`)
125
+ const count = type => {
126
+ const count = sources
127
+ .filter(source => [...source.div.classList].includes(type))
128
+ .length
129
+ return count ? `${count} ${type}` : null}
130
+ const counts = [count('map'),count('image'),count('frame')]
131
+ .filter(count => count)
132
+ .join(", ")
133
+ if (state.debug) console.log({topic,sources})
134
+ elem.innerHTML = command + ' ⇒ ' + counts
135
+ state[topic] = sources
136
+ if (body) run(body,state)
137
+ }
138
+
139
+ function preview_emit ({elem,command,args,state}) {
140
+ const round = digits => (+digits).toFixed(7)
141
+ const story = []
142
+ for (const arg of args) {
143
+ switch (arg) {
144
+ case 'map':
145
+ if(!('marker' in state)) return trouble(elem,`"map" preview expects "marker" state, like from "SOURCE marker".`)
146
+ const text = state.marker
147
+ .map(marker => [marker.result])
148
+ .flat(2)
149
+ .map(latlon => `${round(latlon.lat)}, ${round(latlon.lon)} ${latlon.label||''}`)
150
+ .filter(uniq)
151
+ .join("\n")
152
+ story.push({type:'map',text})
153
+ break
154
+ case 'graph':
155
+ if(!('aspect' in state)) return trouble(elem,`"graph" preview expects "aspect" state, like from "SOURCE aspect".`)
156
+ for (const {div,result} of state.aspect) {
157
+ for (const {name,graph} of result) {
158
+ if(state.debug) console.log({div,result,name,graph})
159
+ story.push({type:'paragraph',text:name})
160
+ story.push({type:'graphviz',text:dotify(graph)})
161
+ }
162
+ story.push({type:'pagefold',text:'.'})
163
+ }
164
+ break
165
+ case 'synopsis':
166
+ {const text = `This page has been generated by the Mech plugin. We want to tell you where. That's coming soon.`
167
+ story.push({type:'paragraph',text})}
168
+ break
169
+ default:
170
+ return trouble(elem,`"${arg}" doesn't name an item we can preview`)
171
+ }
172
+ }
173
+ const title = "Mech Preview"
174
+ const page = {title,story}
175
+ const options = {}
176
+ wiki.showResult(wiki.newPage(page), options)
177
+ }
178
+
118
179
  const blocks = {
119
180
  CLICK: {emit:click_emit, bind:null},
120
181
  HELLO: {emit:hello_emit, bind:null},
121
182
  FROM: {emit:from_emit, bind:null},
122
183
  SENSOR: {emit:sensor_emit, bind:null},
123
- REPORT: {emit:report_emit, bind:null}
184
+ REPORT: {emit:report_emit, bind:null},
185
+ SOURCE: {emit:source_emit, bind:null},
186
+ PREVIEW: {emit:preview_emit, bind:null}
124
187
  }
125
188
 
126
189
  function run (nest,state={}) {
@@ -152,8 +215,9 @@
152
215
  const lines = item.text.split(/\n/)
153
216
  const nest = tree(lines,[],0)
154
217
  const html = format(nest)
218
+ const state = {$item}
155
219
  $item.append(`<div style="background-color:#eee;padding:15px;border-top:8px;">${html}</div>`)
156
- run(nest)
220
+ run(nest,state)
157
221
  }
158
222
 
159
223
  function bind($item, item) {
@@ -170,4 +234,46 @@
170
234
  module.exports = {expand}
171
235
  }
172
236
 
237
+
238
+ // library functions
239
+
240
+ // adapted from wiki-plugin-frame/client/frame.js
241
+ function requestSourceData($item, topic) {
242
+ let sources = []
243
+ for (let div of document.querySelectorAll(`.item`)) {
244
+ if (div.classList.contains(`${topic}-source`)) {
245
+ sources.unshift(div)
246
+ }
247
+ if (div === $item.get(0)) {
248
+ break
249
+ }
250
+ }
251
+
252
+ return sources.map(div => {
253
+ let getData = div[`${topic}Data`]
254
+ let result = getData ? getData() : null
255
+ return {div,result}
256
+ })
257
+ }
258
+
259
+ // adapted from super-collaborator/dotify.js
260
+ function dotify(graph) {
261
+ const tip = props => Object.entries(props).filter(e => e[1]).map(e => `${e[0]}: ${e[1]}`).join("\\n")
262
+ const nodes = graph.nodes.map((node,id) => {
263
+ const label = `${node.type}\\n${node.props.name}`
264
+ return `${id} [label="${label}" ${(node.props.url||node.props.tick)?`URL="${node.props.url||'#'}" target="_blank"`:''} tooltip="${tip(node.props)}"]`
265
+ })
266
+ const edges = graph.rels.map(rel => {
267
+ return `${rel.from}->${rel.to} [label="${rel.type}" labeltooltip="${tip(rel.props)}"]`
268
+ })
269
+ return [
270
+ 'digraph {',
271
+ 'rankdir=LR',
272
+ 'node [shape=box style=filled fillcolor=palegreen]',
273
+ ...nodes,
274
+ ...edges,
275
+ '}'].join("\n")
276
+ }
277
+
278
+
173
279
  }).call(this)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wiki-plugin-mech",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Federated Wiki - Mechanism Scripting Plugin",
5
5
  "keywords": [
6
6
  "mech",