mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 02:10:08 +00:00
refactoring and simplification + docs...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
5b7b7f9257
commit
846f9a3b4c
@ -167,25 +167,28 @@ var BaseTagsClassPrototype = {
|
|||||||
|
|
||||||
var res = normalizeSplit(tags)
|
var res = normalizeSplit(tags)
|
||||||
.map(function(tag){
|
.map(function(tag){
|
||||||
return tag
|
return typeof(tag) == typeof('str') ?
|
||||||
.trim()
|
tag
|
||||||
.toLowerCase()
|
.trim()
|
||||||
.replace(ILLEGAL_CHARS, '')
|
.toLowerCase()
|
||||||
// sort sets within paths...
|
.replace(ILLEGAL_CHARS, '')
|
||||||
.split(PP)
|
// sort sets within paths...
|
||||||
.map(function(e){
|
.split(PP)
|
||||||
return e
|
.map(function(e){
|
||||||
.split(SP)
|
return e
|
||||||
// remove empty set members...
|
.split(SP)
|
||||||
.filter(function(t){
|
// remove empty set members...
|
||||||
return t != '' })
|
.filter(function(t){
|
||||||
.unique()
|
return t != '' })
|
||||||
.sort()
|
.unique()
|
||||||
.join(SS) })
|
.sort()
|
||||||
// NOTE: this also kills the leading '/'
|
.join(SS) })
|
||||||
.filter(function(t){
|
// NOTE: this also kills the leading '/'
|
||||||
return t != '' })
|
.filter(function(t){
|
||||||
.join(PS) })
|
return t != '' })
|
||||||
|
.join(PS)
|
||||||
|
: [] })
|
||||||
|
.flat()
|
||||||
.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...
|
||||||
@ -402,6 +405,8 @@ var BaseTagsPrototype = {
|
|||||||
// a - single tag
|
// a - single tag
|
||||||
// NOTE: a tag is also a unary path and a singular
|
// NOTE: a tag is also a unary path and a singular
|
||||||
// set (see below).
|
// set (see below).
|
||||||
|
// "a" - explicit match, this checks if the tag exists as-is
|
||||||
|
// without any additional heuristics...
|
||||||
// a/b - path, 2 or more tags joined with '/' (or '\').
|
// a/b - path, 2 or more tags joined with '/' (or '\').
|
||||||
// defines a directional relation between a and b
|
// defines a directional relation between a and b
|
||||||
// /a - path special case, a path with a leading '/' (or '\')
|
// /a - path special case, a path with a leading '/' (or '\')
|
||||||
@ -410,6 +415,7 @@ var BaseTagsPrototype = {
|
|||||||
// defines a non-directional relation between a and b.
|
// defines a non-directional relation between a and b.
|
||||||
// * - tag placeholder, matches one and only one tag
|
// * - tag placeholder, matches one and only one tag
|
||||||
//
|
//
|
||||||
|
// NOTE: "a" is equivalent to 'a'
|
||||||
// NOTE: paths have priority over sets: a/b:c -> a / b:c
|
// NOTE: paths have priority over sets: a/b:c -> a / b:c
|
||||||
// NOTE: there is a special case pattern '*a*' that matches the same
|
// NOTE: there is a special case pattern '*a*' that matches the same
|
||||||
// way as 'a', this is used in methods where 'a' is used as an
|
// way as 'a', this is used in methods where 'a' is used as an
|
||||||
@ -509,7 +515,7 @@ var BaseTagsPrototype = {
|
|||||||
b.filter(function(t){
|
b.filter(function(t){
|
||||||
return a == t })
|
return a == t })
|
||||||
: b != null ?
|
: b != null ?
|
||||||
(a == b
|
!!(a == b
|
||||||
|| (definitions
|
|| (definitions
|
||||||
&& (definitions[a] == b
|
&& (definitions[a] == b
|
||||||
|| a == definitions[b]
|
|| a == definitions[b]
|
||||||
@ -732,6 +738,9 @@ var BaseTagsPrototype = {
|
|||||||
// (i.e. ['a:b:c', 'a:b', 'a:c', 'a']) and will only return
|
// (i.e. ['a:b:c', 'a:b', 'a:c', 'a']) and will only return
|
||||||
// the actual full match and an individual tag match...
|
// the actual full match and an individual tag match...
|
||||||
// XXX should it???
|
// XXX should it???
|
||||||
|
// XXX should we support partial quoting?
|
||||||
|
// ...e.g. a:"b" -- search for any set explicitly containing
|
||||||
|
// 'b' and any tag containing an 'a'...
|
||||||
search: function(query, tags){
|
search: function(query, tags){
|
||||||
var that = this
|
var that = this
|
||||||
tags = tags == null ?
|
tags = tags == null ?
|
||||||
@ -968,7 +977,7 @@ var BaseTagsPrototype = {
|
|||||||
},
|
},
|
||||||
// NOTE: this supports tag patterns (see: .match(..))
|
// NOTE: this supports tag patterns (see: .match(..))
|
||||||
// NOTE: non-pattern tags are matched explicitly.
|
// NOTE: non-pattern tags are matched explicitly.
|
||||||
// XXX BUG?: should this remove tags directly (current) or via matching??
|
// XXX Q: should this remove tags directly (current) or via matching??
|
||||||
// .tag('a:b', 'x')
|
// .tag('a:b', 'x')
|
||||||
// .untag('a', 'x') -- this will do nothing.
|
// .untag('a', 'x') -- this will do nothing.
|
||||||
// .untag('*a*', 'x') -- remove the tag.
|
// .untag('*a*', 'x') -- remove the tag.
|
||||||
@ -978,6 +987,7 @@ var BaseTagsPrototype = {
|
|||||||
// .untag('"a"', 'x') -- should remove tagged explicitly
|
// .untag('"a"', 'x') -- should remove tagged explicitly
|
||||||
// with "a"...
|
// with "a"...
|
||||||
// .untag('a', 'x') -- like the current '*a*'
|
// .untag('a', 'x') -- like the current '*a*'
|
||||||
|
// what should the default be????
|
||||||
untag: function(tags, value){
|
untag: function(tags, value){
|
||||||
var that = this
|
var that = this
|
||||||
var index = this.__index = this.__index || {}
|
var index = this.__index = this.__index || {}
|
||||||
@ -1077,95 +1087,6 @@ var BaseTagsPrototype = {
|
|||||||
(that.tag(tag, v), true)
|
(that.tag(tag, v), true)
|
||||||
: null) }) },
|
: null) }) },
|
||||||
|
|
||||||
// Rename a tag...
|
|
||||||
//
|
|
||||||
// Rename tag...
|
|
||||||
// .rename(from, to)
|
|
||||||
// -> this
|
|
||||||
//
|
|
||||||
// Rename a tag in list of tags...
|
|
||||||
// .rename(from, to, tag, ...)
|
|
||||||
// .rename(from, to, [tag, ...])
|
|
||||||
// -> tags
|
|
||||||
//
|
|
||||||
// NOTE: if to is '' this will remove all occurrences of from.
|
|
||||||
// NOTE: if any renamed tag is renamed to '' it will be removed
|
|
||||||
// untagging all relevant values...
|
|
||||||
//
|
|
||||||
// XXX need to sanitize tag -- it can not contain regex characters...
|
|
||||||
// ...should we guard against this???
|
|
||||||
rename: function(tag, to, ...tags){
|
|
||||||
var that = this
|
|
||||||
|
|
||||||
// XXX should we bo more pedantic here???
|
|
||||||
tag = this.normalize(tag)
|
|
||||||
if(tag == ''){
|
|
||||||
throw new Error(`.rename(..): first argument can not be an empty string.`) }
|
|
||||||
if(/[:\\\/]/.test(tag)){
|
|
||||||
throw new Error(
|
|
||||||
`.rename(..): only support singular tag renaming, got: "${tag}"`) }
|
|
||||||
// XXX too strict???
|
|
||||||
if(!/^[a-z0-9]+$/.test(tag)){
|
|
||||||
throw new Error(
|
|
||||||
`.rename(..): first argument must be a valid single tag, got: "${tag}"`) }
|
|
||||||
|
|
||||||
to = this.normalize(to)
|
|
||||||
if(/[\\\/]/.test(to)){
|
|
||||||
throw new Error(
|
|
||||||
`.rename(..): only support tags and tag sets as renaming target, got: "${to}"`) }
|
|
||||||
|
|
||||||
tags = new Set(normalizeSplit(tags))
|
|
||||||
|
|
||||||
// prepare for the replacement...
|
|
||||||
var pattern = new RegExp(`(^|[:\\\\\\/])${tag}(?=$|[:\\\\\\/])`, 'g')
|
|
||||||
var target = `$1${to}`
|
|
||||||
|
|
||||||
var patchSet = function(s){
|
|
||||||
that.match(tag, [...s || []])
|
|
||||||
.forEach(function(tag){
|
|
||||||
s.delete(tag)
|
|
||||||
var t = that.normalize(tag.replace(pattern, target))
|
|
||||||
t != ''
|
|
||||||
&& s.add(t)
|
|
||||||
})
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
var patchObj = function(o, patchValue){
|
|
||||||
that.match(tag, Object.keys(o || {}))
|
|
||||||
.forEach(function(m){
|
|
||||||
var value = o[m]
|
|
||||||
delete o[m]
|
|
||||||
var t = that.normalize(m.replace(pattern, target))
|
|
||||||
t != ''
|
|
||||||
&& (o[t] = value)
|
|
||||||
})
|
|
||||||
patchValue
|
|
||||||
&& Object.keys(o || {})
|
|
||||||
.forEach(function(m){
|
|
||||||
var v = o[m]
|
|
||||||
if(that.match(tag, v)){
|
|
||||||
var t = that.normalize(v.replace(pattern, target))
|
|
||||||
t == '' ?
|
|
||||||
(delete o[m])
|
|
||||||
: (o[m] = t)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return o
|
|
||||||
}
|
|
||||||
|
|
||||||
// rename tags in list...
|
|
||||||
if(arguments.length > 2){
|
|
||||||
return [...patchSet(tags)]
|
|
||||||
|
|
||||||
// rename actual data...
|
|
||||||
} else {
|
|
||||||
patchSet(this.persistent || [])
|
|
||||||
patchObj(this.__index || {})
|
|
||||||
patchObj(this.definitions || {}, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
return this
|
|
||||||
},
|
|
||||||
// Replace tags...
|
// Replace tags...
|
||||||
//
|
//
|
||||||
// Replace tags...
|
// Replace tags...
|
||||||
@ -1195,6 +1116,7 @@ var BaseTagsPrototype = {
|
|||||||
// reachability or definitions...
|
// reachability or definitions...
|
||||||
// NOTE: this will match tags in .__index, .persistent and .definitions
|
// NOTE: this will match tags in .__index, .persistent and .definitions
|
||||||
//
|
//
|
||||||
|
// XXX revise...
|
||||||
replace: function(tag, to, ...tags){
|
replace: function(tag, to, ...tags){
|
||||||
var that = this
|
var that = this
|
||||||
tags = normalizeSplit(tags)
|
tags = normalizeSplit(tags)
|
||||||
@ -1270,6 +1192,54 @@ var BaseTagsPrototype = {
|
|||||||
res.flat()
|
res.flat()
|
||||||
: this
|
: this
|
||||||
},
|
},
|
||||||
|
// Rename a tag...
|
||||||
|
//
|
||||||
|
// Rename tag...
|
||||||
|
// .rename(from, to)
|
||||||
|
// -> this
|
||||||
|
//
|
||||||
|
// Rename a tag in list of tags...
|
||||||
|
// .rename(from, to, tag, ...)
|
||||||
|
// .rename(from, to, [tag, ...])
|
||||||
|
// -> tags
|
||||||
|
//
|
||||||
|
// NOTE: if to is '' this will remove all occurrences of from.
|
||||||
|
// NOTE: if any renamed tag is renamed to '' it will be removed
|
||||||
|
// untagging all relevant values...
|
||||||
|
//
|
||||||
|
// XXX need to sanitize tag -- it can not contain regex characters...
|
||||||
|
// ...should we guard against this???
|
||||||
|
rename: function(tag, to, ...tags){
|
||||||
|
var that = this
|
||||||
|
|
||||||
|
// XXX should we be more pedantic here???
|
||||||
|
tag = this.normalize(tag)
|
||||||
|
if(tag == ''){
|
||||||
|
throw new Error(`.rename(..): first argument can not be an empty string.`) }
|
||||||
|
if(/[:\\\/]/.test(tag)){
|
||||||
|
throw new Error(
|
||||||
|
`.rename(..): only support singular tag renaming, got: "${tag}"`) }
|
||||||
|
// XXX too strict???
|
||||||
|
if(!/^[a-z0-9]+$/.test(tag)){
|
||||||
|
throw new Error(
|
||||||
|
`.rename(..): first argument must be a valid single tag, got: "${tag}"`) }
|
||||||
|
|
||||||
|
to = this.normalize(to)
|
||||||
|
if(/[\\\/]/.test(to)){
|
||||||
|
throw new Error(
|
||||||
|
`.rename(..): only support tags and tag sets as renaming target, got: "${to}"`) }
|
||||||
|
|
||||||
|
// prepare for the replacement...
|
||||||
|
var pattern = new RegExp(
|
||||||
|
`(^|[${this.SET_SEPARATOR}\\${this.PATH_SEPARATOR}])`
|
||||||
|
+`${tag}`
|
||||||
|
+`(?=$|[${this.SET_SEPARATOR}\\${this.PATH_SEPARATOR}])`, 'g')
|
||||||
|
var target = `$1${to}`
|
||||||
|
|
||||||
|
return this.replace(tag,
|
||||||
|
function(from){
|
||||||
|
return from.replace(pattern, target) }, ...tags)
|
||||||
|
},
|
||||||
// NOTE: this is a short hand to .rename(tag, '', ..) for extra
|
// NOTE: this is a short hand to .rename(tag, '', ..) for extra
|
||||||
// docs see that...
|
// docs see that...
|
||||||
removeTag: function(tag, ...tags){
|
removeTag: function(tag, ...tags){
|
||||||
@ -2010,17 +1980,6 @@ var TagsWithHandlersPrototype = {
|
|||||||
return object.parent(TagsWithHandlersPrototype.untag, this).call(this,
|
return object.parent(TagsWithHandlersPrototype.untag, this).call(this,
|
||||||
that.handleSpecialTag(tags, 'untag', value),
|
that.handleSpecialTag(tags, 'untag', value),
|
||||||
...[...arguments].slice(1)) },
|
...[...arguments].slice(1)) },
|
||||||
// handler: action(tag, 'remove')
|
|
||||||
// handler: action(to, 'rename', tag)
|
|
||||||
rename: function(tag, to, ...tags){
|
|
||||||
return object.parent(TagsWithHandlersPrototype.rename, this).call(this,
|
|
||||||
tag,
|
|
||||||
arguments.length == 2 ?
|
|
||||||
(to == '' ?
|
|
||||||
this.handleSpecialTag(tag, 'remove')
|
|
||||||
: this.handleSpecialTag(to, 'rename', tag))
|
|
||||||
: to,
|
|
||||||
...[...arguments].slice(2)) },
|
|
||||||
// handler: action(tag, 'replace', from)
|
// handler: action(tag, 'replace', from)
|
||||||
replace: function(tag, to, ...tags){
|
replace: function(tag, to, ...tags){
|
||||||
// XXX can we avoid doing this here???
|
// XXX can we avoid doing this here???
|
||||||
@ -2030,7 +1989,7 @@ var TagsWithHandlersPrototype = {
|
|||||||
}
|
}
|
||||||
return object.parent(TagsWithHandlersPrototype.replace, this).call(this,
|
return object.parent(TagsWithHandlersPrototype.replace, this).call(this,
|
||||||
tag,
|
tag,
|
||||||
arguments.length == 2 ?
|
arguments.length <= 2 ?
|
||||||
(to instanceof Function ?
|
(to instanceof Function ?
|
||||||
// wrap the handler...
|
// wrap the handler...
|
||||||
function(tag){
|
function(tag){
|
||||||
@ -2112,11 +2071,17 @@ var TagsWithDictPrototype = {
|
|||||||
//
|
//
|
||||||
normalizeSave: function(...tags){
|
normalizeSave: function(...tags){
|
||||||
var dict = this.dict = this.dict || {}
|
var dict = this.dict = this.dict || {}
|
||||||
var res = this.normalize(this.splitTag(...tags))
|
var res = this.normalize(...tags)
|
||||||
|
|
||||||
|
// unaltered tags...
|
||||||
tags = this.splitTag(normalizeSplit(tags))
|
tags = this.splitTag(normalizeSplit(tags))
|
||||||
|
// NOTE: we first split then normalize (order significant) because
|
||||||
|
// we need to conserve the order of the individual tags
|
||||||
|
// consistent with tags above...
|
||||||
|
// XXX can we avoid normalizing twice???
|
||||||
|
var names = this.normalize(this.splitTag(...tags))
|
||||||
|
|
||||||
;(res instanceof Array ? res : [res])
|
;(names instanceof Array ? names : [names])
|
||||||
.forEach(function(tag, i){
|
.forEach(function(tag, i){
|
||||||
tag = tag.trim()
|
tag = tag.trim()
|
||||||
var value = tags[i].trim()
|
var value = tags[i].trim()
|
||||||
@ -2127,7 +2092,7 @@ var TagsWithDictPrototype = {
|
|||||||
.concat([value])
|
.concat([value])
|
||||||
.unique()) })
|
.unique()) })
|
||||||
|
|
||||||
return res
|
return res
|
||||||
},
|
},
|
||||||
|
|
||||||
// Translate normalized tag to the dict form...
|
// Translate normalized tag to the dict form...
|
||||||
@ -2218,15 +2183,6 @@ var TagsWithDictPrototype = {
|
|||||||
this.removeOrphansFromDict(tags)
|
this.removeOrphansFromDict(tags)
|
||||||
return res
|
return res
|
||||||
},
|
},
|
||||||
rename: function(from, to, ...tags){
|
|
||||||
|
|
||||||
var res = object.parent(TagsWithDictPrototype.rename, this).call(this, ...arguments)
|
|
||||||
|
|
||||||
arguments.length == 2
|
|
||||||
&& this.normalizeSave(to)
|
|
||||||
this.removeOrphansFromDict(from)
|
|
||||||
return res
|
|
||||||
},
|
|
||||||
replace: function(tag, to, ...tags){
|
replace: function(tag, to, ...tags){
|
||||||
// XXX can we avoid doing this here???
|
// XXX can we avoid doing this here???
|
||||||
if(tag instanceof Function){
|
if(tag instanceof Function){
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user