Refactoring of internal processing context plus support for implicit sorting specs
- !!! NO UNIT TESTS ADDED - remember to do it
This commit is contained in:
parent
45f5918598
commit
3cc58f69b9
|
@ -79,10 +79,7 @@ export interface CustomSortSpec {
|
|||
outsidersFoldersGroupIdx?: number
|
||||
itemsToHide?: Set<string>
|
||||
priorityOrder?: Array<number> // Indexes of groups in evaluation order
|
||||
|
||||
// For internal transient use
|
||||
plugin?: Plugin // to hand over the access to App instance to the sorting engine
|
||||
_mCache?: MetadataCache
|
||||
implicit?: boolean // spec applied automatically (e.g. auto integration with a plugin)
|
||||
}
|
||||
|
||||
export const DEFAULT_METADATA_FIELD_FOR_SORTING: string = 'sort-index-value'
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
sorterByMetadataField,
|
||||
SorterFn,
|
||||
getSorterFnFor,
|
||||
Sorters
|
||||
ProcessingContext
|
||||
} from './custom-sort';
|
||||
import {CustomSortGroupType, CustomSortOrder, CustomSortSpec, RegExpSpec} from './custom-sort-types';
|
||||
import {CompoundDashNumberNormalizerFn, CompoundDotRomanNumberNormalizerFn} from "./sorting-spec-processor";
|
||||
|
@ -744,7 +744,9 @@ describe('determineSortingGroup', () => {
|
|||
type: CustomSortGroupType.HasMetadataField,
|
||||
withMetadataFieldName: "metadataField1",
|
||||
exactPrefix: 'Ref'
|
||||
}],
|
||||
}]
|
||||
}
|
||||
const ctx: Partial<ProcessingContext> = {
|
||||
_mCache: {
|
||||
getCache: function (path: string): CachedMetadata | undefined {
|
||||
return {
|
||||
|
@ -760,7 +762,7 @@ describe('determineSortingGroup', () => {
|
|||
}
|
||||
|
||||
// when
|
||||
const result = determineSortingGroup(file, sortSpec)
|
||||
const result = determineSortingGroup(file, sortSpec, ctx as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -781,7 +783,9 @@ describe('determineSortingGroup', () => {
|
|||
type: CustomSortGroupType.HasMetadataField,
|
||||
withMetadataFieldName: "metadataField1",
|
||||
exactPrefix: 'Ref'
|
||||
}],
|
||||
}]
|
||||
}
|
||||
const ctx: Partial<ProcessingContext> = {
|
||||
_mCache: {
|
||||
getCache: function (path: string): CachedMetadata | undefined {
|
||||
return {
|
||||
|
@ -797,7 +801,7 @@ describe('determineSortingGroup', () => {
|
|||
}
|
||||
|
||||
// when
|
||||
const result = determineSortingGroup(file, sortSpec)
|
||||
const result = determineSortingGroup(file, sortSpec, ctx as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -818,7 +822,9 @@ describe('determineSortingGroup', () => {
|
|||
type: CustomSortGroupType.HasMetadataField,
|
||||
withMetadataFieldName: "metadataField1",
|
||||
exactPrefix: 'Ref'
|
||||
}],
|
||||
}]
|
||||
}
|
||||
const ctx: Partial<ProcessingContext> = {
|
||||
_mCache: {
|
||||
getCache: function (path: string): CachedMetadata | undefined {
|
||||
return {
|
||||
|
@ -834,7 +840,7 @@ describe('determineSortingGroup', () => {
|
|||
}
|
||||
|
||||
// when
|
||||
const result = determineSortingGroup(file, sortSpec)
|
||||
const result = determineSortingGroup(file, sortSpec, ctx as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -855,7 +861,9 @@ describe('determineSortingGroup', () => {
|
|||
type: CustomSortGroupType.HasMetadataField,
|
||||
withMetadataFieldName: "metadataField1",
|
||||
exactPrefix: 'Ref'
|
||||
}],
|
||||
}]
|
||||
}
|
||||
const ctx: Partial<ProcessingContext> = {
|
||||
_mCache: {
|
||||
getCache: function (path: string): CachedMetadata | undefined {
|
||||
return {
|
||||
|
@ -871,7 +879,7 @@ describe('determineSortingGroup', () => {
|
|||
}
|
||||
|
||||
// when
|
||||
const result = determineSortingGroup(folder, sortSpec)
|
||||
const result = determineSortingGroup(folder, sortSpec, ctx as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -904,7 +912,7 @@ describe('determineSortingGroup', () => {
|
|||
// when
|
||||
const result = determineSortingGroup(file, sortSpec, {
|
||||
starredPluginInstance: starredPluginInstance as Starred_PluginInstance
|
||||
})
|
||||
} as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -935,7 +943,7 @@ describe('determineSortingGroup', () => {
|
|||
// when
|
||||
const result = determineSortingGroup(file, sortSpec, {
|
||||
starredPluginInstance: starredPluginInstance as Starred_PluginInstance
|
||||
})
|
||||
} as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -966,7 +974,7 @@ describe('determineSortingGroup', () => {
|
|||
// when
|
||||
const result = determineSortingGroup(folder, sortSpec, {
|
||||
starredPluginInstance: starredPluginInstance as Starred_PluginInstance
|
||||
})
|
||||
} as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1005,7 +1013,7 @@ describe('determineSortingGroup', () => {
|
|||
// when
|
||||
const result = determineSortingGroup(folder, sortSpec, {
|
||||
starredPluginInstance: starredPluginInstance as Starred_PluginInstance
|
||||
})
|
||||
} as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1044,7 +1052,7 @@ describe('determineSortingGroup', () => {
|
|||
// when
|
||||
const result = determineSortingGroup(folder, sortSpec, {
|
||||
starredPluginInstance: starredPluginInstance as Starred_PluginInstance
|
||||
})
|
||||
} as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1086,7 +1094,7 @@ describe('determineSortingGroup', () => {
|
|||
// when
|
||||
const result = determineSortingGroup(file, sortSpec, {
|
||||
iconFolderPluginInstance: obsidianIconFolderPluginInstance as ObsidianIconFolder_PluginInstance
|
||||
})
|
||||
} as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1121,7 +1129,7 @@ describe('determineSortingGroup', () => {
|
|||
// when
|
||||
const result = determineSortingGroup(file, sortSpec, {
|
||||
iconFolderPluginInstance: obsidianIconFolderPluginInstance as ObsidianIconFolder_PluginInstance
|
||||
})
|
||||
} as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1155,7 +1163,7 @@ describe('determineSortingGroup', () => {
|
|||
// when
|
||||
const result = determineSortingGroup(file, sortSpec, {
|
||||
iconFolderPluginInstance: obsidianIconFolderPluginInstance as ObsidianIconFolder_PluginInstance
|
||||
})
|
||||
} as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1190,7 +1198,7 @@ describe('determineSortingGroup', () => {
|
|||
// when
|
||||
const result = determineSortingGroup(file, sortSpec, {
|
||||
iconFolderPluginInstance: obsidianIconFolderPluginInstance as ObsidianIconFolder_PluginInstance
|
||||
})
|
||||
} as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1221,7 +1229,7 @@ describe('determineSortingGroup', () => {
|
|||
// when
|
||||
const result = determineSortingGroup(folder, sortSpec, {
|
||||
iconFolderPluginInstance: obsidianIconFolderPluginInstance as ObsidianIconFolder_PluginInstance
|
||||
})
|
||||
} as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1263,7 +1271,7 @@ describe('determineSortingGroup', () => {
|
|||
// when
|
||||
const result = determineSortingGroup(folder, sortSpec, {
|
||||
iconFolderPluginInstance: obsidianIconFolderPluginInstance as ObsidianIconFolder_PluginInstance
|
||||
})
|
||||
} as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1308,7 +1316,7 @@ describe('determineSortingGroup', () => {
|
|||
// when
|
||||
const result = determineSortingGroup(folder, sortSpec, {
|
||||
iconFolderPluginInstance: obsidianIconFolderPluginInstance as ObsidianIconFolder_PluginInstance
|
||||
})
|
||||
} as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1351,7 +1359,7 @@ describe('determineSortingGroup', () => {
|
|||
// when
|
||||
const result = determineSortingGroup(folder, sortSpec, {
|
||||
iconFolderPluginInstance: obsidianIconFolderPluginInstance as ObsidianIconFolder_PluginInstance
|
||||
})
|
||||
} as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1397,7 +1405,7 @@ describe('determineSortingGroup', () => {
|
|||
// when
|
||||
const result = determineSortingGroup(folder, sortSpec, {
|
||||
iconFolderPluginInstance: obsidianIconFolderPluginInstance as ObsidianIconFolder_PluginInstance
|
||||
})
|
||||
} as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1440,7 +1448,7 @@ describe('determineSortingGroup', () => {
|
|||
// when
|
||||
const result = determineSortingGroup(folder, sortSpec, {
|
||||
iconFolderPluginInstance: obsidianIconFolderPluginInstance as ObsidianIconFolder_PluginInstance
|
||||
})
|
||||
} as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1486,7 +1494,7 @@ describe('determineSortingGroup', () => {
|
|||
// when
|
||||
const result = determineSortingGroup(folder, sortSpec, {
|
||||
iconFolderPluginInstance: obsidianIconFolderPluginInstance as ObsidianIconFolder_PluginInstance
|
||||
})
|
||||
} as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1519,7 +1527,9 @@ describe('determineSortingGroup', () => {
|
|||
byMetadataField: 'metadata-field-for-sorting',
|
||||
exactPrefix: 'Ref',
|
||||
order: CustomSortOrder.byMetadataFieldAlphabetical
|
||||
}],
|
||||
}]
|
||||
}
|
||||
const ctx: Partial<ProcessingContext> = {
|
||||
_mCache: {
|
||||
getCache: function (path: string): CachedMetadata | undefined {
|
||||
return {
|
||||
|
@ -1535,7 +1545,7 @@ describe('determineSortingGroup', () => {
|
|||
}
|
||||
|
||||
// when
|
||||
const result = determineSortingGroup(file, sortSpec)
|
||||
const result = determineSortingGroup(file, sortSpec, ctx as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1558,7 +1568,9 @@ describe('determineSortingGroup', () => {
|
|||
byMetadataField: 'metadata-field-for-sorting',
|
||||
exactPrefix: 'Ref',
|
||||
order: CustomSortOrder.byMetadataFieldAlphabeticalReverse
|
||||
}],
|
||||
}]
|
||||
}
|
||||
const ctx: Partial<ProcessingContext> = {
|
||||
_mCache: {
|
||||
getCache: function (path: string): CachedMetadata | undefined {
|
||||
return {
|
||||
|
@ -1574,7 +1586,7 @@ describe('determineSortingGroup', () => {
|
|||
}
|
||||
|
||||
// when
|
||||
const result = determineSortingGroup(file, sortSpec)
|
||||
const result = determineSortingGroup(file, sortSpec, ctx as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1597,7 +1609,9 @@ describe('determineSortingGroup', () => {
|
|||
byMetadataField: 'metadata-field-for-sorting',
|
||||
exactPrefix: 'Ref',
|
||||
order: CustomSortOrder.byMetadataFieldTrueAlphabetical
|
||||
}],
|
||||
}]
|
||||
}
|
||||
const ctx: Partial<ProcessingContext> = {
|
||||
_mCache: {
|
||||
getCache: function (path: string): CachedMetadata | undefined {
|
||||
return {
|
||||
|
@ -1613,7 +1627,7 @@ describe('determineSortingGroup', () => {
|
|||
}
|
||||
|
||||
// when
|
||||
const result = determineSortingGroup(file, sortSpec)
|
||||
const result = determineSortingGroup(file, sortSpec, ctx as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1636,7 +1650,9 @@ describe('determineSortingGroup', () => {
|
|||
byMetadataField: 'metadata-field-for-sorting',
|
||||
exactPrefix: 'Ref',
|
||||
order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse
|
||||
}],
|
||||
}]
|
||||
}
|
||||
const ctx: Partial<ProcessingContext> = {
|
||||
_mCache: {
|
||||
getCache: function (path: string): CachedMetadata | undefined {
|
||||
return {
|
||||
|
@ -1652,7 +1668,7 @@ describe('determineSortingGroup', () => {
|
|||
}
|
||||
|
||||
// when
|
||||
const result = determineSortingGroup(file, sortSpec)
|
||||
const result = determineSortingGroup(file, sortSpec, ctx as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1675,7 +1691,9 @@ describe('determineSortingGroup', () => {
|
|||
exactPrefix: 'Ref',
|
||||
byMetadataField: 'metadata-field-for-sorting',
|
||||
order: CustomSortOrder.byMetadataFieldAlphabeticalReverse
|
||||
}],
|
||||
}]
|
||||
}
|
||||
const ctx: Partial<ProcessingContext> = {
|
||||
_mCache: {
|
||||
getCache: function (path: string): CachedMetadata | undefined {
|
||||
return {
|
||||
|
@ -1691,7 +1709,7 @@ describe('determineSortingGroup', () => {
|
|||
}
|
||||
|
||||
// when
|
||||
const result = determineSortingGroup(folder, sortSpec)
|
||||
const result = determineSortingGroup(folder, sortSpec, ctx as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1715,6 +1733,10 @@ describe('determineSortingGroup', () => {
|
|||
exactPrefix: 'Ref',
|
||||
order: CustomSortOrder.byMetadataFieldAlphabetical
|
||||
}],
|
||||
defaultOrder: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
|
||||
byMetadataField: 'metadata-field-for-sorting-specified-on-target-folder'
|
||||
}
|
||||
const ctx: Partial<ProcessingContext> = {
|
||||
_mCache: {
|
||||
getCache: function (path: string): CachedMetadata | undefined {
|
||||
return {
|
||||
|
@ -1726,13 +1748,11 @@ describe('determineSortingGroup', () => {
|
|||
}
|
||||
}[path]
|
||||
}
|
||||
} as MetadataCache,
|
||||
defaultOrder: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
|
||||
byMetadataField: 'metadata-field-for-sorting-specified-on-target-folder',
|
||||
} as MetadataCache
|
||||
}
|
||||
|
||||
// when
|
||||
const result = determineSortingGroup(file, sortSpec)
|
||||
const result = determineSortingGroup(file, sortSpec, ctx as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1754,7 +1774,9 @@ describe('determineSortingGroup', () => {
|
|||
type: CustomSortGroupType.HasMetadataField,
|
||||
order: CustomSortOrder.byMetadataFieldAlphabetical,
|
||||
withMetadataFieldName: 'field-used-with-with-metadata-syntax'
|
||||
}],
|
||||
}]
|
||||
}
|
||||
const ctx: Partial<ProcessingContext> = {
|
||||
_mCache: {
|
||||
getCache: function (path: string): CachedMetadata | undefined {
|
||||
return {
|
||||
|
@ -1770,7 +1792,7 @@ describe('determineSortingGroup', () => {
|
|||
}
|
||||
|
||||
// when
|
||||
const result = determineSortingGroup(file, sortSpec)
|
||||
const result = determineSortingGroup(file, sortSpec, ctx as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -1792,7 +1814,9 @@ describe('determineSortingGroup', () => {
|
|||
type: CustomSortGroupType.ExactPrefix,
|
||||
exactPrefix: 'Ref',
|
||||
order: CustomSortOrder.byMetadataFieldAlphabetical
|
||||
}],
|
||||
}]
|
||||
}
|
||||
const ctx: Partial<ProcessingContext> = {
|
||||
_mCache: {
|
||||
getCache: function (path: string): CachedMetadata | undefined {
|
||||
return {
|
||||
|
@ -1808,7 +1832,7 @@ describe('determineSortingGroup', () => {
|
|||
}
|
||||
|
||||
// when
|
||||
const result = determineSortingGroup(file, sortSpec)
|
||||
const result = determineSortingGroup(file, sortSpec, ctx as ProcessingContext)
|
||||
|
||||
// then
|
||||
expect(result).toEqual({
|
||||
|
@ -2122,7 +2146,7 @@ describe('CustomSortOrder.byMetadataFieldAlphabetical', () => {
|
|||
const itemB: Partial<FolderItemForSorting> = {
|
||||
metadataFieldValue: 'B'
|
||||
}
|
||||
const sorter: SorterFn = Sorters[CustomSortOrder.byMetadataFieldAlphabetical]
|
||||
const sorter: SorterFn = getSorterFnFor(CustomSortOrder.byMetadataFieldAlphabetical)
|
||||
|
||||
// when
|
||||
const result1: number = sorter(itemA as FolderItemForSorting, itemB as FolderItemForSorting)
|
||||
|
@ -2142,7 +2166,7 @@ describe('CustomSortOrder.byMetadataFieldAlphabetical', () => {
|
|||
metadataFieldValue: 'Aaa',
|
||||
sortString: 'a123'
|
||||
}
|
||||
const sorter: SorterFn = Sorters[CustomSortOrder.byMetadataFieldAlphabetical]
|
||||
const sorter: SorterFn = getSorterFnFor(CustomSortOrder.byMetadataFieldAlphabetical)
|
||||
|
||||
// when
|
||||
const result1: number = sorter(itemA as FolderItemForSorting, itemB as FolderItemForSorting)
|
||||
|
@ -2163,7 +2187,7 @@ describe('CustomSortOrder.byMetadataFieldAlphabetical', () => {
|
|||
const itemB: Partial<FolderItemForSorting> = {
|
||||
sortString: 'n123'
|
||||
}
|
||||
const sorter: SorterFn = Sorters[CustomSortOrder.byMetadataFieldAlphabetical]
|
||||
const sorter: SorterFn = getSorterFnFor(CustomSortOrder.byMetadataFieldAlphabetical)
|
||||
|
||||
// when
|
||||
const result1: number = sorter(itemA as FolderItemForSorting, itemB as FolderItemForSorting)
|
||||
|
@ -2181,7 +2205,7 @@ describe('CustomSortOrder.byMetadataFieldAlphabetical', () => {
|
|||
const itemB: Partial<FolderItemForSorting> = {
|
||||
sortString: 'ccc '
|
||||
}
|
||||
const sorter: SorterFn = Sorters[CustomSortOrder.byMetadataFieldAlphabetical]
|
||||
const sorter: SorterFn = getSorterFnFor(CustomSortOrder.byMetadataFieldAlphabetical)
|
||||
|
||||
// when
|
||||
const result1: number = sorter(itemA as FolderItemForSorting, itemB as FolderItemForSorting)
|
||||
|
@ -2204,7 +2228,7 @@ describe('CustomSortOrder.byMetadataFieldAlphabeticalReverse', () => {
|
|||
const itemB: Partial<FolderItemForSorting> = {
|
||||
metadataFieldValue: 'B'
|
||||
}
|
||||
const sorter: SorterFn = Sorters[CustomSortOrder.byMetadataFieldAlphabeticalReverse]
|
||||
const sorter: SorterFn = getSorterFnFor(CustomSortOrder.byMetadataFieldAlphabeticalReverse)
|
||||
|
||||
// when
|
||||
const result1: number = sorter(itemA as FolderItemForSorting, itemB as FolderItemForSorting)
|
||||
|
@ -2224,7 +2248,7 @@ describe('CustomSortOrder.byMetadataFieldAlphabeticalReverse', () => {
|
|||
metadataFieldValue: 'Aaa',
|
||||
sortString: 'a123'
|
||||
}
|
||||
const sorter: SorterFn = Sorters[CustomSortOrder.byMetadataFieldAlphabeticalReverse]
|
||||
const sorter: SorterFn = getSorterFnFor(CustomSortOrder.byMetadataFieldAlphabeticalReverse)
|
||||
|
||||
// when
|
||||
const result1: number = sorter(itemA as FolderItemForSorting, itemB as FolderItemForSorting)
|
||||
|
@ -2236,25 +2260,6 @@ describe('CustomSortOrder.byMetadataFieldAlphabeticalReverse', () => {
|
|||
expect(result2).toBe(SORT_FIRST_GOES_LATER)
|
||||
expect(result3).toBe(SORT_ITEMS_ARE_EQUAL)
|
||||
})
|
||||
it('should put the item with metadata below the second one w/o metadata (this is reverse order)', () => {
|
||||
// given
|
||||
const itemA: Partial<FolderItemForSorting> = {
|
||||
metadataFieldValue: '15',
|
||||
sortString: 'n123'
|
||||
}
|
||||
const itemB: Partial<FolderItemForSorting> = {
|
||||
sortString: 'n123'
|
||||
}
|
||||
const sorter: SorterFn = Sorters[CustomSortOrder.byMetadataFieldAlphabeticalReverse]
|
||||
|
||||
// when
|
||||
const result1: number = sorter(itemA as FolderItemForSorting, itemB as FolderItemForSorting)
|
||||
const result2: number = sorter(itemB as FolderItemForSorting, itemA as FolderItemForSorting)
|
||||
|
||||
// then
|
||||
expect(result1).toBe(SORT_FIRST_GOES_LATER)
|
||||
expect(result2).toBe(SORT_FIRST_GOES_EARLIER)
|
||||
})
|
||||
it('should put the item with metadata later if the second one has no metadata (reverse order)', () => {
|
||||
// given
|
||||
const itemA: Partial<FolderItemForSorting> = {
|
||||
|
@ -2264,7 +2269,7 @@ describe('CustomSortOrder.byMetadataFieldAlphabeticalReverse', () => {
|
|||
const itemB: Partial<FolderItemForSorting> = {
|
||||
sortString: 'n123'
|
||||
}
|
||||
const sorter: SorterFn = Sorters[CustomSortOrder.byMetadataFieldAlphabeticalReverse]
|
||||
const sorter: SorterFn = getSorterFnFor(CustomSortOrder.byMetadataFieldAlphabeticalReverse)
|
||||
|
||||
// when
|
||||
const result1: number = sorter(itemA as FolderItemForSorting, itemB as FolderItemForSorting)
|
||||
|
@ -2282,7 +2287,7 @@ describe('CustomSortOrder.byMetadataFieldAlphabeticalReverse', () => {
|
|||
const itemB: Partial<FolderItemForSorting> = {
|
||||
sortString: 'ccc '
|
||||
}
|
||||
const sorter: SorterFn = Sorters[CustomSortOrder.byMetadataFieldAlphabeticalReverse]
|
||||
const sorter: SorterFn = getSorterFnFor(CustomSortOrder.byMetadataFieldAlphabeticalReverse)
|
||||
|
||||
// when
|
||||
const result1: number = sorter(itemA as FolderItemForSorting, itemB as FolderItemForSorting)
|
||||
|
|
|
@ -3,6 +3,7 @@ import {
|
|||
CommunityPlugin,
|
||||
FrontMatterCache,
|
||||
InstalledPlugin,
|
||||
MetadataCache,
|
||||
requireApiVersion,
|
||||
TAbstractFile,
|
||||
TFile,
|
||||
|
@ -39,6 +40,15 @@ import {
|
|||
} from "./macros";
|
||||
import {Obj} from "tern";
|
||||
|
||||
export interface ProcessingContext {
|
||||
// For internal transient use
|
||||
plugin?: Plugin // to hand over the access to App instance to the sorting engine
|
||||
_mCache?: MetadataCache
|
||||
starredPluginInstance?: Starred_PluginInstance
|
||||
|
||||
iconFolderPluginInstance?: ObsidianIconFolder_PluginInstance
|
||||
}
|
||||
|
||||
let CollatorCompare = new Intl.Collator(undefined, {
|
||||
usage: "sort",
|
||||
sensitivity: "base",
|
||||
|
@ -96,7 +106,7 @@ export const sorterByMetadataField:(reverseOrder?: boolean, trueAlphabetical?: b
|
|||
}
|
||||
}
|
||||
|
||||
export let Sorters: { [key in CustomSortOrder]: SorterFn } = {
|
||||
let Sorters: { [key in CustomSortOrder]: SorterFn } = {
|
||||
[CustomSortOrder.alphabetical]: (a: FolderItemForSorting, b: FolderItemForSorting) => CollatorCompare(a.sortString, b.sortString),
|
||||
[CustomSortOrder.trueAlphabetical]: (a: FolderItemForSorting, b: FolderItemForSorting) => CollatorTrueAlphabeticalCompare(a.sortString, b.sortString),
|
||||
[CustomSortOrder.alphabeticalReverse]: (a: FolderItemForSorting, b: FolderItemForSorting) => CollatorCompare(b.sortString, a.sortString),
|
||||
|
@ -236,12 +246,7 @@ export const matchGroupRegex = (theRegex: RegExpSpec, nameForMatching: string):
|
|||
return [false, undefined, undefined]
|
||||
}
|
||||
|
||||
export interface Context {
|
||||
starredPluginInstance?: Starred_PluginInstance
|
||||
iconFolderPluginInstance?: ObsidianIconFolder_PluginInstance
|
||||
}
|
||||
|
||||
export const determineSortingGroup = function (entry: TFile | TFolder, spec: CustomSortSpec, ctx?: Context): FolderItemForSorting {
|
||||
export const determineSortingGroup = function (entry: TFile | TFolder, spec: CustomSortSpec, ctx?: ProcessingContext): FolderItemForSorting {
|
||||
let groupIdx: number
|
||||
let determined: boolean = false
|
||||
let matchedGroup: string | null | undefined
|
||||
|
@ -324,10 +329,10 @@ export const determineSortingGroup = function (entry: TFile | TFolder, spec: Cus
|
|||
break
|
||||
case CustomSortGroupType.HasMetadataField:
|
||||
if (group.withMetadataFieldName) {
|
||||
if (spec._mCache) {
|
||||
if (ctx?._mCache) {
|
||||
// For folders - scan metadata of 'folder note'
|
||||
const notePathToScan: string = aFile ? entry.path : `${entry.path}/${entry.name}.md`
|
||||
const frontMatterCache: FrontMatterCache | undefined = spec._mCache.getCache(notePathToScan)?.frontmatter
|
||||
const frontMatterCache: FrontMatterCache | undefined = ctx._mCache.getCache(notePathToScan)?.frontmatter
|
||||
const hasMetadata: boolean | undefined = frontMatterCache?.hasOwnProperty(group.withMetadataFieldName)
|
||||
|
||||
if (hasMetadata) {
|
||||
|
@ -417,10 +422,10 @@ export const determineSortingGroup = function (entry: TFile | TFolder, spec: Cus
|
|||
metadataFieldName = DEFAULT_METADATA_FIELD_FOR_SORTING
|
||||
}
|
||||
if (metadataFieldName) {
|
||||
if (spec._mCache) {
|
||||
if (ctx?._mCache) {
|
||||
// For folders - scan metadata of 'folder note'
|
||||
const notePathToScan: string = aFile ? entry.path : `${entry.path}/${entry.name}.md`
|
||||
const frontMatterCache: FrontMatterCache | undefined = spec._mCache.getCache(notePathToScan)?.frontmatter
|
||||
const frontMatterCache: FrontMatterCache | undefined = ctx._mCache.getCache(notePathToScan)?.frontmatter
|
||||
metadataValueToSortBy = frontMatterCache?.[metadataFieldName]
|
||||
}
|
||||
}
|
||||
|
@ -496,11 +501,8 @@ export const determineFolderDatesIfNeeded = (folderItems: Array<FolderItemForSor
|
|||
})
|
||||
}
|
||||
|
||||
export const folderSort = function (sortingSpec: CustomSortSpec, order: string[]) {
|
||||
export const folderSort = function (sortingSpec: CustomSortSpec, ctx: ProcessingContext) {
|
||||
let fileExplorer = this.fileExplorer
|
||||
sortingSpec._mCache = sortingSpec.plugin?.app.metadataCache
|
||||
const starredPluginInstance: Starred_PluginInstance | undefined = getStarredPlugin()
|
||||
const iconFolderPluginInstance: ObsidianIconFolder_PluginInstance | undefined = getIconFolderPlugin()
|
||||
|
||||
// shallow copy of groups
|
||||
sortingSpec.groupsShadow = sortingSpec.groups?.map((group) => Object.assign({} as CustomSortGroup, group))
|
||||
|
@ -516,10 +518,7 @@ export const folderSort = function (sortingSpec: CustomSortSpec, order: string[]
|
|||
:
|
||||
this.file.children)
|
||||
.map((entry: TFile | TFolder) => {
|
||||
const itemForSorting: FolderItemForSorting = determineSortingGroup(entry, sortingSpec, {
|
||||
starredPluginInstance: starredPluginInstance,
|
||||
iconFolderPluginInstance: iconFolderPluginInstance
|
||||
})
|
||||
const itemForSorting: FolderItemForSorting = determineSortingGroup(entry, sortingSpec, ctx)
|
||||
return itemForSorting
|
||||
})
|
||||
|
||||
|
@ -538,8 +537,4 @@ export const folderSort = function (sortingSpec: CustomSortSpec, order: string[]
|
|||
} else {
|
||||
this.children = items;
|
||||
}
|
||||
|
||||
// release risky references
|
||||
sortingSpec._mCache = undefined
|
||||
sortingSpec.plugin = undefined
|
||||
};
|
||||
|
|
|
@ -2,8 +2,10 @@ import {FolderWildcardMatching} from './folder-matching-rules'
|
|||
|
||||
type SortingSpec = string
|
||||
|
||||
const checkIfImplicitSpec = (s: SortingSpec) => false
|
||||
|
||||
const createMockMatcherRichVersion = (): FolderWildcardMatching<SortingSpec> => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
let p: string
|
||||
p = '/...'; matcher.addWildcardDefinition(p, `00 ${p}`)
|
||||
p = '/*'; matcher.addWildcardDefinition(p, `0 ${p}`)
|
||||
|
@ -19,25 +21,25 @@ const PRIO2 = 2
|
|||
const PRIO3 = 3
|
||||
|
||||
const createMockMatcherSimplestVersion = (): FolderWildcardMatching<SortingSpec> => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addWildcardDefinition('/Reviews/daily/*', '/Reviews/daily/*')
|
||||
return matcher
|
||||
}
|
||||
|
||||
const createMockMatcherRootOnlyVersion = (): FolderWildcardMatching<SortingSpec> => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addWildcardDefinition('/...', '/...')
|
||||
return matcher
|
||||
}
|
||||
|
||||
const createMockMatcherRootOnlyDeepVersion = (): FolderWildcardMatching<SortingSpec> => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addWildcardDefinition('/*', '/*')
|
||||
return matcher
|
||||
}
|
||||
|
||||
const createMockMatcherSimpleVersion = (): FolderWildcardMatching<SortingSpec> => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addWildcardDefinition('/Reviews/daily/*', '/Reviews/daily/*')
|
||||
matcher.addWildcardDefinition('/Reviews/daily/...', '/Reviews/daily/...')
|
||||
return matcher
|
||||
|
@ -108,21 +110,21 @@ describe('folderMatch', () => {
|
|||
expect(match3).toBe('/Reviews/daily/...')
|
||||
})
|
||||
it('should detect duplicate match children definitions for same path', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addWildcardDefinition('Archive/2020/...', 'First occurrence')
|
||||
const result = matcher.addWildcardDefinition('/Archive/2020/.../', 'Duplicate')
|
||||
|
||||
expect(result).toEqual({errorMsg: "Duplicate wildcard '...' specification for /Archive/2020/.../"})
|
||||
})
|
||||
it('should detect duplicate match all definitions for same path', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addWildcardDefinition('/Archive/2019/*', 'First occurrence')
|
||||
const result = matcher.addWildcardDefinition('Archive/2019/*', 'Duplicate')
|
||||
|
||||
expect(result).toEqual({errorMsg: "Duplicate wildcard '*' specification for Archive/2019/*"})
|
||||
})
|
||||
it('regexp-match by name works (order of regexp doesn\'t matter) case A', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addRegexpDefinition(/^daily$/, false, undefined, false, `r1`)
|
||||
matcher.addRegexpDefinition(/^daily$/, true, undefined, false, `r2`)
|
||||
matcher.addWildcardDefinition('/Reviews/*', `w1`)
|
||||
|
@ -134,7 +136,7 @@ describe('folderMatch', () => {
|
|||
expect(match2).toBe('r2')
|
||||
})
|
||||
it('regexp-match by name works (order of regexp doesn\'t matter) reversed case A', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addRegexpDefinition(/^daily$/, true, undefined, false, `r2`)
|
||||
matcher.addRegexpDefinition(/^daily$/, false, undefined, false, `r1`)
|
||||
matcher.addWildcardDefinition('/Reviews/*', `w1`)
|
||||
|
@ -146,7 +148,7 @@ describe('folderMatch', () => {
|
|||
expect(match2).toBe('r2')
|
||||
})
|
||||
it('regexp-match by path works (order of regexp doesn\'t matter) case A', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addRegexpDefinition(/^Reviews\/daily$/, false, undefined, false, `r1`)
|
||||
matcher.addRegexpDefinition(/^Reviews\/daily$/, true, undefined, false, `r2`)
|
||||
matcher.addWildcardDefinition('/Reviews/*', `w1`)
|
||||
|
@ -158,7 +160,7 @@ describe('folderMatch', () => {
|
|||
expect(match2).toBe('r1')
|
||||
})
|
||||
it('regexp-match by path works (order of regexp doesn\'t matter) reversed case A', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addRegexpDefinition(/^Reviews\/daily$/, true, undefined, false, `r2`)
|
||||
matcher.addRegexpDefinition(/^Reviews\/daily$/, false, undefined, false, `r1`)
|
||||
matcher.addWildcardDefinition('/Reviews/*', `w1`)
|
||||
|
@ -170,7 +172,7 @@ describe('folderMatch', () => {
|
|||
expect(match2).toBe('r1')
|
||||
})
|
||||
it('regexp-match by path and name for root level - order of regexp decides - case A', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addRegexpDefinition(/^daily$/, false, undefined, false, `r1`)
|
||||
matcher.addRegexpDefinition(/^daily$/, true, undefined, false, `r2`)
|
||||
matcher.addWildcardDefinition('/Reviews/*', `w1`)
|
||||
|
@ -179,7 +181,7 @@ describe('folderMatch', () => {
|
|||
expect(match).toBe('r2')
|
||||
})
|
||||
it('regexp-match by path and name for root level - order of regexp decides - reversed case A', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addRegexpDefinition(/^daily$/, true, undefined, false, `r2`)
|
||||
matcher.addRegexpDefinition(/^daily$/, false, undefined, false, `r1`)
|
||||
matcher.addWildcardDefinition('/Reviews/*', `w1`)
|
||||
|
@ -188,7 +190,7 @@ describe('folderMatch', () => {
|
|||
expect(match).toBe('r1')
|
||||
})
|
||||
it('regexp-match priorities - order of definitions irrelevant - unique priorities - case A', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addRegexpDefinition(/^freq\/daily$/, false, 3, false, `r1p3`)
|
||||
matcher.addRegexpDefinition(/^freq\/daily$/, false, 2, false, `r2p2`)
|
||||
matcher.addRegexpDefinition(/^freq\/daily$/, false, 1, false, `r3p1`)
|
||||
|
@ -198,7 +200,7 @@ describe('folderMatch', () => {
|
|||
expect(match).toBe('r1p3')
|
||||
})
|
||||
it('regexp-match priorities - order of definitions irrelevant - unique priorities - reversed case A', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addRegexpDefinition(/^freq\/daily$/, false, undefined, false, `r4pNone`)
|
||||
matcher.addRegexpDefinition(/^freq\/daily$/, false, 1, false, `r3p1`)
|
||||
matcher.addRegexpDefinition(/^freq\/daily$/, false, 2, false, `r2p2`)
|
||||
|
@ -208,7 +210,7 @@ describe('folderMatch', () => {
|
|||
expect(match).toBe('r1p3')
|
||||
})
|
||||
it('regexp-match priorities - order of definitions irrelevant - duplicate priorities - case A', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addRegexpDefinition(/^daily$/, true, 3, false, `r1p3a`)
|
||||
matcher.addRegexpDefinition(/^daily$/, true, 3, false, `r1p3b`)
|
||||
matcher.addRegexpDefinition(/^daily$/, true, 2, false, `r2p2a`)
|
||||
|
@ -221,7 +223,7 @@ describe('folderMatch', () => {
|
|||
expect(match).toBe('r1p3b')
|
||||
})
|
||||
it('regexp-match priorities - order of definitions irrelevant - unique priorities - reversed case A', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addRegexpDefinition(/^freq\/daily$/, false, undefined, false, `r4pNone`)
|
||||
matcher.addRegexpDefinition(/^freq\/daily$/, false, 1, false, `r3p1`)
|
||||
matcher.addRegexpDefinition(/^freq\/daily$/, false, 2, false, `r2p2`)
|
||||
|
@ -231,14 +233,14 @@ describe('folderMatch', () => {
|
|||
expect(match).toBe('r1p3')
|
||||
})
|
||||
it('regexp-match - edge case of matching the root folder - match by path', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
matcher.addRegexpDefinition(/^\/$/, false, undefined, false, `r1`)
|
||||
// Path w/o leading / - this is how Obsidian supplies the path
|
||||
const match: SortingSpec | null = matcher.folderMatch('/', '')
|
||||
expect(match).toBe('r1')
|
||||
})
|
||||
it('regexp-match - edge case of matching the root folder - match by name not possible', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
// Tricky regexp which can return zero length matches
|
||||
matcher.addRegexpDefinition(/.*/, true, undefined, false, `r1`)
|
||||
matcher.addWildcardDefinition('/*', `w1`)
|
||||
|
@ -247,7 +249,7 @@ describe('folderMatch', () => {
|
|||
expect(match).toBe('w1')
|
||||
})
|
||||
it('regexp-match - edge case of no match when only regexp rules present', () => {
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching()
|
||||
const matcher: FolderWildcardMatching<SortingSpec> = new FolderWildcardMatching(checkIfImplicitSpec)
|
||||
// Tricky regexp which can return zero length matches
|
||||
matcher.addRegexpDefinition(/abc/, true, undefined, false, `r1`)
|
||||
// Path w/o leading / - this is how Obsidian supplies the path
|
||||
|
|
|
@ -35,6 +35,8 @@ export interface AddingWildcardFailure {
|
|||
errorMsg: string
|
||||
}
|
||||
|
||||
export type CheckIfImplicitSpec<SortingSpec> = (s: SortingSpec) => boolean
|
||||
|
||||
export class FolderWildcardMatching<SortingSpec> {
|
||||
|
||||
// mimics the structure of folders, so for example tree.matchAll contains the matchAll flag for the root '/'
|
||||
|
@ -44,6 +46,9 @@ export class FolderWildcardMatching<SortingSpec> {
|
|||
|
||||
regexps: Array<FolderMatchingRegexp<SortingSpec>>
|
||||
|
||||
constructor(private checkIfImplicitSpec: CheckIfImplicitSpec<SortingSpec>) {
|
||||
}
|
||||
|
||||
// cache
|
||||
determinedWildcardRules: { [key: string]: DeterminedSortingSpec<SortingSpec> } = {}
|
||||
|
||||
|
@ -68,13 +73,13 @@ export class FolderWildcardMatching<SortingSpec> {
|
|||
}
|
||||
})
|
||||
if (lastComponent === MATCH_CHILDREN_PATH_TOKEN) {
|
||||
if (leafNode.matchChildren) {
|
||||
if (leafNode.matchChildren && !this.checkIfImplicitSpec(leafNode.matchChildren)) {
|
||||
return {errorMsg: `Duplicate wildcard '${lastComponent}' specification for ${wilcardDefinition}`}
|
||||
} else {
|
||||
leafNode.matchChildren = rule
|
||||
}
|
||||
} else { // Implicitly: MATCH_ALL_PATH_TOKEN
|
||||
if (leafNode.matchAll) {
|
||||
if (leafNode.matchAll && !this.checkIfImplicitSpec(leafNode.matchAll)) {
|
||||
return {errorMsg: `Duplicate wildcard '${lastComponent}' specification for ${wilcardDefinition}`}
|
||||
} else {
|
||||
leafNode.matchAll = rule
|
||||
|
|
|
@ -1677,6 +1677,11 @@ const txtInputErrorPriorityEmptyPattern: string = `
|
|||
`
|
||||
|
||||
const txtInputEmptySpec: string = ``
|
||||
const txtInputOnlyCommentsSpec: string = `
|
||||
// Some comment
|
||||
|
||||
// Another comment below empty line
|
||||
`
|
||||
|
||||
describe('SortingSpecProcessor error detection and reporting', () => {
|
||||
let processor: SortingSpecProcessor;
|
||||
|
@ -1915,7 +1920,7 @@ describe('SortingSpecProcessor error detection and reporting', () => {
|
|||
`${ERR_PREFIX} 22:PriorityPrefixAfterGroupTypePrefix Priority prefix must be used before sorting group type indicator ${ERR_SUFFIX_IN_LINE(2)}`)
|
||||
expect(errorsLogger).toHaveBeenNthCalledWith(2, ERR_LINE_TXT('/folders /+ /! Hello'))
|
||||
})
|
||||
it('should recognize error: combine prefix after sorting group type prefixe', () => {
|
||||
it('should recognize error: combine prefix after sorting group type prefix', () => {
|
||||
const inputTxtArr: Array<string> = `
|
||||
/folders /+ Hello
|
||||
`.replace(/\t/gi, '').split('\n')
|
||||
|
@ -1932,6 +1937,12 @@ describe('SortingSpecProcessor error detection and reporting', () => {
|
|||
expect(result).toBeNull()
|
||||
expect(errorsLogger).toHaveBeenCalledTimes(0)
|
||||
})
|
||||
it('should recognize empty spec', () => {
|
||||
const inputTxtArr: Array<string> = txtInputOnlyCommentsSpec.split('\n')
|
||||
const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
|
||||
expect(result).toBeNull()
|
||||
expect(errorsLogger).toHaveBeenCalledTimes(0)
|
||||
})
|
||||
it.each([
|
||||
'% \\.d+...',
|
||||
'% ...\\d+',
|
||||
|
|
|
@ -37,6 +37,7 @@ interface ProcessingContext {
|
|||
specs: Array<CustomSortSpec>
|
||||
currentSpec?: CustomSortSpec
|
||||
currentSpecGroup?: CustomSortGroup
|
||||
implicitSpec?: boolean
|
||||
|
||||
// Support for specific conditions (intentionally not generic approach)
|
||||
previousValidEntryWasTargetFolderAttr?: boolean // Entry in previous non-empty valid line
|
||||
|
@ -577,7 +578,7 @@ const ensureCollectionHasSortSpecByName = (collection?: SortSpecsCollection | nu
|
|||
const ensureCollectionHasSortSpecByWildcard = (collection?: SortSpecsCollection | null) => {
|
||||
collection = collection ?? {}
|
||||
if (!collection.sortSpecByWildcard) {
|
||||
collection.sortSpecByWildcard = new FolderWildcardMatching<CustomSortSpec>()
|
||||
collection.sortSpecByWildcard = new FolderWildcardMatching<CustomSortSpec>((spec: CustomSortSpec) => !!spec.implicit)
|
||||
}
|
||||
return collection
|
||||
}
|
||||
|
@ -602,35 +603,38 @@ const endsWithWildcardPatternSuffix = (path: string): boolean => {
|
|||
|
||||
enum WildcardPriority {
|
||||
NO_WILDCARD = 1,
|
||||
NO_WILDCARD_IMPLICIT,
|
||||
MATCH_CHILDREN,
|
||||
MATCH_ALL
|
||||
MATCH_CHILDREN_IMPLICIT,
|
||||
MATCH_ALL,
|
||||
MATCH_ALL_IMPLICIT
|
||||
}
|
||||
|
||||
const stripWildcardPatternSuffix = (path: string): {path: string, detectedWildcardPriority: number} => {
|
||||
const stripWildcardPatternSuffix = (path: string, ofImplicitSpec: boolean): {path: string, detectedWildcardPriority: number} => {
|
||||
if (path.endsWith(MATCH_ALL_SUFFIX)) {
|
||||
path = path.slice(0, -MATCH_ALL_SUFFIX.length)
|
||||
return {
|
||||
path: path.length > 0 ? path : '/',
|
||||
detectedWildcardPriority: WildcardPriority.MATCH_ALL
|
||||
detectedWildcardPriority: ofImplicitSpec ? WildcardPriority.MATCH_ALL_IMPLICIT : WildcardPriority.MATCH_ALL
|
||||
}
|
||||
}
|
||||
if (path.endsWith(MATCH_CHILDREN_1_SUFFIX)) {
|
||||
path = path.slice(0, -MATCH_CHILDREN_1_SUFFIX.length)
|
||||
return {
|
||||
path: path.length > 0 ? path : '/',
|
||||
detectedWildcardPriority: WildcardPriority.MATCH_CHILDREN,
|
||||
detectedWildcardPriority: ofImplicitSpec ? WildcardPriority.MATCH_CHILDREN_IMPLICIT : WildcardPriority.MATCH_CHILDREN
|
||||
}
|
||||
}
|
||||
if (path.endsWith(MATCH_CHILDREN_2_SUFFIX)) {
|
||||
path = path.slice(0, -MATCH_CHILDREN_2_SUFFIX.length)
|
||||
return {
|
||||
path: path.length > 0 ? path : '/',
|
||||
detectedWildcardPriority: WildcardPriority.MATCH_CHILDREN
|
||||
detectedWildcardPriority: ofImplicitSpec ? WildcardPriority.MATCH_CHILDREN_IMPLICIT : WildcardPriority.MATCH_CHILDREN
|
||||
}
|
||||
}
|
||||
return {
|
||||
path: path,
|
||||
detectedWildcardPriority: WildcardPriority.NO_WILDCARD
|
||||
detectedWildcardPriority: ofImplicitSpec ? WildcardPriority.NO_WILDCARD_IMPLICIT : WildcardPriority.NO_WILDCARD
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -727,12 +731,14 @@ export class SortingSpecProcessor {
|
|||
parseSortSpecFromText(text: Array<string>,
|
||||
folderPath: string,
|
||||
sortingSpecFileName: string,
|
||||
collection?: SortSpecsCollection | null
|
||||
collection?: SortSpecsCollection | null,
|
||||
implicitSpec?: boolean
|
||||
): SortSpecsCollection | null | undefined {
|
||||
// reset / init processing state after potential previous invocation
|
||||
this.ctx = {
|
||||
folderPath: folderPath, // location of the sorting spec file
|
||||
specs: []
|
||||
specs: [],
|
||||
implicitSpec: implicitSpec
|
||||
};
|
||||
this.currentEntryLine = null
|
||||
this.currentEntryLineIdx = null
|
||||
|
@ -839,7 +845,7 @@ export class SortingSpecProcessor {
|
|||
for (let idx = 0; idx < spec.targetFoldersPaths.length; idx++) {
|
||||
const originalPath = spec.targetFoldersPaths[idx]
|
||||
if (!originalPath.startsWith(MatchFolderNameLexeme) && !originalPath.startsWith(MatchFolderByRegexpLexeme)) {
|
||||
const {path, detectedWildcardPriority} = stripWildcardPatternSuffix(originalPath)
|
||||
const {path, detectedWildcardPriority} = stripWildcardPatternSuffix(originalPath, !!spec.implicit)
|
||||
let storeTheSpec: boolean = true
|
||||
const preexistingSortSpecPriority: WildcardPriority = this.pathMatchPriorityForPath[path]
|
||||
if (preexistingSortSpecPriority) {
|
||||
|
@ -1446,7 +1452,8 @@ export class SortingSpecProcessor {
|
|||
private putNewSpecForNewTargetFolder(folderPath?: string): CustomSortSpec {
|
||||
const newSpec: CustomSortSpec = {
|
||||
targetFoldersPaths: [folderPath ?? this.ctx.folderPath],
|
||||
groups: []
|
||||
groups: [],
|
||||
implicit: this.ctx.implicitSpec
|
||||
}
|
||||
|
||||
this.ctx.specs.push(newSpec);
|
||||
|
|
Loading…
Reference in New Issue