Support for implicit sorting specs - refined priorities of implicit vs explicit rules
- new unit tests cover the changes
This commit is contained in:
parent
76ee3dfa62
commit
24af493734
|
@ -3,6 +3,7 @@ import {FolderWildcardMatching} from './folder-matching-rules'
|
|||
type SortingSpec = string
|
||||
|
||||
const checkIfImplicitSpec = (s: SortingSpec) => false
|
||||
const checkIfImplicitSpecByPrefix = (s: SortingSpec) => s.startsWith('implicit:')
|
||||
|
||||
const createMockMatcherRichVersion = (): FolderWildcardMatching<SortingSpec> => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
|
@ -116,6 +117,13 @@ describe('folderMatch', () => {
|
|||
|
||||
expect(result).toEqual({errorMsg: "Duplicate wildcard '...' specification for /Archive/2020/.../"})
|
||||
})
|
||||
it('should accept duplicate match children definitions for same path, if the former comes from implicit spec', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpecByPrefix)
|
||||
matcher.addWildcardDefinition('Archive/2020/...', 'implicit: First occurrence')
|
||||
const result = matcher.addWildcardDefinition('/Archive/2020/.../', 'Duplicate')
|
||||
|
||||
expect(result).toBeUndefined()
|
||||
})
|
||||
it('should detect duplicate match all definitions for same path', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addWildcardDefinition('/Archive/2019/*', 'First occurrence')
|
||||
|
@ -123,6 +131,13 @@ describe('folderMatch', () => {
|
|||
|
||||
expect(result).toEqual({errorMsg: "Duplicate wildcard '*' specification for Archive/2019/*"})
|
||||
})
|
||||
it('should accept duplicate match all definitions for same path, if the former comes from implicit spec', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpecByPrefix)
|
||||
matcher.addWildcardDefinition('/Archive/2019/*', 'implicit: First occurrence')
|
||||
const result = matcher.addWildcardDefinition('Archive/2019/*', 'Duplicate')
|
||||
|
||||
expect(result).toBeUndefined()
|
||||
})
|
||||
it('regexp-match by name works (order of regexp doesn\'t matter) case A', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addRegexpDefinition(/^daily$/, false, undefined, false, `r1`)
|
||||
|
|
|
@ -1415,6 +1415,13 @@ const txtInputTargetFolderMultiSpecD: string = `
|
|||
target-folder: ./*
|
||||
`
|
||||
|
||||
const txtInputTargetFolderMultiSpecD_implicitCase: string = `
|
||||
// typically implicit specs come context-free, no notion of current folder, that's why using explicit target-folder path
|
||||
target-folder: mock-folder/*
|
||||
// Reverse order to distinguish between implicit and explicit spec
|
||||
> a-z
|
||||
`
|
||||
|
||||
const expectedSortSpecForMultiSpecD: { [key: string]: CustomSortSpec } = {
|
||||
'mock-folder': {
|
||||
groups: [{
|
||||
|
@ -1426,6 +1433,19 @@ const expectedSortSpecForMultiSpecD: { [key: string]: CustomSortSpec } = {
|
|||
}
|
||||
}
|
||||
|
||||
const expectedSortSpecForMultiSpecD_implicitCase: { [key: string]: CustomSortSpec } = {
|
||||
'mock-folder': {
|
||||
defaultOrder: CustomSortOrder.alphabeticalReverse,
|
||||
groups: [{
|
||||
order: CustomSortOrder.alphabeticalReverse,
|
||||
type: CustomSortGroupType.Outsiders
|
||||
}],
|
||||
outsidersGroupIdx: 0,
|
||||
targetFoldersPaths: ['mock-folder/*'],
|
||||
implicit: true
|
||||
}
|
||||
}
|
||||
|
||||
const expectedWildcardMatchingTreeForMultiSpecD: FolderMatchingTreeNode<CustomSortSpec> = {
|
||||
subtree: {
|
||||
"mock-folder": {
|
||||
|
@ -1443,10 +1463,36 @@ const expectedWildcardMatchingTreeForMultiSpecD: FolderMatchingTreeNode<CustomSo
|
|||
}
|
||||
}
|
||||
|
||||
const expectedWildcardMatchingTreeForMultiSpecD_implicitCase: FolderMatchingTreeNode<CustomSortSpec> = {
|
||||
subtree: {
|
||||
"mock-folder": {
|
||||
matchAll: {
|
||||
defaultOrder: CustomSortOrder.alphabeticalReverse,
|
||||
"groups": [{
|
||||
"order": CustomSortOrder.alphabeticalReverse,
|
||||
"type": CustomSortGroupType.Outsiders
|
||||
}],
|
||||
"outsidersGroupIdx": 0,
|
||||
"targetFoldersPaths": ["mock-folder/*"],
|
||||
implicit: true
|
||||
},
|
||||
name: "mock-folder",
|
||||
subtree: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const txtInputTargetFolderMultiSpecE: string = `
|
||||
target-folder: mock-folder/...
|
||||
`
|
||||
|
||||
const txtInputTargetFolderMultiSpecE_implicitCase: string = `
|
||||
// typically implicit specs come context-free, no notion of current folder, that's why using explicit target-folder path
|
||||
target-folder: mock-folder/...
|
||||
// Reverse order to distinguish between implicit and explicit spec
|
||||
> a-z
|
||||
`
|
||||
|
||||
const expectedSortSpecForMultiSpecE: { [key: string]: CustomSortSpec } = {
|
||||
'mock-folder': {
|
||||
groups: [{
|
||||
|
@ -1458,6 +1504,19 @@ const expectedSortSpecForMultiSpecE: { [key: string]: CustomSortSpec } = {
|
|||
}
|
||||
}
|
||||
|
||||
const expectedSortSpecForMultiSpecE_implicitCase: { [key: string]: CustomSortSpec } = {
|
||||
'mock-folder': {
|
||||
defaultOrder: CustomSortOrder.alphabeticalReverse,
|
||||
groups: [{
|
||||
order: CustomSortOrder.alphabeticalReverse,
|
||||
type: CustomSortGroupType.Outsiders
|
||||
}],
|
||||
outsidersGroupIdx: 0,
|
||||
targetFoldersPaths: ['mock-folder/...'],
|
||||
implicit: true
|
||||
}
|
||||
}
|
||||
|
||||
const expectedWildcardMatchingTreeForMultiSpecE: FolderMatchingTreeNode<CustomSortSpec> = {
|
||||
subtree: {
|
||||
"mock-folder": {
|
||||
|
@ -1475,6 +1534,72 @@ const expectedWildcardMatchingTreeForMultiSpecE: FolderMatchingTreeNode<CustomSo
|
|||
}
|
||||
}
|
||||
|
||||
const expectedWildcardMatchingTreeForMultiSpecE_implicitCase: FolderMatchingTreeNode<CustomSortSpec> = {
|
||||
subtree: {
|
||||
"mock-folder": {
|
||||
matchChildren: {
|
||||
defaultOrder: CustomSortOrder.alphabeticalReverse,
|
||||
"groups": [{
|
||||
"order": CustomSortOrder.alphabeticalReverse,
|
||||
"type": CustomSortGroupType.Outsiders
|
||||
}],
|
||||
"outsidersGroupIdx": 0,
|
||||
"targetFoldersPaths": ["mock-folder/..."],
|
||||
implicit: true
|
||||
},
|
||||
name: "mock-folder",
|
||||
subtree: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const expectedWildcardMatchingTreeForMultiSpecDplusE_implicitCase: FolderMatchingTreeNode<CustomSortSpec> = {
|
||||
subtree: {
|
||||
"mock-folder": {
|
||||
matchAll: {
|
||||
"groups": [{
|
||||
"order": CustomSortOrder.alphabetical,
|
||||
"type": CustomSortGroupType.Outsiders
|
||||
}],
|
||||
"outsidersGroupIdx": 0,
|
||||
"targetFoldersPaths": ["mock-folder/*"]
|
||||
},
|
||||
matchChildren: {
|
||||
defaultOrder: CustomSortOrder.alphabeticalReverse,
|
||||
"groups": [{
|
||||
"order": CustomSortOrder.alphabeticalReverse,
|
||||
"type": CustomSortGroupType.Outsiders
|
||||
}],
|
||||
"outsidersGroupIdx": 0,
|
||||
"targetFoldersPaths": ["mock-folder/..."],
|
||||
implicit: true
|
||||
},
|
||||
name: "mock-folder",
|
||||
subtree: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const txtInputTargetFolderMultiSpecF_implicitCase: string = `
|
||||
// typically implicit specs come context-free, no notion of current folder, that's why using explicit target-folder path
|
||||
target-folder: mock-folder
|
||||
// Reverse order to distinguish between implicit and explicit spec
|
||||
> a-z
|
||||
`
|
||||
|
||||
const expectedSortSpecForMultiSpecF_implicitCase: { [key: string]: CustomSortSpec } = {
|
||||
'mock-folder': {
|
||||
defaultOrder: CustomSortOrder.alphabeticalReverse,
|
||||
groups: [{
|
||||
order: CustomSortOrder.alphabeticalReverse,
|
||||
type: CustomSortGroupType.Outsiders
|
||||
}],
|
||||
outsidersGroupIdx: 0,
|
||||
targetFoldersPaths: ['mock-folder'],
|
||||
implicit: true
|
||||
}
|
||||
}
|
||||
|
||||
describe('SortingSpecProcessor path wildcard priorities', () => {
|
||||
let processor: SortingSpecProcessor;
|
||||
beforeEach(() => {
|
||||
|
@ -1504,12 +1629,52 @@ describe('SortingSpecProcessor path wildcard priorities', () => {
|
|||
expect(result?.sortSpecByPath).toEqual(expectedSortSpecForMultiSpecD)
|
||||
expect(result?.sortSpecByWildcard?.tree).toEqual(expectedWildcardMatchingTreeForMultiSpecD)
|
||||
})
|
||||
it('should not raise error for multiple spec for the same path and choose correct spec, case D - with implicit spec', () => {
|
||||
const inputTxtArrImplicit: Array<string> = txtInputTargetFolderMultiSpecD_implicitCase.split('\n')
|
||||
const resultImplicit = processor.parseSortSpecFromText(inputTxtArrImplicit, 'implicit ignored param', 'implicit ignored param', null, true)
|
||||
expect(resultImplicit?.sortSpecByPath).toEqual(expectedSortSpecForMultiSpecD_implicitCase)
|
||||
expect(resultImplicit?.sortSpecByWildcard?.tree).toEqual(expectedWildcardMatchingTreeForMultiSpecD_implicitCase)
|
||||
const inputTxtArrExplicit: Array<string> = txtInputTargetFolderMultiSpecD.split('\n')
|
||||
const result = processor.parseSortSpecFromText(inputTxtArrExplicit, 'mock-folder', 'custom-name-note.md', resultImplicit)
|
||||
expect(result?.sortSpecByPath).toEqual(expectedSortSpecForMultiSpecD)
|
||||
expect(result?.sortSpecByWildcard?.tree).toEqual(expectedWildcardMatchingTreeForMultiSpecD)
|
||||
})
|
||||
it('should not raise error for multiple spec for the same path and choose correct spec, case E', () => {
|
||||
const inputTxtArr: Array<string> = txtInputTargetFolderMultiSpecE.split('\n')
|
||||
const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
|
||||
expect(result?.sortSpecByPath).toEqual(expectedSortSpecForMultiSpecE)
|
||||
expect(result?.sortSpecByWildcard?.tree).toEqual(expectedWildcardMatchingTreeForMultiSpecE)
|
||||
})
|
||||
it('should not raise error for multiple spec for the same path and choose correct spec, case E - with implicit spec', () => {
|
||||
const inputTxtArrImplicit: Array<string> = txtInputTargetFolderMultiSpecE_implicitCase.split('\n')
|
||||
const resultImplicit = processor.parseSortSpecFromText(inputTxtArrImplicit, 'implicit ignored param', 'implicit ignored param', null, true)
|
||||
expect(resultImplicit?.sortSpecByPath).toEqual(expectedSortSpecForMultiSpecE_implicitCase)
|
||||
expect(resultImplicit?.sortSpecByWildcard?.tree).toEqual(expectedWildcardMatchingTreeForMultiSpecE_implicitCase)
|
||||
const inputTxtArrExplicit: Array<string> = txtInputTargetFolderMultiSpecE.split('\n')
|
||||
const result = processor.parseSortSpecFromText(inputTxtArrExplicit, 'mock-folder', 'custom-name-note.md', resultImplicit)
|
||||
expect(result?.sortSpecByPath).toEqual(expectedSortSpecForMultiSpecE)
|
||||
expect(result?.sortSpecByWildcard?.tree).toEqual(expectedWildcardMatchingTreeForMultiSpecE)
|
||||
})
|
||||
it('should not raise error for multiple spec for the same path and choose correct spec, mixed case D+E - with implicit spec, which looses all', () => {
|
||||
const inputTxtArrImplicit: Array<string> = txtInputTargetFolderMultiSpecE_implicitCase.split('\n')
|
||||
const resultImplicit = processor.parseSortSpecFromText(inputTxtArrImplicit, 'implicit ignored param', 'implicit ignored param', null, true)
|
||||
expect(resultImplicit?.sortSpecByPath).toEqual(expectedSortSpecForMultiSpecE_implicitCase)
|
||||
expect(resultImplicit?.sortSpecByWildcard?.tree).toEqual(expectedWildcardMatchingTreeForMultiSpecE_implicitCase)
|
||||
const inputTxtArrExplicit: Array<string> = txtInputTargetFolderMultiSpecD.split('\n')
|
||||
const result = processor.parseSortSpecFromText(inputTxtArrExplicit, 'mock-folder', 'custom-name-note.md', resultImplicit)
|
||||
expect(result?.sortSpecByPath).toEqual(expectedSortSpecForMultiSpecD)
|
||||
expect(result?.sortSpecByWildcard?.tree).toEqual(expectedWildcardMatchingTreeForMultiSpecDplusE_implicitCase)
|
||||
})
|
||||
it('should not raise error for multiple spec for the same path and choose correct spec, mixed case E+F => implicit by name', () => {
|
||||
const inputTxtArrImplicit: Array<string> = txtInputTargetFolderMultiSpecF_implicitCase.split('\n')
|
||||
const resultImplicit = processor.parseSortSpecFromText(inputTxtArrImplicit, 'implicit ignored param', 'implicit ignored param', null, true)
|
||||
expect(resultImplicit?.sortSpecByPath).toEqual(expectedSortSpecForMultiSpecF_implicitCase)
|
||||
expect(resultImplicit?.sortSpecByWildcard?.tree).toBeUndefined()
|
||||
const inputTxtArrExplicit: Array<string> = txtInputTargetFolderMultiSpecE.split('\n')
|
||||
const result = processor.parseSortSpecFromText(inputTxtArrExplicit, 'mock-folder', 'custom-name-note.md', resultImplicit)
|
||||
expect(result?.sortSpecByPath).toEqual(expectedSortSpecForMultiSpecF_implicitCase)
|
||||
expect(result?.sortSpecByWildcard?.tree).toEqual(expectedWildcardMatchingTreeForMultiSpecE)
|
||||
})
|
||||
})
|
||||
|
||||
const txtInputAdvancedFolderDateSortingMethods: string = `
|
||||
|
|
|
@ -601,12 +601,18 @@ const endsWithWildcardPatternSuffix = (path: string): boolean => {
|
|||
path.endsWith(MATCH_ALL_SUFFIX)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Important note:
|
||||
even if the actual enum labels seem to be unused thus unneeded, their numerical values (implied by the order below) matter.
|
||||
They define the priorities of the rules for wilcard target-folder specs. The rule with higher priority overrides the one with lower
|
||||
*/
|
||||
enum WildcardPriority {
|
||||
NO_WILDCARD = 1,
|
||||
NO_WILDCARD_IMPLICIT,
|
||||
MATCH_CHILDREN,
|
||||
MATCH_CHILDREN_IMPLICIT,
|
||||
MATCH_ALL,
|
||||
MATCH_CHILDREN_IMPLICIT,
|
||||
MATCH_ALL_IMPLICIT
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue