mirror of
https://github.com/misode/misode.github.io.git
synced 2026-04-23 07:10:41 +00:00
Improvements to transform + make source a textarea
This commit is contained in:
@@ -15,7 +15,6 @@ modelSelector.innerHTML = `
|
||||
<option value="predicate">Predicate</option>
|
||||
<option value="sandbox">Sandbox</option>`
|
||||
modelSelector.addEventListener('change', evt => {
|
||||
console.log("hello?")
|
||||
if (modelSelector.value === 'sandbox') {
|
||||
model = sandboxModel
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { RootNode } from "../nodes/RootNode"
|
||||
import { Path } from "./Path"
|
||||
import { INode } from "../nodes/AbstractNode"
|
||||
|
||||
@@ -25,6 +24,11 @@ export class DataModel {
|
||||
this.listeners.forEach(listener => listener.invalidated(this))
|
||||
}
|
||||
|
||||
reset(value: any) {
|
||||
this.data = value
|
||||
this.invalidate()
|
||||
}
|
||||
|
||||
get(path: Path) {
|
||||
let node = this.data;
|
||||
for (let index of path) {
|
||||
|
||||
@@ -14,6 +14,14 @@ export class ListNode extends AbstractNode<IObject[]> {
|
||||
this.children = values
|
||||
}
|
||||
|
||||
transform(path: Path, value: IObject[]) {
|
||||
if (!(value instanceof Array)) return undefined
|
||||
const res = value.map((obj, index) =>
|
||||
this.children.transform(path.push(index), obj)
|
||||
)
|
||||
return this.transformMod(res)
|
||||
}
|
||||
|
||||
updateModel(el: Element, path: Path, model: DataModel) {
|
||||
model.set(path, el.querySelector('select')?.value)
|
||||
}
|
||||
|
||||
@@ -19,6 +19,15 @@ export class MapNode extends AbstractNode<IMap> {
|
||||
this.values = values
|
||||
}
|
||||
|
||||
transform(path: Path, value: IMap) {
|
||||
if (value === undefined) return undefined
|
||||
let res: any = {}
|
||||
Object.keys(value).forEach(f =>
|
||||
res[f] = this.values.transform(path.push(f), value[f])
|
||||
)
|
||||
return this.transformMod(res);
|
||||
}
|
||||
|
||||
renderRaw(path: Path, value: IMap, view: TreeView) {
|
||||
value = value ?? []
|
||||
const button = view.registerClick(el => {
|
||||
|
||||
@@ -36,14 +36,14 @@ export class ObjectNode extends AbstractNode<IObject> {
|
||||
|
||||
transform(path: Path, value: IObject) {
|
||||
if (value === undefined) return undefined
|
||||
value = value ?? {}
|
||||
const activeCase = this.filter ? this.cases[value[this.filter]] : {};
|
||||
const activeFields = {...this.fields, ...activeCase}
|
||||
let res: any = {}
|
||||
Object.keys(activeFields).forEach(f =>
|
||||
res[f] = activeFields[f].transform(path.push(f), value[f])
|
||||
)
|
||||
return res;
|
||||
Object.keys(activeFields).forEach(f => {
|
||||
console.log(f)
|
||||
return res[f] = activeFields[f].transform(path.push(f), value[f])
|
||||
})
|
||||
return this.transformMod(res);
|
||||
}
|
||||
|
||||
renderRaw(path: Path, value: IObject, view: TreeView, options?: RenderOptions) {
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import { NodeChildren, NodeMods } from './AbstractNode'
|
||||
import { ObjectNode, IObject } from './ObjectNode'
|
||||
import { Path } from '../model/Path'
|
||||
import { TreeView } from '../view/TreeView'
|
||||
|
||||
export class RootNode extends ObjectNode {
|
||||
id: string
|
||||
|
||||
constructor(id: string, fields: NodeChildren, mods?: NodeMods<IObject>) {
|
||||
super(fields, mods)
|
||||
this.id = id
|
||||
}
|
||||
|
||||
render(path: Path, value: IObject, view: TreeView) {
|
||||
value = value ?? {}
|
||||
return `<div>
|
||||
${Object.keys(this.fields).map(f => {
|
||||
return this.fields[f].render(path.push(f), value[f], view)
|
||||
}).join('')}
|
||||
</div>`
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ export class ResourceNode extends EnumNode {
|
||||
const options = mods?.options ?? [] // TODO: Support registry using `github.com/Arcensoth/mcdata`
|
||||
super(options, {
|
||||
transform: (v) => {
|
||||
if (v === undefined) return undefined
|
||||
if (v === undefined || v.length === 0) return undefined
|
||||
return v.startsWith('minecraft:') ? v : 'minecraft:' + v
|
||||
}, ...mods})
|
||||
this.additional = mods?.additional ?? false
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { ObjectNode } from '../nodes/ObjectNode';
|
||||
import { EnumNode } from '../nodes/EnumNode';
|
||||
import { ResourceNode } from '../nodes/custom/ResourceNode';
|
||||
import { NumberNode } from '../nodes/NumberNode';
|
||||
import { BooleanNode } from '../nodes/BooleanNode';
|
||||
import { RootNode } from '../nodes/RootNode';
|
||||
import { RangeNode } from '../nodes/custom/RangeNode';
|
||||
import { MapNode } from '../nodes/MapNode';
|
||||
import { StringNode } from '../nodes/StringNode';
|
||||
@@ -11,10 +9,9 @@ import { ListNode } from '../nodes/ListNode';
|
||||
|
||||
const EntityCollection = ['sheep', 'pig']
|
||||
|
||||
export const SandboxSchema = new RootNode('predicate', {
|
||||
export const SandboxSchema = new ObjectNode({
|
||||
condition: new EnumNode(['foo', 'bar'], {
|
||||
default: () => 'bar',
|
||||
transform: (s: string) => (s === 'foo') ? {test: 'baz'} : s
|
||||
default: () => 'bar'
|
||||
}),
|
||||
number: new NumberNode({integer: false, min: 0}),
|
||||
range: new RangeNode({
|
||||
@@ -22,14 +19,18 @@ export const SandboxSchema = new RootNode('predicate', {
|
||||
}),
|
||||
predicate: new ObjectNode({
|
||||
type: new EnumNode(EntityCollection),
|
||||
nbt: new ResourceNode({
|
||||
nbt: new StringNode({
|
||||
default: (v) => 'hahaha'
|
||||
}),
|
||||
test: new BooleanNode({force: () => true}),
|
||||
recipes: new MapNode(
|
||||
new StringNode(),
|
||||
new RangeNode({
|
||||
default: (v) => RangeNode.isExact(v) ? 2 : v
|
||||
default: (v) => RangeNode.isExact(v) ? 2 : v,
|
||||
transform: (v: any) => RangeNode.isRange(v) ? ({
|
||||
min: v?.min ?? -2147483648,
|
||||
max: v?.max ?? 2147483647
|
||||
}) : v
|
||||
})
|
||||
)
|
||||
}),
|
||||
@@ -49,5 +50,6 @@ export const SandboxSchema = new RootNode('predicate', {
|
||||
predicate: {
|
||||
nbt: 'hi'
|
||||
}
|
||||
})
|
||||
}),
|
||||
transform: (v) => v?.condition === 'foo' ? ({...v, test: 'hello'}) : v
|
||||
});
|
||||
|
||||
@@ -13,7 +13,16 @@ export class SourceView implements ModelListener {
|
||||
|
||||
render() {
|
||||
const transformed = this.model.schema.transform(new Path([], this.model), this.model.data)
|
||||
this.target.textContent = JSON.stringify(transformed)
|
||||
const textarea = document.createElement('textarea')
|
||||
textarea.style.width = 'calc(100% - 6px)'
|
||||
textarea.rows = 10
|
||||
textarea.textContent = JSON.stringify(transformed)
|
||||
textarea.addEventListener('change', evt => {
|
||||
const parsed = JSON.parse(textarea.value)
|
||||
this.model.reset(parsed)
|
||||
})
|
||||
this.target.innerHTML = ''
|
||||
this.target.appendChild(textarea)
|
||||
}
|
||||
|
||||
invalidated() {
|
||||
|
||||
@@ -49,7 +49,8 @@ export class TreeView implements ModelListener {
|
||||
}
|
||||
|
||||
render() {
|
||||
this.target.innerHTML = this.model.schema.render(new Path(), this.model.data, this)
|
||||
this.target.innerHTML = this.model.schema.render(
|
||||
new Path(), this.model.data, this, {hideLabel: true})
|
||||
for (const id in this.registry) {
|
||||
const element = this.target.querySelector(`[data-id="${id}"]`)
|
||||
if (element !== null) this.registry[id](element)
|
||||
|
||||
Reference in New Issue
Block a user