mirror of
https://github.com/misode/misode.github.io.git
synced 2026-04-23 07:10:41 +00:00
Add nodes with render and transform
This commit is contained in:
@@ -6,7 +6,9 @@
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<div id="view"></div>
|
||||
<hr>
|
||||
<div id="source"></div>
|
||||
<script src="./build/bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1 +1,43 @@
|
||||
document!.getElementById('root')!.textContent = 'Hello world!';
|
||||
import { EnumNode } from '../nodes/EnumNode'
|
||||
import { ObjectNode } from '../nodes/ObjectNode'
|
||||
import { StringNode } from '../nodes/StringNode'
|
||||
|
||||
const EntityCollection = ['sheep', 'pig']
|
||||
|
||||
const predicateTree = {
|
||||
id: 'predicate',
|
||||
fields: {
|
||||
condition: new EnumNode(['foo', 'bar'], {
|
||||
transform: (s: string) => (s === 'foo') ? {predicate: 'baz'} : s
|
||||
}),
|
||||
predicate: new ObjectNode({
|
||||
type: new EnumNode(EntityCollection, {}),
|
||||
nbt: new StringNode()
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
function renderTree(tree: any, data: any) {
|
||||
return Object.keys(tree.fields).map(f =>
|
||||
tree.fields[f].render(f, data[f])
|
||||
).join('<br>');
|
||||
}
|
||||
|
||||
function serializeTree(tree: any, data: any) {
|
||||
let res: any = {}
|
||||
Object.keys(tree.fields).forEach(f =>
|
||||
res[f] = tree.fields[f].transform(data[f])
|
||||
)
|
||||
return JSON.stringify(res);
|
||||
}
|
||||
|
||||
let dummyData = {
|
||||
condition: 'foo',
|
||||
chance: 0.4,
|
||||
predicate: {
|
||||
nbt: 'hi'
|
||||
}
|
||||
}
|
||||
|
||||
document!.getElementById('view')!.innerHTML = renderTree(predicateTree, dummyData)
|
||||
document!.getElementById('source')!.textContent = serializeTree(predicateTree, dummyData)
|
||||
|
||||
33
src/nodes/AbstractNode.ts
Normal file
33
src/nodes/AbstractNode.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
export interface INode<T> {
|
||||
setParent: (parent: INode<any>) => void
|
||||
transform: (value: T) => any
|
||||
render: (field: string, value: T) => string
|
||||
}
|
||||
|
||||
export interface NodeChildren {
|
||||
[name: string]: INode<any>
|
||||
}
|
||||
|
||||
export interface NodeMods<T> {
|
||||
transform?: (value: T) => any
|
||||
}
|
||||
|
||||
export abstract class AbstractNode<T> implements INode<T> {
|
||||
private transformMod = (v: T) => v
|
||||
protected parent?: INode<any>
|
||||
|
||||
constructor(mods?: NodeMods<T>) {
|
||||
if (mods?.transform) this.transformMod = mods.transform
|
||||
}
|
||||
|
||||
setParent(parent: INode<any>) {
|
||||
this.parent = parent
|
||||
}
|
||||
|
||||
transform(value: T) {
|
||||
return this.transformMod(value)
|
||||
}
|
||||
|
||||
abstract render(field: string, value: T): string
|
||||
}
|
||||
17
src/nodes/EnumNode.ts
Normal file
17
src/nodes/EnumNode.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { AbstractNode, NodeMods } from './AbstractNode'
|
||||
|
||||
export class EnumNode extends AbstractNode<string> {
|
||||
private options: string[]
|
||||
|
||||
constructor(options: string[], mods?: NodeMods<string>) {
|
||||
super(mods)
|
||||
this.options = options
|
||||
}
|
||||
|
||||
render (field: string, value: string) {
|
||||
return `<span>${field}</span>
|
||||
<select value="${value}">
|
||||
${this.options.map(o => `<option>${o}</option>`)}
|
||||
</select>`
|
||||
}
|
||||
}
|
||||
22
src/nodes/ObjectNode.ts
Normal file
22
src/nodes/ObjectNode.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { AbstractNode, NodeChildren, NodeMods } from './AbstractNode'
|
||||
|
||||
export class ObjectNode extends AbstractNode<any> {
|
||||
private fields: NodeChildren
|
||||
|
||||
constructor(fields: NodeChildren, mods?: NodeMods<any>) {
|
||||
super(mods)
|
||||
this.fields = fields
|
||||
Object.values(fields).forEach(child => {
|
||||
child.setParent(this)
|
||||
})
|
||||
}
|
||||
|
||||
render(field: string, value: any) {
|
||||
value = value || {}
|
||||
return `<span>${field}:</span><div>
|
||||
${Object.keys(this.fields).map(f => {
|
||||
return '> ' + this.fields[f].render(f, value[f])
|
||||
}).join('<br>')}
|
||||
</div>`
|
||||
}
|
||||
}
|
||||
11
src/nodes/StringNode.ts
Normal file
11
src/nodes/StringNode.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { AbstractNode, NodeMods } from './AbstractNode'
|
||||
|
||||
export class StringNode extends AbstractNode<string> {
|
||||
constructor(mods?: NodeMods<string>) {
|
||||
super(mods)
|
||||
}
|
||||
|
||||
render(field: string, value: string) {
|
||||
return `<span>${field}</span> <span>${value || ''}</span>`
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user