Plectica - Extract Structure

Extracting the structure from a Plectica JSON export.

samples

Ferndale Structure => Young Adult Learning System => json

.

http://observable.wiki.dbbs.co/assets/pages/snippet-template/esm.html

We will create an outline of the nodes from the Plectica export, to show the structure.

Here we create a tree by walking the nodes. Starting with those nodes without a parent, `parentId ⩶ null`. We use `.filter()` to create a shallow copy of `nodes` with the nodes that have the current node as their parent. For each of the children found we create a list entry, and look to see if it has any children. If currently processing the first, or last, child we create, or close, and indentation in the list.

const createOutline = dataset => { const outline = [] let start = null const nodes = dataset.map_data.nodes const walk = id => { nodes .filter(item => item['parentId'] === id) .sort((a,b) => a.orderIndex - b.orderIndex) .forEach((item, i, a) => { if (i === 0) { outline.push('<ul>') } outline.push(`<li>${item.title} (${item.orderIndex})`) walk(item.id) outline.push(`</li>`) if (i === a.length - 1) { outline.push('</ul>') } }) } walk(start) return outline }

The code below this point is the boiler plate that runs our code under test

We load in some helper modules

import * as frame from "http://code.fed.wiki/assets/v1/frame.js" import * as index from "http://code.fed.wiki/assets/v1/index.js"

Extract the samples

const context = await frame.context() const folds = index.folds(context.page.story) const samples = folds.samples.map(item => item.text)

and create a button for each.

const buttons = samples .map(sample => { const [what,how,link] = sample.split(/ => /) return ` <p><button data-text="${sample}"> ${what}</button> ${how}</p>`}) .join("\n")+`<div id=diagram></div>`

Bind a listener to each button,

export async function bind(el) { el.innerHTML = buttons el.addEventListener('click',async event => { const button = event.target const title = `Exploring ${button.innerText}` let text = button.dataset.text const story = await createStory(text) frame.open({title,story},event.shiftKey) }) }

that will craft a ghost page with the results of our exploration.

async function createStory(sample) { const [what, how, link] = sample.split(' => ') const [_,url,word] = link.split(/[\[ \]]/) const data = await fetch(url) .then(res => res.json()) const output = createOutline(data) const formatted = output.join('') return [ {type: 'paragraph', text: `${how} ${link}`}, {type: 'html', text: `${formatted}`} ] }