Skip to content

Instantly share code, notes, and snippets.

@serebano
Last active March 17, 2017 07:09
Show Gist options
  • Select an option

  • Save serebano/728de69c44f297dbaddbc987f071b742 to your computer and use it in GitHub Desktop.

Select an option

Save serebano/728de69c44f297dbaddbc987f071b742 to your computer and use it in GitHub Desktop.
class Tag {
static isTag(arg) {
return arg instanceof Tag
}
static create(type) {
return (keys, ...values) => new Tag(type, keys, values)
}
constructor(type, keys, values) {
this.type = type
this.keys = typeof keys !== "undefined" ? [].concat(keys) : []
this.values = values
}
resolve(tree, props) {
const getters = props ? Object.assign({
props: props || {}
}, tree) : tree
if (!getters[this.type])
throw new Error(`Cannot resolve target: ${this.type}`)
if (Model.isModel(getters[this.type])) {
return Object.create(
getters[this.type],
{
type: { value: this.type },
path: { value: this.path(getters) }
}
)
}
return getters[this.type]
}
path(tree, props) {
return this.keys.reduce((path, key, index) => {
const arg = this.values[index];
if (arg instanceof Tag)
return path + key + arg.value(tree, props);
return path + key + (arg || "");
}, "").split(".")
}
value(tree, props) {
const path = this.path(tree, props)
const model = this.resolve(tree, props)
return model.get
? model.get(path)
: path.reduce((obj, key, index) => obj[key], model)
}
tags(map) {
const tags = [this].concat(
this.values.reduce((paths, value) => value instanceof Tag ? paths.concat(value.tags()) : paths, [])
);
return map ? tags.map(map) : tags
}
}
class Tag {
static create(path, ext) {
path = path ? path.split(".") : []
return (keys, ...values) => new Tag(path,keys,values)
}
constructor(path, keys, values) {
this.path = path
this.keys = typeof keys !== "undefined" ? [].concat(keys) : []
this.values = values
}
resolve(tree, props) {
const target = this.path.reduce((o,k)=>o[k] ? o[k] : null, tree)
return Object.create(target, {
path: {
get: () => {
if (!this.keys.length)
return this.path
const res = this.keys.reduce((path,key,index)=>{
if (typeof key === "undefined") return this.path
const value = this.values[index];
if (value instanceof Tag)
return path + key + value.resolve(tree, props).value;
return path + key + (value || "");
}, "")
return res ? this.path.concat(res.split(".")) : this.path
}
},
value: {
get() {
const keys = this.path.slice()
return keys.reduce((target, key, index) => {
if (!target) return undefined
if (target[key] && target[key].get)
return target[key].get(keys.splice(index+1))
return target[key]
}, props ? Object.assign({}, tree, {props}) : tree)
}
}
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment