mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 10:20:08 +00:00
reworked deffinitions again...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
fb9570c175
commit
bc9962bc64
@ -16,6 +16,11 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* TODO:
|
* TODO:
|
||||||
|
* - stress test / optimize this for:
|
||||||
|
* - large number of tags, paths
|
||||||
|
* - larger number of definitions
|
||||||
|
* - extremely large numbers of values
|
||||||
|
* ...values should have the least impact on performance.
|
||||||
* - investigate support for sqlite3
|
* - investigate support for sqlite3
|
||||||
* - will it be faster?
|
* - will it be faster?
|
||||||
*
|
*
|
||||||
@ -264,27 +269,28 @@ var BaseTagsPrototype = {
|
|||||||
// Tag definitions...
|
// Tag definitions...
|
||||||
//
|
//
|
||||||
// Format:
|
// Format:
|
||||||
// Set([<tag>, ..])
|
|
||||||
//
|
|
||||||
// XXX Q: should definitions be treated as persistent tags???
|
|
||||||
definitions: null,
|
|
||||||
// Format:
|
|
||||||
// {
|
// {
|
||||||
// <tag>: [<tag>, ..],
|
// <tag>: [<tag>, ..],
|
||||||
// ...
|
// ...
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
__definition_index: null,
|
// NOTE: a definition is equivalent to a very specific path tag but
|
||||||
get definition_index(){
|
// considering it's a special case it is handled allot faster...
|
||||||
var that = this
|
// .define('birds', 'bird:many')
|
||||||
return (this.definitions == null || this.definitions.size == 0) ?
|
// is equivalent to:
|
||||||
{}
|
// .togglePersistent('bird:many/birds')
|
||||||
: (this.__definition_index = this.__definition_index
|
//
|
||||||
|| [...this.definitions]
|
// XXX Q: should definitions be displayed as persistent tags???
|
||||||
.reduce(function(res, p){
|
definitions: null,
|
||||||
p = that.splitPath(p)
|
|
||||||
res[p.pop()] = that.splitSet(p[0])
|
// definitions as paths...
|
||||||
return res }, {})) },
|
//
|
||||||
|
// XXX do we need this???
|
||||||
|
// XXX should we cache this???
|
||||||
|
get definition_paths(){
|
||||||
|
return [...Object.entries(this.definitions)]
|
||||||
|
.map(function(e){
|
||||||
|
return [e[1].join(':'), e[0]].join('/') }) },
|
||||||
|
|
||||||
|
|
||||||
// Props...
|
// Props...
|
||||||
@ -294,10 +300,7 @@ var BaseTagsPrototype = {
|
|||||||
// XXX should this include only definition keys, values or both???
|
// XXX should this include only definition keys, values or both???
|
||||||
get persistentAll(){
|
get persistentAll(){
|
||||||
return (this.__persistent || new Set())
|
return (this.__persistent || new Set())
|
||||||
.unite(this.definitions || []) },
|
.unite(this.definition_paths || []) },
|
||||||
//.unite(Object.entries(this.definitions || {})
|
|
||||||
// .flat(1)
|
|
||||||
// .map(function(d){ return d.join ? d.join(':') : d })) },
|
|
||||||
|
|
||||||
|
|
||||||
// Utils...
|
// Utils...
|
||||||
@ -400,7 +403,7 @@ var BaseTagsPrototype = {
|
|||||||
|
|
||||||
// match two tags...
|
// match two tags...
|
||||||
} else {
|
} else {
|
||||||
var definitions = this.definition_index
|
var definitions = this.definitions
|
||||||
|
|
||||||
var root = /^\s*[\\\/]/.test(a)
|
var root = /^\s*[\\\/]/.test(a)
|
||||||
var base = /[\\\/]\s*$/.test(a)
|
var base = /[\\\/]\s*$/.test(a)
|
||||||
@ -417,7 +420,6 @@ var BaseTagsPrototype = {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Expand definitions...
|
// Expand definitions...
|
||||||
//
|
//
|
||||||
// NOTE: this does not care about infinite recursion...
|
// NOTE: this does not care about infinite recursion...
|
||||||
@ -1034,9 +1036,7 @@ var BaseTagsPrototype = {
|
|||||||
} else {
|
} else {
|
||||||
patchSet(this.persistent || [])
|
patchSet(this.persistent || [])
|
||||||
patchObj(this.__index || {})
|
patchObj(this.__index || {})
|
||||||
//patchObj(this.definitions || {}, true)
|
patchObj(this.definitions || {}, true)
|
||||||
patchSet(this.definitions || [])
|
|
||||||
delete this.__definition_index
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this
|
return this
|
||||||
@ -1081,106 +1081,6 @@ var BaseTagsPrototype = {
|
|||||||
return res
|
return res
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*/ XXX there are two implementations here:
|
|
||||||
// 1) using a map index...
|
|
||||||
// + should be faster...
|
|
||||||
// - re-implements essentially the same mechanism as path
|
|
||||||
// searching but in a different way...
|
|
||||||
// 2) using the existing path mechanic...
|
|
||||||
// + simpler
|
|
||||||
// + less code
|
|
||||||
// - should be slower for lots of deffinitions...
|
|
||||||
// Get/set/remove tag definitions...
|
|
||||||
//
|
|
||||||
// A definition is a single tag that is defined by ("means") a tag set.
|
|
||||||
//
|
|
||||||
// Resolve definition (recursive)...
|
|
||||||
// .define(tag)
|
|
||||||
// -> value
|
|
||||||
// -> undefined
|
|
||||||
//
|
|
||||||
// Set definition...
|
|
||||||
// .define(tag, value)
|
|
||||||
// -> this
|
|
||||||
//
|
|
||||||
// Remove definition...
|
|
||||||
// .define(tag, null)
|
|
||||||
// -> this
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Nested recursive definitions (i.e. left side is part of the right
|
|
||||||
// side) are supported, but literal definition recursion are not (i.e.
|
|
||||||
// left side is literally reachable in the definitionchain):
|
|
||||||
// a -> a:b:c - nested (recursive) definition, this is fine.
|
|
||||||
// a -> a - type A literal recursion, this will fail.
|
|
||||||
// a -> b -> a - type B literal recursion will fail too.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
// // nested recursive definition...
|
|
||||||
// ts.define('bird', 'bird:one')
|
|
||||||
//
|
|
||||||
// ts.define('birds', 'bird:many')
|
|
||||||
//
|
|
||||||
// // filter a list...
|
|
||||||
// ts.match('bird', ['bird', 'birds', 'animal']) // -> ['bird', 'birds']
|
|
||||||
//
|
|
||||||
define: function(tag, value){
|
|
||||||
var definitions = this.definitions = this.definitions || {}
|
|
||||||
|
|
||||||
// XXX this seems a bit ugly...
|
|
||||||
var resolve = function(tag, seen){
|
|
||||||
seen = seen || []
|
|
||||||
// check for loops...
|
|
||||||
if(seen.indexOf(tag) >= 0){
|
|
||||||
throw new Error(`.alias(..): Recursive alias chain: "${
|
|
||||||
seen
|
|
||||||
.concat([seen[0]])
|
|
||||||
.join('" -> "') }"`) }
|
|
||||||
var next = definitions[tag]
|
|
||||||
|| definitions[this.normalize(tag)]
|
|
||||||
seen.push(tag)
|
|
||||||
return next != null ?
|
|
||||||
resolve(next.join(':'), seen)
|
|
||||||
: seen.length > 1 ?
|
|
||||||
tag
|
|
||||||
: undefined
|
|
||||||
}.bind(this)
|
|
||||||
|
|
||||||
tag = this.normalize(tag)
|
|
||||||
if(/[:\\\/]/.test(tag)){
|
|
||||||
throw new Error(`.alias(..): tag must be a single tag, got: "${tag}`) }
|
|
||||||
|
|
||||||
// resolve...
|
|
||||||
if(arguments.length == 1){
|
|
||||||
return resolve(tag)
|
|
||||||
|
|
||||||
// remove...
|
|
||||||
} else if(value == null){
|
|
||||||
delete definitions[tag]
|
|
||||||
|
|
||||||
// set...
|
|
||||||
} else {
|
|
||||||
value = this.normalize(value)
|
|
||||||
if(/[\\\/]/.test(tag)){
|
|
||||||
throw new Error(`.alias(..): value must not be a path, got: "${value}`) }
|
|
||||||
|
|
||||||
// check for recursion...
|
|
||||||
var chain = []
|
|
||||||
var target = resolve(value, chain)
|
|
||||||
if(target == tag || target == this.normalize(tag)){
|
|
||||||
throw new Error(`.alias(..): Creating a recursive alias chain: "${
|
|
||||||
chain
|
|
||||||
.concat([chain[0]])
|
|
||||||
.join('" -> "') }"`) }
|
|
||||||
|
|
||||||
definitions[tag] = this.splitSet(value)
|
|
||||||
}
|
|
||||||
return this
|
|
||||||
},
|
|
||||||
/*/
|
|
||||||
// Get/set/remove tag definitions...
|
// Get/set/remove tag definitions...
|
||||||
//
|
//
|
||||||
// A definition is a single tag that is defined by ("means") a tag set.
|
// A definition is a single tag that is defined by ("means") a tag set.
|
||||||
@ -1226,7 +1126,6 @@ var BaseTagsPrototype = {
|
|||||||
// in a different location (.definitions), same search rules
|
// in a different location (.definitions), same search rules
|
||||||
// apply.
|
// apply.
|
||||||
//
|
//
|
||||||
// XXX this can be faster if we index definitions via a map...
|
|
||||||
define: function(tag, value){
|
define: function(tag, value){
|
||||||
var that = this
|
var that = this
|
||||||
var definitions = this.definitions
|
var definitions = this.definitions
|
||||||
@ -1249,23 +1148,19 @@ var BaseTagsPrototype = {
|
|||||||
// get/resolve...
|
// get/resolve...
|
||||||
if(arguments.length == 1){
|
if(arguments.length == 1){
|
||||||
// NOTE: we expect there to be only one definition...
|
// NOTE: we expect there to be only one definition...
|
||||||
return this.match(tag +'/', [...this.definitions || []])
|
return this.match(tag +'/', [...Object.keys(definitions) || []])
|
||||||
.map(function(d){
|
.map(function(d){
|
||||||
return that.splitPath(d).shift() })[0]
|
return definitions[d].join(':') })[0]
|
||||||
|
|
||||||
// remove...
|
// remove...
|
||||||
} else if(value == null){
|
} else if(value == null){
|
||||||
// remove all definitions of tag...
|
|
||||||
this.match(tag +'/', [...this.definitions || []])
|
|
||||||
.forEach(function(value){
|
|
||||||
definitions.delete(value +'/'+ tag) })
|
|
||||||
|
|
||||||
// delete empty .definitions
|
// delete empty .definitions
|
||||||
definitions
|
definitions
|
||||||
&& definitions.size == 0
|
&& Object.keys(definitions).length == 0
|
||||||
&& (delete this.definitions)
|
&& (delete this.definitions)
|
||||||
|
|
||||||
delete this.__definition_index
|
// clear the index...
|
||||||
|
delete (definitions || {})[tag]
|
||||||
|
|
||||||
// set...
|
// set...
|
||||||
} else {
|
} else {
|
||||||
@ -1274,16 +1169,19 @@ var BaseTagsPrototype = {
|
|||||||
throw new Error(`.alias(..): value must not be a path, got: "${value}`) }
|
throw new Error(`.alias(..): value must not be a path, got: "${value}`) }
|
||||||
|
|
||||||
// clear previous definition...
|
// clear previous definition...
|
||||||
|
// NOTE: this will also clear the index...
|
||||||
this.define(tag, null)
|
this.define(tag, null)
|
||||||
|
|
||||||
this.definitions = (this.definitions || new Set())
|
// XXX add the def...
|
||||||
.add(value +'/'+ tag)
|
//this.definitions = (this.definitions || new Set())
|
||||||
|
// .add(value +'/'+ tag)
|
||||||
|
|
||||||
|
// update the index...
|
||||||
|
this.definitions = definitions || {}
|
||||||
|
this.definitions[tag] = this.splitSet(value)
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
//*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Optimize tags...
|
// Optimize tags...
|
||||||
@ -1651,10 +1549,8 @@ var BaseTagsPrototype = {
|
|||||||
var res = {}
|
var res = {}
|
||||||
|
|
||||||
// definitions...
|
// definitions...
|
||||||
//this.definitions && Object.keys(this.definitions).length > 0
|
this.definitions && Object.keys(this.definitions).length > 0
|
||||||
// && (res.definitions = Object.assign({}, this.definitions))
|
&& (res.definitions = Object.assign({}, this.definitions))
|
||||||
this.definitions && this.definitions.size > 0
|
|
||||||
&& (res.definitions = [...this.definitions])
|
|
||||||
|
|
||||||
// persistent tags...
|
// persistent tags...
|
||||||
this.persistent && this.persistent.size > 0
|
this.persistent && this.persistent.size > 0
|
||||||
@ -1674,8 +1570,7 @@ var BaseTagsPrototype = {
|
|||||||
|
|
||||||
// definitions...
|
// definitions...
|
||||||
json.definitions
|
json.definitions
|
||||||
//&& (this.definitions = Object.assign({}, json.definitions))
|
&& (this.definitions = Object.assign({}, json.definitions))
|
||||||
&& (this.definitions = new Set(json.definitions))
|
|
||||||
|
|
||||||
// persistent tags...
|
// persistent tags...
|
||||||
json.persistent
|
json.persistent
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user