Public
Edited
Apr 3, 2020
Importers
Insert cell
Insert cell
Insert cell
diag(100) // not a schema
Insert cell
diag({}) // unknown type
Insert cell
diag({type: 'number'})
Insert cell
diag({
type: 'string',
title: 'Name'
})
Insert cell
diag({type: 'object'}) // no children
Insert cell
diag({type: 'array'})
Insert cell
diag({
type: 'array',
items: {}
})
Insert cell
diag({
type: 'object',
properties: {
a: {
type: 'object',
properties: {
p1: {type: 'array'},
p2: {type: 'integer'},
p3: 100
}
},
c: 100,
}
})
Insert cell
field = diag({
type: 'object',
title: 'field',
required: ['name', 'bitOffset', 'bitWidth'],
properties: {
name: {$ref: 'vlnv/name'},
description: {type: 'string'},
bitOffset: {},
resetValue: {type: 'integer'}, // base % regWidth in bits
bitWidth: {type: 'integer'}, // in bits
volatile: {type: 'boolean'},
// access,
// enumeratedValues,
// modifiedWriteValue,
// readAction,
testable: { type: 'boolean' }, // default true
reserved: { type: 'boolean' } // ipxactish
}
})
Insert cell
diag({
type: 'object',
title: 'register',
required: ['name', 'addressOffset', 'size'],
properties: {
name: {$ref: 'vlnv/name'},
addressOffset: {oneOf: [{$ref: 'expression'}, {$ref: 'uint'}]}, // in memoryMaps[?].addressUnitBits
size: {oneOf: [{$ref: 'expression'}, {$ref: 'uint'}]}, // regWidth in bits
access: {$ref: 'access'},
displayName: { type: 'string' },
description: { type: 'string' },
fields: {
type: 'array',
items: {$ref: 'field'}
},
resetValue: {type: 'integer'} // spiritual
}
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
render = cfg => {

const grid = cfg.grid;

const perEnum = node => {
let w = 8 * grid;
let h = grid;
return ['g',
{w: w, h: h},
['rect', {class: 'ref', width: w, height: h}],
['text', {class: 'refText', x: 2, y: grid - 2}, 'enum']
];
};

const perRef = node => {
let w = 8 * grid;
let h = grid;
return ['g',
{w: w, h: h},
['rect', {class: 'ref', width: w, height: h}],
['a', {'xlink:href': 'google.com'},
['text', {class: 'refText', x: 2, y: grid - 2}, ' → ' + node.$ref]
]
];
};

const perLeaf = node => {
let w = 8 * grid;
let h = grid;

let title = [];
if (node.title) {
title = [['text', {x: 2, y: 2 * grid - 2}, node.title]];
h += grid;
}
return ['g',
{w: w, h: h},
['rect', {class: 'leaf', width: w, height: h}],
['text', {x: 2, y: grid - 2}].concat(tspan.parse('T: <i>' + node.type + '</i>'))
].concat(title);
};
const perOneOf = node => {
let w = 0;
let h = 0;

const children = node.oneOf.map(e => {
const child = rec(e);
const res = ['g', t(grid, h)].concat([child]);
w = Math.max(w, child[1].w);
h += child[1].h;
return res;
});

return ['g',
{w: w, h: h},
['rect', {class: 'ref', width: w + grid, height: h}],
oneOfSymbol(grid, h)
].concat(children);
};

const perObject = node => {
let w = 2 * grid;
let h = grid;

let required = (node.required || []).reduce((res, e) => {
res[e] = true;
return res;
}, {})

const properties = (typeof node.properties === 'object') ? node.properties : {};
const patternProperties = (typeof node.patternProperties === 'object') ? node.patternProperties : {};
const allProperties = Object.assign({}, properties, patternProperties);

const keys = Object.keys(properties);
const patternKeys = Object.keys(patternProperties);
const allKeys = Object.keys(allProperties);

if (allKeys.length > 0) {
w = 0;
h = 0;
}
const keyLength = allKeys.reduce((res, key) =>
Math.max(res, 0.5 * key.length * grid), grid);

const children = allKeys.map(key => {
const child = rec(allProperties[key]);
const keyLabel = tspan.parse(required[key] ? '<b>' + key + '</b>' : key);
const res = ['g',
t(keyLength + 2 * grid, h),
['text', {x: -2, y: grid-2, class: 'key'}].concat(keyLabel)
]
.concat([child]);
w = Math.max(w, child[1].w);
h += child[1].h;
return res;
});

return ['g',
{w: 2 * grid + keyLength + w, h: h},
['rect', {class: 'object', width: keyLength + w, height: h}],
objectSymbol(grid>>3, h)
].concat(children);
};

const perArray = node => {
const items = (typeof node.items === 'object') ? node.items : {};
const children = rec(items);
const cw = children[1].w;
const ch = children[1].h;
return ['g',
{w: 2 * grid + cw, h: ch},
['rect', {class: 'array', width: cw, height: ch}],
arraySymbol(grid>>3, ch)
].concat([['g', t(grid), children]]);
};

const rec = node => {
if (typeof node === 'object') {

if (node.enum !== undefined) { return perEnum(node); }
if (node.$ref !== undefined) { return perRef(node); }
if (node.oneOf !== undefined) { return perOneOf(node); }

switch (node.type) {
case 'number':
case 'integer':
case 'boolean':
case 'string':
case 'null':
return perLeaf(node);
case 'object':
return perObject(node);
case 'array':
return perArray(node);
}
const w = grid;
const h = w;
return ['rect', {class: 'level', w: w, h: h, width: w, height: h}];
}

const w = grid;
const h = w;
return ['rect', {class: 'error', w: w, h: h, width: w, height: h}];
};

return obj => {
const body = rec(obj);
const res = getSvg({w: body[1].w, h: body[1].h}).concat([style], [['g', t(.5,.5)].concat([body])]);
console.log(res);
return res;
};
}
Insert cell
renderHead = obj => {
if ((obj.title == undefined) && (obj.description == undefined)) {
return '';
}
const res = ['div',
['h3', {id: obj.title}, obj.title || 'Title'],
['div', md`${obj.description || ''}`.innerHTML]
];
return res;
}
Insert cell
renderFoot = obj => {
const res = ['div']; // , 'notes'];
return res;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more