mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 02:10:08 +00:00
started real work on tags...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
a0767d3c11
commit
210ad80c3d
@ -30,9 +30,17 @@ var TagsClassPrototype = {
|
|||||||
// .normalize([tag, ...])
|
// .normalize([tag, ...])
|
||||||
// -> [ntag, ...]
|
// -> [ntag, ...]
|
||||||
//
|
//
|
||||||
// XXX should this sort sets???
|
// NOTE: tag set order is not significant.
|
||||||
|
// NOTE: for mixed tags sets are sorted in-place within paths,
|
||||||
|
// e.g.
|
||||||
|
// c:b/a -> b:c/a
|
||||||
|
//
|
||||||
|
// XXX not sure if we should do:
|
||||||
|
// c:b/a -> b:c/a - sort sets within pats (current)
|
||||||
|
// or
|
||||||
|
// c:b/a -> b/a:c - sort paths within sets
|
||||||
// XXX should this be .normalizeTags(..) ???
|
// XXX should this be .normalizeTags(..) ???
|
||||||
// XXX should this resolve aliases???
|
// XXX should we support priority braces, i.e. c:(b/a)
|
||||||
normalize: function(...tags){
|
normalize: function(...tags){
|
||||||
var that = this
|
var that = this
|
||||||
var tagRemovedChars = (this.config || {})['tagRemovedChars']
|
var tagRemovedChars = (this.config || {})['tagRemovedChars']
|
||||||
@ -50,10 +58,18 @@ var TagsClassPrototype = {
|
|||||||
.trim()
|
.trim()
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.replace(tagRemovedChars, '')
|
.replace(tagRemovedChars, '')
|
||||||
// XXX do we need to sort here???
|
// sort sets within paths...
|
||||||
.split(/:/)
|
.split(/[\\\/]/g)
|
||||||
.sort()
|
.map(function(e){
|
||||||
.join(':') })
|
return e
|
||||||
|
.split(/:/g)
|
||||||
|
.sort()
|
||||||
|
.join(':') })
|
||||||
|
.join('/') })
|
||||||
|
// sort paths within sets...
|
||||||
|
//.split(/:/g)
|
||||||
|
// .sort()
|
||||||
|
// .join(':') })
|
||||||
.unique()
|
.unique()
|
||||||
return (tags.length == 1 && !(tags[0] instanceof Array)) ?
|
return (tags.length == 1 && !(tags[0] instanceof Array)) ?
|
||||||
// NOTE: if we got a single tag return it as a single tag...
|
// NOTE: if we got a single tag return it as a single tag...
|
||||||
@ -88,14 +104,7 @@ var TagsPrototype = {
|
|||||||
// [ <tag>, ... ]
|
// [ <tag>, ... ]
|
||||||
//
|
//
|
||||||
// XXX Q: should these be normalized???
|
// XXX Q: should these be normalized???
|
||||||
__persistent_tags: [],
|
__persistent_tags: null,
|
||||||
|
|
||||||
// Format:
|
|
||||||
// {
|
|
||||||
// <tag>: [ <item>, ... ],
|
|
||||||
// ...
|
|
||||||
// }
|
|
||||||
__index: {},
|
|
||||||
|
|
||||||
// Format:
|
// Format:
|
||||||
// {
|
// {
|
||||||
@ -104,7 +113,14 @@ var TagsPrototype = {
|
|||||||
//
|
//
|
||||||
// XXX need introspection for this...
|
// XXX need introspection for this...
|
||||||
// ...should this be .aliases ???
|
// ...should this be .aliases ???
|
||||||
__aliases: {},
|
__aliases: null,
|
||||||
|
|
||||||
|
// Format:
|
||||||
|
// {
|
||||||
|
// <tag>: [ <item>, ... ],
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
__index: null,
|
||||||
|
|
||||||
|
|
||||||
// Utils...
|
// Utils...
|
||||||
@ -113,37 +129,106 @@ var TagsPrototype = {
|
|||||||
// XXX Q: should this be .normalizeTags(..) ???
|
// XXX Q: should this be .normalizeTags(..) ???
|
||||||
normalize: function(...tags){
|
normalize: function(...tags){
|
||||||
return this.constructor.normalize.call(this, ...tags) },
|
return this.constructor.normalize.call(this, ...tags) },
|
||||||
|
// Match two tags...
|
||||||
// XXX expand aliases...
|
|
||||||
// XXX
|
|
||||||
|
|
||||||
|
|
||||||
get length(){
|
|
||||||
// XXX number of elements (values)...
|
|
||||||
},
|
|
||||||
|
|
||||||
// Tags present in the system...
|
|
||||||
//
|
//
|
||||||
// NOTE: this includes all the .persistent tags as well as all the
|
// NOTE: this is not symmetric e.g. a will match a:b but not vice-versa.
|
||||||
// tags actually used.
|
//
|
||||||
tags: function(){
|
// XXX add support for * in sets...
|
||||||
// XXX
|
match: function(a, b){
|
||||||
|
// normalized match...
|
||||||
|
a = this.normalize(a)
|
||||||
|
b = this.normalize(b)
|
||||||
|
if(a == b){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// set matching...
|
||||||
|
// a matches b iff each element of a exists in b.
|
||||||
|
var matchSet = function(a, b){
|
||||||
|
a = a.split(/:/g)
|
||||||
|
b = b.split(/:/g)
|
||||||
|
return a
|
||||||
|
.filter(function(e){
|
||||||
|
return e == '*'
|
||||||
|
|| b.indexOf(e) < 0 }).length == 0 }
|
||||||
|
|
||||||
|
// path matching...
|
||||||
|
// a matches b iff each element in a exists in b and in the same
|
||||||
|
// order as in a.
|
||||||
|
a = a.split(/[\/\\]/g)
|
||||||
|
b = b.split(/[\/\\]/g)
|
||||||
|
|
||||||
|
return b
|
||||||
|
.reduce(function(a, e){
|
||||||
|
return a[0] && matchSet(a[0], e) ?
|
||||||
|
a.slice(1)
|
||||||
|
: a
|
||||||
|
}, a).length == 0
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// Introspection...
|
||||||
|
//
|
||||||
|
get length(){
|
||||||
|
return this.values().length },
|
||||||
|
|
||||||
// XXX need a way to add/remove these...
|
// XXX need a way to add/remove these...
|
||||||
persistent: function(){
|
persistent: function(){
|
||||||
// XXX
|
// XXX
|
||||||
},
|
},
|
||||||
values: function(){
|
// Tags present in the system...
|
||||||
// XXX
|
//
|
||||||
|
// Get all tags...
|
||||||
|
// .tags()
|
||||||
|
// -> tags
|
||||||
|
//
|
||||||
|
// Get value tags...
|
||||||
|
// .tags(value)
|
||||||
|
// -> tags
|
||||||
|
//
|
||||||
|
// NOTE: this includes all the .persistent tags as well as all the
|
||||||
|
// tags actually used.
|
||||||
|
tags: function(value){
|
||||||
|
var that = this
|
||||||
|
// get tags of specific value...
|
||||||
|
if(value){
|
||||||
|
return Object.entries(this.__index || {})
|
||||||
|
.filter(function(e){ return e[1].has(value) })
|
||||||
|
.map(function(e){ return e[0] })
|
||||||
|
.flat()
|
||||||
|
.unique()
|
||||||
|
|
||||||
|
// get all tags...
|
||||||
|
} else {
|
||||||
|
return Object.keys(this.__index || {})
|
||||||
|
.concat((this.__persistent_tags || [])
|
||||||
|
.map(function(t){
|
||||||
|
return that.normalize(t) }))
|
||||||
|
.unique()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
//
|
||||||
|
// Get all values...
|
||||||
|
// .values()
|
||||||
|
// -> values
|
||||||
|
//
|
||||||
|
// Get specific tag values...
|
||||||
|
// .values(tag)
|
||||||
|
// -> values
|
||||||
|
//
|
||||||
|
// NOTE: this does not support any query syntax...
|
||||||
|
values: function(tag){
|
||||||
|
var that = this
|
||||||
|
tag = this.normalize(tag || '*')
|
||||||
|
return [...new Set(
|
||||||
|
Object.entries(this.__index || {})
|
||||||
|
.filter(function(e){
|
||||||
|
return tag == '*' || that.match(tag, e[0]) })
|
||||||
|
.map(function(s){ return [...s[1]] })
|
||||||
|
.flat())] },
|
||||||
|
|
||||||
|
|
||||||
// Add/Remove/Modify tags API...
|
// Add/Remove/Modify tags API...
|
||||||
// XXX
|
|
||||||
path: function(){
|
|
||||||
// XXX
|
|
||||||
return this
|
|
||||||
},
|
|
||||||
//
|
//
|
||||||
// Resolve alias (recursive)...
|
// Resolve alias (recursive)...
|
||||||
// .alias(tag)
|
// .alias(tag)
|
||||||
@ -159,6 +244,7 @@ var TagsPrototype = {
|
|||||||
// -> this
|
// -> this
|
||||||
//
|
//
|
||||||
alias: function(tag, value){
|
alias: function(tag, value){
|
||||||
|
var aliases = this.__aliases = this.__aliases || {}
|
||||||
// XXX this seems a bit ugly...
|
// XXX this seems a bit ugly...
|
||||||
var resolve = function(tag, seen){
|
var resolve = function(tag, seen){
|
||||||
seen = seen || []
|
seen = seen || []
|
||||||
@ -168,8 +254,8 @@ var TagsPrototype = {
|
|||||||
seen
|
seen
|
||||||
.concat([seen[0]])
|
.concat([seen[0]])
|
||||||
.join('" -> "') }"`) }
|
.join('" -> "') }"`) }
|
||||||
var next = this.__aliases[tag]
|
var next = aliases[tag]
|
||||||
|| this.__aliases[this.normalize(tag)]
|
|| aliases[this.normalize(tag)]
|
||||||
seen.push(tag)
|
seen.push(tag)
|
||||||
return next != null ?
|
return next != null ?
|
||||||
resolve(next, seen)
|
resolve(next, seen)
|
||||||
@ -184,8 +270,8 @@ var TagsPrototype = {
|
|||||||
|
|
||||||
// remove...
|
// remove...
|
||||||
} else if(value == null){
|
} else if(value == null){
|
||||||
delete this.__aliases[tag.trim()]
|
delete aliases[tag.trim()]
|
||||||
delete this.__aliases[this.normalize(tag)]
|
delete aliases[this.normalize(tag)]
|
||||||
|
|
||||||
// set...
|
// set...
|
||||||
} else {
|
} else {
|
||||||
@ -201,20 +287,35 @@ var TagsPrototype = {
|
|||||||
.concat([chain[0]])
|
.concat([chain[0]])
|
||||||
.join('" -> "') }"`) }
|
.join('" -> "') }"`) }
|
||||||
|
|
||||||
this.__aliases[tag] = value
|
aliases[tag] = value
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
// Add/Remove/Modify content API...
|
// Add/Remove/Modify content API...
|
||||||
// XXX
|
//
|
||||||
tag: function(){
|
// XXX save un-normalized tags as aliases...
|
||||||
// XXX
|
// XXX when value is not given, add tags to persistent tags...
|
||||||
|
tag: function(tags, value){
|
||||||
|
var that = this
|
||||||
|
this.__index = this.__index || {}
|
||||||
|
this.normalize(tags instanceof Array ? tags : [tags])
|
||||||
|
.forEach(function(tag){
|
||||||
|
(that.__index[tag] = that.__index[tag] || new Set()).add(value) })
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
untag: function(){
|
untag: function(tags, value){
|
||||||
// XXX
|
var that = this
|
||||||
|
this.normalize(tags instanceof Array ? tags : [tags])
|
||||||
|
.forEach(function(tag){
|
||||||
|
var s = that.__index[tag] || new Set()
|
||||||
|
s.delete(value)
|
||||||
|
// remove empty sets...
|
||||||
|
if(s.size == 0){
|
||||||
|
delete that.__index[tag]
|
||||||
|
}
|
||||||
|
})
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user