Comparing version 0.1.27 to 0.1.28
@@ -9,2 +9,3 @@ import { Segments, Node, Pattern } from './types'; | ||
haveExcludePattern: boolean; | ||
matchScore: number; | ||
tree: Node; | ||
@@ -32,3 +33,3 @@ private matchCache; | ||
match: (pattern: Pattern) => boolean; | ||
matchAliasGroup: (...patterns: Pattern[]) => boolean; | ||
matchAliasGroup: (name: Pattern, alias: Pattern) => boolean; | ||
existIn: (source?: any, start?: number | Path) => boolean; | ||
@@ -35,0 +36,0 @@ getIn: (source?: any) => any; |
@@ -261,4 +261,8 @@ "use strict"; | ||
var cache = _this.matchCache.get(path.entire); | ||
if (cache !== undefined) | ||
return cache; | ||
if (cache !== undefined) { | ||
if (cache.record && cache.record.score !== undefined) { | ||
_this.matchScore = cache.record.score; | ||
} | ||
return cache.matched; | ||
} | ||
var cacheWith = function (value) { | ||
@@ -273,2 +277,3 @@ _this.matchCache.set(path.entire, value); | ||
else { | ||
_this.matchScore = 0; | ||
return cacheWith(path.match(_this.segments)); | ||
@@ -279,17 +284,37 @@ } | ||
if (_this.isMatchPattern) { | ||
return cacheWith(new matcher_1.Matcher(_this.tree).match(path.segments)); | ||
var record = { | ||
score: 0 | ||
}; | ||
var result = cacheWith(new matcher_1.Matcher(_this.tree, record).match(path.segments)); | ||
_this.matchScore = record.score; | ||
return result.matched; | ||
} | ||
else { | ||
return cacheWith(matcher_1.Matcher.matchSegments(_this.segments, path.segments)); | ||
var record = { | ||
score: 0 | ||
}; | ||
var result = cacheWith(matcher_1.Matcher.matchSegments(_this.segments, path.segments, record)); | ||
_this.matchScore = record.score; | ||
return result.matched; | ||
} | ||
} | ||
}; | ||
this.matchAliasGroup = function () { | ||
var patterns = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
patterns[_i] = arguments[_i]; | ||
this.matchAliasGroup = function (name, alias) { | ||
var namePath = Path.parse(name); | ||
var aliasPath = Path.parse(alias); | ||
var nameMatched = _this.match(namePath); | ||
var nameMatchedScore = _this.matchScore; | ||
var aliasMatched = _this.match(aliasPath); | ||
var aliasMatchedScore = _this.matchScore; | ||
if (_this.haveExcludePattern) { | ||
if (nameMatchedScore >= aliasMatchedScore) { | ||
return nameMatched; | ||
} | ||
else { | ||
return aliasMatched; | ||
} | ||
} | ||
if (patterns.length === 0) | ||
return false; | ||
return patterns.some(function (pattern) { return _this.match(pattern); }); | ||
else { | ||
return nameMatched || aliasMatched; | ||
} | ||
}; | ||
@@ -296,0 +321,0 @@ this.existIn = function (source, start) { |
@@ -8,5 +8,7 @@ import { Segments, Node, IdentifierNode, IgnoreExpressionNode, DestructorExpressionNode, ExpandOperatorNode, WildcardOperatorNode, GroupExpressionNode, RangeExpressionNode, DotOperatorNode } from './types'; | ||
private excluding; | ||
constructor(tree: Node); | ||
private record; | ||
constructor(tree: Node, record?: any); | ||
currentElement(path: Segments): string; | ||
matchNext: (node: any, path: any) => any; | ||
recordMatch(match: () => boolean): () => boolean; | ||
matchIdentifier(path: Segments, node: IdentifierNode): any; | ||
@@ -21,4 +23,13 @@ matchIgnoreExpression(path: Segments, node: IgnoreExpressionNode): any; | ||
matchAtom(path: Segments, node: Node): any; | ||
match(path: Segments): any; | ||
static matchSegments(source: Segments, target: Segments): any; | ||
match(path: Segments): { | ||
matched: boolean; | ||
record?: undefined; | ||
} | { | ||
matched: any; | ||
record: any; | ||
}; | ||
static matchSegments(source: Segments, target: Segments, record?: any): false | { | ||
matched: any; | ||
record: any; | ||
}; | ||
} |
@@ -7,3 +7,3 @@ "use strict"; | ||
var Matcher = (function () { | ||
function Matcher(tree) { | ||
function Matcher(tree, record) { | ||
var _this = this; | ||
@@ -18,2 +18,3 @@ this.matchNext = function (node, path) { | ||
this.excluding = false; | ||
this.record = record; | ||
this.stack = []; | ||
@@ -24,2 +25,14 @@ } | ||
}; | ||
Matcher.prototype.recordMatch = function (match) { | ||
var _this = this; | ||
return function () { | ||
var result = match(); | ||
if (result) { | ||
if (_this.record && _this.record.score !== undefined) { | ||
_this.record.score++; | ||
} | ||
} | ||
return result; | ||
}; | ||
}; | ||
Matcher.prototype.matchIdentifier = function (path, node) { | ||
@@ -45,12 +58,31 @@ var _this = this; | ||
if (types_1.isExpandOperator(node.after)) { | ||
current = function () { | ||
current = this.recordMatch(function () { | ||
return node.value === String(path[_this.pos]).substring(0, node.value.length); | ||
}; | ||
}); | ||
} | ||
else { | ||
current = function () { return utils_1.isEqual(String(node.value), String(path[_this.pos])); }; | ||
current = this.recordMatch(function () { | ||
return utils_1.isEqual(String(node.value), String(path[_this.pos])); | ||
}); | ||
} | ||
return this.excluding | ||
? isValid(path[this.pos]) && !current() | ||
: current() && next(); | ||
if (this.excluding) { | ||
if (node.after) { | ||
if (this.pos < path.length) { | ||
return current() && next(); | ||
} | ||
else { | ||
if (node.after && types_1.isWildcardOperator(node.after.after)) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
} | ||
else { | ||
if (this.pos >= path.length) { | ||
return true; | ||
} | ||
return current(); | ||
} | ||
} | ||
return current() && next(); | ||
}; | ||
@@ -94,3 +126,5 @@ Matcher.prototype.matchIgnoreExpression = function (path, node) { | ||
_this.pos = current; | ||
return _this.matchAtom(path, _node); | ||
return _this.excluding | ||
? !_this.matchAtom(path, _node) | ||
: _this.matchAtom(path, _node); | ||
}); | ||
@@ -107,3 +141,3 @@ this.excluding = false; | ||
else { | ||
return (path[this.pos] >= parseInt(node.start.value)); | ||
return path[this.pos] >= parseInt(node.start.value); | ||
} | ||
@@ -113,3 +147,3 @@ } | ||
if (node.end) { | ||
return (path[this.pos] <= parseInt(node.end.value)); | ||
return path[this.pos] <= parseInt(node.end.value); | ||
} | ||
@@ -163,9 +197,9 @@ else { | ||
if (!this.tail) | ||
return false; | ||
return { matched: false }; | ||
if (this.tail == this.tree && types_1.isWildcardOperator(this.tail)) { | ||
return true; | ||
return { matched: true }; | ||
} | ||
return matched; | ||
return { matched: matched, record: this.record }; | ||
}; | ||
Matcher.matchSegments = function (source, target) { | ||
Matcher.matchSegments = function (source, target, record) { | ||
var pos = 0; | ||
@@ -175,7 +209,13 @@ if (source.length !== target.length) | ||
var match = function (pos) { | ||
var current = function () { return utils_1.isEqual(source[pos], target[pos]); }; | ||
var current = function () { | ||
var res = utils_1.isEqual(source[pos], target[pos]); | ||
if (record && record.score !== undefined) { | ||
record.score++; | ||
} | ||
return res; | ||
}; | ||
var next = function () { return (pos < source.length - 1 ? match(pos + 1) : true); }; | ||
return current() && next(); | ||
}; | ||
return match(pos); | ||
return { matched: match(pos), record: record }; | ||
}; | ||
@@ -182,0 +222,0 @@ return Matcher; |
{ | ||
"name": "cool-path", | ||
"version": "0.1.27", | ||
"version": "0.1.28", | ||
"description": "Path Matcher/Getter/Setter for Object/Array", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -139,2 +139,3 @@ import { Parser } from './parser' | ||
public haveExcludePattern: boolean | ||
public matchScore: number | ||
public tree: Node | ||
@@ -385,4 +386,9 @@ private matchCache: any | ||
const cache = this.matchCache.get(path.entire) | ||
if (cache !== undefined) return cache | ||
const cacheWith = (value: boolean): boolean => { | ||
if (cache !== undefined) { | ||
if (cache.record && cache.record.score !== undefined) { | ||
this.matchScore = cache.record.score | ||
} | ||
return cache.matched | ||
} | ||
const cacheWith = (value: any) => { | ||
this.matchCache.set(path.entire, value) | ||
@@ -395,2 +401,3 @@ return value | ||
} else { | ||
this.matchScore = 0 | ||
return cacheWith(path.match(this.segments)) | ||
@@ -400,5 +407,19 @@ } | ||
if (this.isMatchPattern) { | ||
return cacheWith(new Matcher(this.tree).match(path.segments)) | ||
const record = { | ||
score: 0 | ||
} | ||
const result = cacheWith( | ||
new Matcher(this.tree, record).match(path.segments) | ||
) | ||
this.matchScore = record.score | ||
return result.matched | ||
} else { | ||
return cacheWith(Matcher.matchSegments(this.segments, path.segments)) | ||
const record = { | ||
score: 0 | ||
} | ||
const result = cacheWith( | ||
Matcher.matchSegments(this.segments, path.segments, record) | ||
) | ||
this.matchScore = record.score | ||
return result.matched | ||
} | ||
@@ -409,5 +430,18 @@ } | ||
//别名组匹配 | ||
matchAliasGroup = (...patterns: Pattern[]) => { | ||
if (patterns.length === 0) return false | ||
return patterns.some(pattern => this.match(pattern)) | ||
matchAliasGroup = (name: Pattern, alias: Pattern) => { | ||
const namePath = Path.parse(name) | ||
const aliasPath = Path.parse(alias) | ||
const nameMatched = this.match(namePath) | ||
const nameMatchedScore = this.matchScore | ||
const aliasMatched = this.match(aliasPath) | ||
const aliasMatchedScore = this.matchScore | ||
if (this.haveExcludePattern) { | ||
if (nameMatchedScore >= aliasMatchedScore) { | ||
return nameMatched | ||
} else { | ||
return aliasMatched | ||
} | ||
} else { | ||
return nameMatched || aliasMatched | ||
} | ||
} | ||
@@ -414,0 +448,0 @@ |
@@ -36,6 +36,9 @@ import { | ||
constructor(tree: Node) { | ||
private record: any | ||
constructor(tree: Node, record?: any) { | ||
this.tree = tree | ||
this.pos = 0 | ||
this.excluding = false | ||
this.record = record | ||
this.stack = [] | ||
@@ -54,2 +57,14 @@ } | ||
recordMatch(match: () => boolean) { | ||
return () => { | ||
const result = match() | ||
if (result) { | ||
if (this.record && this.record.score !== undefined) { | ||
this.record.score++ | ||
} | ||
} | ||
return result | ||
} | ||
} | ||
matchIdentifier(path: Segments, node: IdentifierNode) { | ||
@@ -74,10 +89,31 @@ this.tail = node | ||
if (isExpandOperator(node.after)) { | ||
current = () => | ||
node.value === String(path[this.pos]).substring(0, node.value.length) | ||
current = this.recordMatch( | ||
() => | ||
node.value === String(path[this.pos]).substring(0, node.value.length) | ||
) | ||
} else { | ||
current = () => isEqual(String(node.value), String(path[this.pos])) | ||
current = this.recordMatch(() => | ||
isEqual(String(node.value), String(path[this.pos])) | ||
) | ||
} | ||
return this.excluding | ||
? isValid(path[this.pos]) && !current() | ||
: current() && next() | ||
if (this.excluding) { | ||
if (node.after) { | ||
if (this.pos < path.length) { | ||
return current() && next() | ||
} else { | ||
if (node.after && isWildcardOperator(node.after.after)) { | ||
return true | ||
} | ||
return false | ||
} | ||
} else { | ||
if (this.pos >= path.length) { | ||
return true | ||
} | ||
return current() | ||
} | ||
} | ||
return current() && next() | ||
} | ||
@@ -127,3 +163,5 @@ | ||
this.pos = current | ||
return this.matchAtom(path, _node) | ||
return this.excluding | ||
? !this.matchAtom(path, _node) | ||
: this.matchAtom(path, _node) | ||
}) | ||
@@ -142,11 +180,7 @@ this.excluding = false | ||
} else { | ||
return ( | ||
path[this.pos] >= parseInt(node.start.value) | ||
) | ||
return path[this.pos] >= parseInt(node.start.value) | ||
} | ||
} else { | ||
if (node.end) { | ||
return ( | ||
path[this.pos] <= parseInt(node.end.value) | ||
) | ||
return path[this.pos] <= parseInt(node.end.value) | ||
} else { | ||
@@ -192,15 +226,21 @@ return true | ||
const matched = this.matchAtom(path, this.tree) | ||
if (!this.tail) return false | ||
if (!this.tail) return { matched: false } | ||
if (this.tail == this.tree && isWildcardOperator(this.tail)) { | ||
return true | ||
return { matched: true } | ||
} | ||
return matched | ||
return { matched, record: this.record } | ||
} | ||
static matchSegments(source: Segments, target: Segments) { | ||
static matchSegments(source: Segments, target: Segments, record?: any) { | ||
let pos = 0 | ||
if (source.length !== target.length) return false | ||
const match = (pos: number) => { | ||
const current = () => isEqual(source[pos], target[pos]) | ||
const current = () => { | ||
const res = isEqual(source[pos], target[pos]) | ||
if (record && record.score !== undefined) { | ||
record.score++ | ||
} | ||
return res | ||
} | ||
const next = () => (pos < source.length - 1 ? match(pos + 1) : true) | ||
@@ -210,4 +250,4 @@ return current() && next() | ||
return match(pos) | ||
return { matched: match(pos), record } | ||
} | ||
} |
@@ -45,5 +45,3 @@ import expect from 'expect' | ||
) | ||
expect( | ||
new Path('aa.*(!bb)').matchAliasGroup('kk.mm.aa.bb.cc', 'aa.bb.cc') | ||
).toEqual(false) | ||
expect(new Path('aa.*(!bb)').matchAliasGroup('kk.mm.aa.bb.cc')).toEqual(false) | ||
expect(new Path('aa.*(!bb,oo)').matchAliasGroup('kk.mm', 'aa')).toEqual(false) | ||
@@ -56,4 +54,40 @@ expect(new Path('aa.*(!bb.*)').matchAliasGroup('kk.mm', 'aa')).toEqual(false) | ||
expect(patttern2.matchAliasGroup(['array', 0], ['array', 0])).toEqual(false) | ||
expect(Path.parse('*(!aaa,bbb)').match('ggg')).toBeTruthy() | ||
}) | ||
test('exclude match', () => { | ||
//路径长度相等 | ||
expect(Path.parse('*(!aaa)').match('ggg')).toBeTruthy() | ||
expect(Path.parse('*(!aaa)').match('aaa')).toBeFalsy() | ||
expect(Path.parse('*(!aaa.bbb)').match('ggg.ddd')).toBeTruthy() | ||
expect(Path.parse('*(!aaa.ccc)').match('aaa.ccc')).toBeFalsy() | ||
//长路径匹配短路径 | ||
expect(Path.parse('*(!aaa.bbb)').match('ggg')).toBeTruthy() | ||
expect(Path.parse('*(!aaa.bbb)').match('aaa')).toBeFalsy() | ||
//短路径匹配长路径 | ||
expect(Path.parse('*(!aaa)').match('aaa.bbb')).toBeTruthy() | ||
expect(Path.parse('*(!aaa)').match('aaa.ccc')).toBeTruthy() | ||
expect(Path.parse('*(!aaa)').match('bbb.ccc')).toBeTruthy() | ||
expect(Path.parse('*(!aaa,bbb)').match('bbb')).toBeFalsy() | ||
expect(Path.parse('*(!aaa.bbb)').match('aaa.ccc')).toBeTruthy() | ||
expect(Path.parse('*(!basic.name,versionTag)').match('basic.id')).toBeTruthy() | ||
expect(Path.parse('*(!basic.name,versionTag)').match('basic')).toBeFalsy() | ||
expect( | ||
Path.parse('*(!basic.name,versionTag)').match('isExecutable') | ||
).toBeTruthy() | ||
expect( | ||
Path.parse('*(!basic.name,versionTag)').match('versionTag') | ||
).toBeFalsy() | ||
expect( | ||
Path.parse('*(!basic.name,basic.name.*,versionTag)').match('basic.name') | ||
).toBeFalsy() | ||
expect( | ||
Path.parse('*(!basic.name,basic.name.*,versionTag)').match('basic.name.kkk') | ||
).toBeFalsy() | ||
expect(Path.parse('aa.*(!bb)').match('kk.mm.aa.bb.cc')).toBeFalsy() | ||
expect(Path.parse('aa.*(!bb)').match('aa')).toBeFalsy() | ||
expect(Path.parse('aa.*(!bb.*)').match('aa')).toBeFalsy() | ||
expect(Path.parse('aa.*(!bb,cc)').match('aa')).toBeFalsy() | ||
expect(Path.parse('aa.*(!bb,cc)').match('aa.dd')).toBeTruthy() | ||
expect(Path.parse('aa.*(!bb,cc)').match('aa.kk')).toBeTruthy() | ||
}) | ||
@@ -124,3 +158,3 @@ | ||
'*(!aaa)': [['bbb']], | ||
'*(!aaa,bbb)': [['ccc'],['ggg']] | ||
'*(!aaa,bbb)': [['ccc'], ['ggg']] | ||
}) | ||
@@ -134,6 +168,4 @@ | ||
'*(!aaa)': [['aaa']], | ||
'dyanmic.*(!dynamic-1)': [ | ||
['dyanmic', 'dynamic-1', 'ccc'], | ||
['dyanmic', 'dynamic-1'] | ||
], | ||
'dyanmic.*(!dynamic-1)': [['dyanmic', 'dynamic-1']], | ||
'dyanmic.*(!dynamic-1.*)': [['dyanmic', 'dynamic-1', 'ccc']], | ||
a: [['c', 'b']], | ||
@@ -140,0 +172,0 @@ 'aa~.ccc': [['a', 'ccc'], ['aa'], ['aaasdd']], |
169208
5384