Merge pull request #174 from SebastianMC/nov-2024-refactoring-regroup-sorting-structures
Major refactoring of sorting structures.
This commit is contained in:
		
						commit
						2c2053d853
					
				| 
						 | 
				
			
			@ -49,15 +49,6 @@ export enum CustomSortOrder {
 | 
			
		|||
	default = alphabeticalWithFilesPreferred
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface RecognizedOrderValue {
 | 
			
		||||
	order: CustomSortOrder
 | 
			
		||||
	applyToMetadataField?: string
 | 
			
		||||
	metadataValueExtractor?: MDataExtractor
 | 
			
		||||
	secondaryOrder?: CustomSortOrder
 | 
			
		||||
	secondaryApplyToMetadataField?: string
 | 
			
		||||
	secondaryMetadataValueExtractor?: MDataExtractor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type NormalizerFn = (s: string) => string | null
 | 
			
		||||
export const IdentityNormalizerFn: NormalizerFn = (s: string) => s
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -66,6 +57,17 @@ export interface RegExpSpec {
 | 
			
		|||
	normalizerFn?: NormalizerFn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface CustomSort {
 | 
			
		||||
	order: CustomSortOrder    // mandatory
 | 
			
		||||
	byMetadata?: string
 | 
			
		||||
	metadataValueExtractor?: MDataExtractor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface RecognizedSorting {
 | 
			
		||||
	primary?: CustomSort
 | 
			
		||||
	secondary?: CustomSort
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface CustomSortGroup {
 | 
			
		||||
	type: CustomSortGroupType
 | 
			
		||||
	exactText?: string
 | 
			
		||||
| 
						 | 
				
			
			@ -73,12 +75,8 @@ export interface CustomSortGroup {
 | 
			
		|||
	regexPrefix?: RegExpSpec
 | 
			
		||||
	exactSuffix?: string
 | 
			
		||||
	regexSuffix?: RegExpSpec
 | 
			
		||||
	order?: CustomSortOrder
 | 
			
		||||
	byMetadataField?: string                       // for 'by-metadata:' sorting if the order is by metadata alphabetical or reverse
 | 
			
		||||
	metadataFieldValueExtractor?: MDataExtractor   //    and its sorting value extractor
 | 
			
		||||
	secondaryOrder?: CustomSortOrder
 | 
			
		||||
	byMetadataFieldSecondary?: string     // for 'by-metadata:' sorting if the order is by metadata alphabetical or reverse
 | 
			
		||||
	metadataFieldSecondaryValueExtractor?: MDataExtractor
 | 
			
		||||
	sorting?: CustomSort
 | 
			
		||||
	secondarySorting?: CustomSort
 | 
			
		||||
	filesOnly?: boolean
 | 
			
		||||
	matchFilenameWithExt?: boolean
 | 
			
		||||
	foldersOnly?: boolean
 | 
			
		||||
| 
						 | 
				
			
			@ -91,12 +89,8 @@ export interface CustomSortGroup {
 | 
			
		|||
export interface CustomSortSpec {
 | 
			
		||||
		// plays only informative role about the original parsed 'target-folder:' values
 | 
			
		||||
	targetFoldersPaths: Array<string>   // For root use '/'
 | 
			
		||||
	defaultOrder?: CustomSortOrder
 | 
			
		||||
	defaultSecondaryOrder?: CustomSortOrder
 | 
			
		||||
	byMetadataField?: string                 // for 'by-metadata:' if the defaultOrder is by metadata
 | 
			
		||||
	metadataFieldValueExtractor?: MDataExtractor  //       and its sorting value extractor
 | 
			
		||||
	byMetadataFieldSecondary?: string
 | 
			
		||||
	metadataFieldSecondaryValueExtractor?: MDataExtractor
 | 
			
		||||
	defaultSorting?: CustomSort
 | 
			
		||||
	defaultSecondarySorting?: CustomSort
 | 
			
		||||
	groups: Array<CustomSortGroup>
 | 
			
		||||
	groupsShadow?: Array<CustomSortGroup>   // A shallow copy of groups, used at applying sorting for items in a folder.
 | 
			
		||||
	                                        // Stores folder-specific values (e.g. macros expanded with folder-specific values)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,12 +57,12 @@ export const collectSortingAndGroupingTypes = (sortSpec?: CustomSortSpec|null):
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (!sortSpec) return has
 | 
			
		||||
    doCheck(has, sortSpec.defaultOrder)
 | 
			
		||||
    doCheck(has, sortSpec.defaultSecondaryOrder)
 | 
			
		||||
    doCheck(has, sortSpec.defaultSorting?.order)
 | 
			
		||||
    doCheck(has, sortSpec.defaultSecondarySorting?.order)
 | 
			
		||||
    if (sortSpec.groups) {
 | 
			
		||||
        for (let group of sortSpec.groups) {
 | 
			
		||||
            doCheck(has, group.order, group.type)
 | 
			
		||||
            doCheck(has, group.secondaryOrder)
 | 
			
		||||
            doCheck(has, group.sorting?.order, group.type)
 | 
			
		||||
            doCheck(has, group.secondarySorting?.order)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return has
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@ import {
 | 
			
		|||
	ObsidianIconFolder_PluginInstance
 | 
			
		||||
} from '../utils/ObsidianIconFolderPluginSignature'
 | 
			
		||||
import {
 | 
			
		||||
	CustomSort,
 | 
			
		||||
	CustomSortGroup,
 | 
			
		||||
	CustomSortGroupType,
 | 
			
		||||
	CustomSortOrder,
 | 
			
		||||
| 
						 | 
				
			
			@ -287,18 +288,18 @@ export const StandardPlainObsidianComparator = (order: string): PlainSorterFn =>
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getSorterFnFor = (sorting: CustomSortOrder, currentUIselectedSorting?: string, sortLevelId?: SortingLevelId): SorterFn => {
 | 
			
		||||
	if (sorting === CustomSortOrder.standardObsidian) {
 | 
			
		||||
		sorting = StandardObsidianToCustomSort[currentUIselectedSorting ?? 'alphabetical'] ?? CustomSortOrder.alphabetical
 | 
			
		||||
		return StandardObsidianComparator(sorting)
 | 
			
		||||
export const getSorterFnFor = (order: CustomSortOrder, currentUIselectedSorting?: string, sortLevelId?: SortingLevelId): SorterFn => {
 | 
			
		||||
	if (order === CustomSortOrder.standardObsidian) {
 | 
			
		||||
		order = StandardObsidianToCustomSort[currentUIselectedSorting ?? 'alphabetical'] ?? CustomSortOrder.alphabetical
 | 
			
		||||
		return StandardObsidianComparator(order)
 | 
			
		||||
	} else {
 | 
			
		||||
		// Some sorters have to know at which sorting level they are used
 | 
			
		||||
		switch(sortLevelId) {
 | 
			
		||||
			case SortingLevelId.forSecondary: return SortersForSecondary[sorting] ?? Sorters[sorting]
 | 
			
		||||
			case SortingLevelId.forDerivedPrimary: return SortersForDerivedPrimary[sorting] ?? Sorters[sorting]
 | 
			
		||||
			case SortingLevelId.forDerivedSecondary: return SortersForDerivedSecondary[sorting] ?? Sorters[sorting]
 | 
			
		||||
			case SortingLevelId.forSecondary: return SortersForSecondary[order] ?? Sorters[order]
 | 
			
		||||
			case SortingLevelId.forDerivedPrimary: return SortersForDerivedPrimary[order] ?? Sorters[order]
 | 
			
		||||
			case SortingLevelId.forDerivedSecondary: return SortersForDerivedSecondary[order] ?? Sorters[order]
 | 
			
		||||
			case SortingLevelId.forPrimary:
 | 
			
		||||
			default: return Sorters[sorting]
 | 
			
		||||
			default: return Sorters[order]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -308,13 +309,13 @@ export const getComparator = (sortSpec: CustomSortSpec, currentUIselectedSorting
 | 
			
		|||
		if (itA.groupIdx != undefined && itB.groupIdx != undefined) {
 | 
			
		||||
			if (itA.groupIdx === itB.groupIdx) {
 | 
			
		||||
				const group: CustomSortGroup | undefined = sortSpec.groups[itA.groupIdx]
 | 
			
		||||
				const primary: number = group?.order ? getSorterFnFor(group.order, currentUIselectedSorting, SortingLevelId.forPrimary)(itA, itB) : EQUAL_OR_UNCOMPARABLE
 | 
			
		||||
				const primary: number = group?.sorting ? getSorterFnFor(group.sorting.order, currentUIselectedSorting, SortingLevelId.forPrimary)(itA, itB) : EQUAL_OR_UNCOMPARABLE
 | 
			
		||||
				if (primary !== EQUAL_OR_UNCOMPARABLE) return primary
 | 
			
		||||
				const secondary: number = group?.secondaryOrder ? getSorterFnFor(group.secondaryOrder, currentUIselectedSorting, SortingLevelId.forSecondary)(itA, itB) : EQUAL_OR_UNCOMPARABLE
 | 
			
		||||
				const secondary: number = group?.secondarySorting ? getSorterFnFor(group.secondarySorting.order, currentUIselectedSorting, SortingLevelId.forSecondary)(itA, itB) : EQUAL_OR_UNCOMPARABLE
 | 
			
		||||
				if (secondary !== EQUAL_OR_UNCOMPARABLE) return secondary
 | 
			
		||||
				const folderLevel: number = sortSpec.defaultOrder ? getSorterFnFor(sortSpec.defaultOrder, currentUIselectedSorting, SortingLevelId.forDerivedPrimary)(itA, itB) : EQUAL_OR_UNCOMPARABLE
 | 
			
		||||
				const folderLevel: number = sortSpec.defaultSorting ? getSorterFnFor(sortSpec.defaultSorting.order, currentUIselectedSorting, SortingLevelId.forDerivedPrimary)(itA, itB) : EQUAL_OR_UNCOMPARABLE
 | 
			
		||||
				if (folderLevel !== EQUAL_OR_UNCOMPARABLE) return folderLevel
 | 
			
		||||
				const folderLevelSecondary: number = sortSpec.defaultSecondaryOrder ? getSorterFnFor(sortSpec.defaultSecondaryOrder, currentUIselectedSorting, SortingLevelId.forDerivedSecondary)(itA, itB) : EQUAL_OR_UNCOMPARABLE
 | 
			
		||||
				const folderLevelSecondary: number = sortSpec.defaultSecondarySorting ? getSorterFnFor(sortSpec.defaultSecondarySorting.order, currentUIselectedSorting, SortingLevelId.forDerivedSecondary)(itA, itB) : EQUAL_OR_UNCOMPARABLE
 | 
			
		||||
				if (folderLevelSecondary !== EQUAL_OR_UNCOMPARABLE) return folderLevelSecondary
 | 
			
		||||
				const defaultForUnspecified: number = getSorterFnFor(CustomSortOrder.default, undefined, SortingLevelId.forDefaultWhenUnspecified)(itA, itB)
 | 
			
		||||
				return defaultForUnspecified
 | 
			
		||||
| 
						 | 
				
			
			@ -552,10 +553,10 @@ export const determineSortingGroup = function (entry: TFile | TFolder, spec: Cus
 | 
			
		|||
 | 
			
		||||
	if (determined && determinedGroupIdx !== undefined) {  // <-- defensive code, maybe too defensive
 | 
			
		||||
		const group: CustomSortGroup = spec.groups[determinedGroupIdx];
 | 
			
		||||
		const isPrimaryOrderByMetadata: boolean = isByMetadata(group?.order)
 | 
			
		||||
		const isSecondaryOrderByMetadata: boolean = isByMetadata(group?.secondaryOrder)
 | 
			
		||||
		const isDerivedPrimaryByMetadata: boolean = isByMetadata(spec.defaultOrder)
 | 
			
		||||
		const isDerivedSecondaryByMetadata: boolean = isByMetadata(spec.defaultSecondaryOrder)
 | 
			
		||||
		const isPrimaryOrderByMetadata: boolean = isByMetadata(group?.sorting?.order)
 | 
			
		||||
		const isSecondaryOrderByMetadata: boolean = isByMetadata(group?.secondarySorting?.order)
 | 
			
		||||
		const isDerivedPrimaryByMetadata: boolean = isByMetadata(spec.defaultSorting?.order)
 | 
			
		||||
		const isDerivedSecondaryByMetadata: boolean = isByMetadata(spec.defaultSecondarySorting?.order)
 | 
			
		||||
		if (isPrimaryOrderByMetadata || isSecondaryOrderByMetadata || isDerivedPrimaryByMetadata || isDerivedSecondaryByMetadata) {
 | 
			
		||||
			if (ctx?._mCache) {
 | 
			
		||||
				// For folders - scan metadata of 'folder note'
 | 
			
		||||
| 
						 | 
				
			
			@ -571,26 +572,26 @@ export const determineSortingGroup = function (entry: TFile | TFolder, spec: Cus
 | 
			
		|||
				}
 | 
			
		||||
				if (isPrimaryOrderByMetadata) metadataValueToSortBy =
 | 
			
		||||
					mdataValueFromFMCaches (
 | 
			
		||||
						group?.byMetadataField || group?.withMetadataFieldName || DEFAULT_METADATA_FIELD_FOR_SORTING,
 | 
			
		||||
						group?.metadataFieldValueExtractor,
 | 
			
		||||
						group.sorting!.byMetadata || group.withMetadataFieldName || DEFAULT_METADATA_FIELD_FOR_SORTING,
 | 
			
		||||
						group.sorting!.metadataValueExtractor,
 | 
			
		||||
						frontMatterCache,
 | 
			
		||||
						prioFrontMatterCache)
 | 
			
		||||
				if (isSecondaryOrderByMetadata) metadataValueSecondaryToSortBy =
 | 
			
		||||
					mdataValueFromFMCaches (
 | 
			
		||||
						group?.byMetadataFieldSecondary || group?.withMetadataFieldName || DEFAULT_METADATA_FIELD_FOR_SORTING,
 | 
			
		||||
						group?.metadataFieldSecondaryValueExtractor,
 | 
			
		||||
						group.secondarySorting!.byMetadata || group.withMetadataFieldName || DEFAULT_METADATA_FIELD_FOR_SORTING,
 | 
			
		||||
						group.secondarySorting!.metadataValueExtractor,
 | 
			
		||||
						frontMatterCache,
 | 
			
		||||
						prioFrontMatterCache)
 | 
			
		||||
				if (isDerivedPrimaryByMetadata) metadataValueDerivedPrimaryToSortBy =
 | 
			
		||||
					mdataValueFromFMCaches (
 | 
			
		||||
						spec.byMetadataField || DEFAULT_METADATA_FIELD_FOR_SORTING,
 | 
			
		||||
						spec.metadataFieldValueExtractor,
 | 
			
		||||
						spec.defaultSorting!.byMetadata || DEFAULT_METADATA_FIELD_FOR_SORTING,
 | 
			
		||||
						spec.defaultSorting!.metadataValueExtractor,
 | 
			
		||||
						frontMatterCache,
 | 
			
		||||
						prioFrontMatterCache)
 | 
			
		||||
				if (isDerivedSecondaryByMetadata) metadataValueDerivedSecondaryToSortBy =
 | 
			
		||||
					mdataValueFromFMCaches (
 | 
			
		||||
						spec.byMetadataFieldSecondary || DEFAULT_METADATA_FIELD_FOR_SORTING,
 | 
			
		||||
						spec.metadataFieldSecondaryValueExtractor,
 | 
			
		||||
						spec.defaultSecondarySorting!.byMetadata || DEFAULT_METADATA_FIELD_FOR_SORTING,
 | 
			
		||||
						spec.defaultSecondarySorting!.metadataValueExtractor,
 | 
			
		||||
						frontMatterCache,
 | 
			
		||||
						prioFrontMatterCache)
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -692,12 +693,12 @@ export const determineDatesForFolder = (folder: TFolder, recursive?: boolean): [
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
export const determineFolderDatesIfNeeded = (folderItems: Array<FolderItemForSorting>, sortingSpec: CustomSortSpec) => {
 | 
			
		||||
	const foldersDatesNeeded = sortOrderNeedsFolderDates(sortingSpec.defaultOrder, sortingSpec.defaultSecondaryOrder)
 | 
			
		||||
	const foldersDeepDatesNeeded = sortOrderNeedsFolderDeepDates(sortingSpec.defaultOrder, sortingSpec.defaultSecondaryOrder)
 | 
			
		||||
	const foldersDatesNeeded = sortOrderNeedsFolderDates(sortingSpec.defaultSorting?.order, sortingSpec.defaultSecondarySorting?.order)
 | 
			
		||||
	const foldersDeepDatesNeeded = sortOrderNeedsFolderDeepDates(sortingSpec.defaultSorting?.order, sortingSpec.defaultSecondarySorting?.order)
 | 
			
		||||
 | 
			
		||||
	const groupOrders = sortingSpec.groups?.map((group) => ({
 | 
			
		||||
		foldersDatesNeeded: sortOrderNeedsFolderDates(group.order, group.secondaryOrder),
 | 
			
		||||
		foldersDeepDatesNeeded: sortOrderNeedsFolderDeepDates(group.order, group.secondaryOrder)
 | 
			
		||||
		foldersDatesNeeded: sortOrderNeedsFolderDates(group.sorting?.order, group.secondarySorting?.order),
 | 
			
		||||
		foldersDeepDatesNeeded: sortOrderNeedsFolderDeepDates(group.sorting?.order, group.secondarySorting?.order)
 | 
			
		||||
	}))
 | 
			
		||||
 | 
			
		||||
	folderItems.forEach((item) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -717,15 +718,15 @@ export const determineFolderDatesIfNeeded = (folderItems: Array<FolderItemForSor
 | 
			
		|||
export const determineBookmarksOrderIfNeeded = (folderItems: Array<FolderItemForSorting>, sortingSpec: CustomSortSpec, plugin: BookmarksPluginInterface) => {
 | 
			
		||||
	if (!plugin) return
 | 
			
		||||
 | 
			
		||||
	const folderDefaultSortRequiresBookmarksOrder: boolean = !!(sortingSpec.defaultOrder && sortOrderNeedsBookmarksOrder(sortingSpec.defaultOrder, sortingSpec.defaultSecondaryOrder))
 | 
			
		||||
	const folderDefaultSortRequiresBookmarksOrder: boolean = !!(sortingSpec.defaultSorting && sortOrderNeedsBookmarksOrder(sortingSpec.defaultSorting.order, sortingSpec.defaultSecondarySorting?.order))
 | 
			
		||||
 | 
			
		||||
	folderItems.forEach((item) => {
 | 
			
		||||
		let groupSortRequiresBookmarksOrder: boolean = false
 | 
			
		||||
		if (!folderDefaultSortRequiresBookmarksOrder) {
 | 
			
		||||
			const groupIdx: number | undefined = item.groupIdx
 | 
			
		||||
			if (groupIdx !== undefined) {
 | 
			
		||||
				const groupOrder: CustomSortOrder | undefined = sortingSpec.groups[groupIdx].order
 | 
			
		||||
				const groupSecondaryOrder: CustomSortOrder | undefined = sortingSpec.groups[groupIdx].secondaryOrder
 | 
			
		||||
				const groupOrder: CustomSortOrder | undefined = sortingSpec.groups[groupIdx].sorting?.order
 | 
			
		||||
				const groupSecondaryOrder: CustomSortOrder | undefined = sortingSpec.groups[groupIdx].secondarySorting?.order
 | 
			
		||||
				groupSortRequiresBookmarksOrder = sortOrderNeedsBookmarksOrder(groupOrder, groupSecondaryOrder)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
import {
 | 
			
		||||
	CustomSort,
 | 
			
		||||
	CustomSortGroup,
 | 
			
		||||
	CustomSortGroupType,
 | 
			
		||||
	CustomSortOrder,
 | 
			
		||||
| 
						 | 
				
			
			@ -6,7 +7,7 @@ import {
 | 
			
		|||
	DEFAULT_METADATA_FIELD_FOR_SORTING,
 | 
			
		||||
	IdentityNormalizerFn,
 | 
			
		||||
	NormalizerFn,
 | 
			
		||||
	RecognizedOrderValue,
 | 
			
		||||
	RecognizedSorting,
 | 
			
		||||
	RegExpSpec
 | 
			
		||||
} from "./custom-sort-types";
 | 
			
		||||
import {isDefined, last} from "../utils/utils";
 | 
			
		||||
| 
						 | 
				
			
			@ -115,12 +116,6 @@ interface CustomSortOrderAscDescPair {
 | 
			
		|||
	desc: CustomSortOrder
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface CustomSortOrderSpec {
 | 
			
		||||
	order: CustomSortOrder
 | 
			
		||||
	byMetadataField?: string
 | 
			
		||||
	metadataFieldExtractor?: MDataExtractor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const MAX_SORT_LEVEL: number = 1
 | 
			
		||||
 | 
			
		||||
// remember about .toLowerCase() before comparison!
 | 
			
		||||
| 
						 | 
				
			
			@ -1090,34 +1085,28 @@ export class SortingSpecProcessor {
 | 
			
		|||
				if (!this.ctx.currentSpec) {
 | 
			
		||||
					this.ctx.currentSpec = this.putNewSpecForNewTargetFolder()
 | 
			
		||||
				}
 | 
			
		||||
				if (this.ctx.currentSpec.defaultOrder) {
 | 
			
		||||
				if (this.ctx.currentSpec.defaultSorting) {
 | 
			
		||||
					const folderPathsForProblemMsg: string = this.ctx.currentSpec.targetFoldersPaths.join(' :: ');
 | 
			
		||||
					this.problem(ProblemCode.DuplicateOrderAttr, `Duplicate order specification for folder(s) ${folderPathsForProblemMsg}`)
 | 
			
		||||
					return false;
 | 
			
		||||
				}
 | 
			
		||||
				this.ctx.currentSpec.defaultOrder = (attr.value as RecognizedOrderValue).order
 | 
			
		||||
				this.ctx.currentSpec.byMetadataField = (attr.value as RecognizedOrderValue).applyToMetadataField
 | 
			
		||||
				this.ctx.currentSpec.metadataFieldValueExtractor = (attr.value as RecognizedOrderValue).metadataValueExtractor
 | 
			
		||||
				this.ctx.currentSpec.defaultSecondaryOrder = (attr.value as RecognizedOrderValue).secondaryOrder
 | 
			
		||||
				this.ctx.currentSpec.byMetadataFieldSecondary = (attr.value as RecognizedOrderValue).secondaryApplyToMetadataField
 | 
			
		||||
				this.ctx.currentSpec.metadataFieldSecondaryValueExtractor = (attr.value as RecognizedOrderValue).secondaryMetadataValueExtractor
 | 
			
		||||
				const rs: RecognizedSorting = attr.value  // Syntax sugar
 | 
			
		||||
				this.ctx.currentSpec.defaultSorting = rs.primary
 | 
			
		||||
				this.ctx.currentSpec.defaultSecondarySorting = rs.secondary
 | 
			
		||||
				return true;
 | 
			
		||||
			} else if (attr.nesting > 0) { // For now only distinguishing nested (indented) and not-nested (not-indented), the depth doesn't matter
 | 
			
		||||
				if (!this.ctx.currentSpec || !this.ctx.currentSpecGroup) {
 | 
			
		||||
					this.problem(ProblemCode.DanglingOrderAttr, `Nested (indented) attribute requires prior sorting group definition`)
 | 
			
		||||
					return false;
 | 
			
		||||
				}
 | 
			
		||||
				if (this.ctx.currentSpecGroup.order) {
 | 
			
		||||
				if (this.ctx.currentSpecGroup.sorting) {
 | 
			
		||||
					const folderPathsForProblemMsg: string = this.ctx.currentSpec.targetFoldersPaths.join(' :: ');
 | 
			
		||||
					this.problem(ProblemCode.DuplicateOrderAttr, `Duplicate order specification for a sorting rule of folder ${folderPathsForProblemMsg}`)
 | 
			
		||||
					return false;
 | 
			
		||||
				}
 | 
			
		||||
				this.ctx.currentSpecGroup.order = (attr.value as RecognizedOrderValue).order
 | 
			
		||||
				this.ctx.currentSpecGroup.byMetadataField = (attr.value as RecognizedOrderValue).applyToMetadataField
 | 
			
		||||
				this.ctx.currentSpecGroup.metadataFieldValueExtractor = (attr.value as RecognizedOrderValue).metadataValueExtractor
 | 
			
		||||
				this.ctx.currentSpecGroup.secondaryOrder = (attr.value as RecognizedOrderValue).secondaryOrder
 | 
			
		||||
				this.ctx.currentSpecGroup.byMetadataFieldSecondary = (attr.value as RecognizedOrderValue).secondaryApplyToMetadataField
 | 
			
		||||
				this.ctx.currentSpecGroup.metadataFieldSecondaryValueExtractor = (attr.value as RecognizedOrderValue).secondaryMetadataValueExtractor
 | 
			
		||||
				const rs: RecognizedSorting = attr.value  // Syntax sugar
 | 
			
		||||
				this.ctx.currentSpecGroup.sorting = rs.primary
 | 
			
		||||
				this.ctx.currentSpecGroup.secondarySorting = rs.secondary
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -1406,7 +1395,7 @@ export class SortingSpecProcessor {
 | 
			
		|||
					currentCombinedGroupIdx = i
 | 
			
		||||
				} else {
 | 
			
		||||
					// Ensure that the preceding group doesn't contain sorting order
 | 
			
		||||
					if (spec.groups[i - 1].order) {
 | 
			
		||||
					if (spec.groups[i - 1].sorting) {
 | 
			
		||||
						this.problem(ProblemCode.OnlyLastCombinedGroupCanSpecifyOrder, 'Predecessor group of combined group cannot contain order specification. Put it at the last of group in combined groups')
 | 
			
		||||
						return false
 | 
			
		||||
					}
 | 
			
		||||
| 
						 | 
				
			
			@ -1421,34 +1410,26 @@ export class SortingSpecProcessor {
 | 
			
		|||
 | 
			
		||||
		// Populate sorting order within combined groups
 | 
			
		||||
		if (anyCombinedGroupPresent) {
 | 
			
		||||
			let orderForCombinedGroup: CustomSortOrder | undefined
 | 
			
		||||
			let byMetadataFieldForCombinedGroup: string | undefined
 | 
			
		||||
			let secondaryOrderForCombinedGroup: CustomSortOrder | undefined
 | 
			
		||||
			let secondaryByMetadataFieldForCombinedGroup: string | undefined
 | 
			
		||||
			let sortingForCombinedGroup: CustomSort|undefined
 | 
			
		||||
			let secondarySortingForCombinedGroup: CustomSort|undefined
 | 
			
		||||
			let idxOfCurrentCombinedGroup: number | undefined = undefined
 | 
			
		||||
			for (let i = spec.groups.length - 1; i >= 0; i--) {
 | 
			
		||||
				const group: CustomSortGroup = spec.groups[i]
 | 
			
		||||
 | 
			
		||||
				if (group.combineWithIdx !== undefined) {
 | 
			
		||||
					if (group.combineWithIdx === idxOfCurrentCombinedGroup) { // a subsequent (2nd, 3rd, ...) group of combined (counting from the end)
 | 
			
		||||
						group.order = orderForCombinedGroup
 | 
			
		||||
						group.byMetadataField = byMetadataFieldForCombinedGroup
 | 
			
		||||
						group.secondaryOrder = secondaryOrderForCombinedGroup
 | 
			
		||||
						group.byMetadataFieldSecondary = secondaryByMetadataFieldForCombinedGroup
 | 
			
		||||
						group.sorting = sortingForCombinedGroup
 | 
			
		||||
						group.secondarySorting = secondarySortingForCombinedGroup
 | 
			
		||||
					} else { // the first group of combined (counting from the end)
 | 
			
		||||
						idxOfCurrentCombinedGroup = group.combineWithIdx
 | 
			
		||||
						orderForCombinedGroup = group.order // could be undefined
 | 
			
		||||
						byMetadataFieldForCombinedGroup = group.byMetadataField // could be undefined
 | 
			
		||||
						secondaryOrderForCombinedGroup = group.secondaryOrder // could be undefined
 | 
			
		||||
						secondaryByMetadataFieldForCombinedGroup = group.byMetadataFieldSecondary // could be undefined
 | 
			
		||||
						sortingForCombinedGroup = group.sorting
 | 
			
		||||
						secondarySortingForCombinedGroup = group.secondarySorting
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					// for sanity
 | 
			
		||||
					idxOfCurrentCombinedGroup = undefined
 | 
			
		||||
					orderForCombinedGroup = undefined
 | 
			
		||||
					byMetadataFieldForCombinedGroup = undefined
 | 
			
		||||
					secondaryOrderForCombinedGroup = undefined
 | 
			
		||||
					secondaryByMetadataFieldForCombinedGroup = undefined
 | 
			
		||||
					sortingForCombinedGroup = undefined
 | 
			
		||||
					secondarySortingForCombinedGroup = undefined
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -1490,13 +1471,13 @@ export class SortingSpecProcessor {
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private internalValidateOrderAttrValue = (sortOrderSpecText: string, prefixLexeme: string): Array<CustomSortOrderSpec>|AttrError|null => {
 | 
			
		||||
	private internalValidateOrderAttrValue = (sortOrderSpecText: string, prefixLexeme: string): Array<CustomSort>|AttrError|null => {
 | 
			
		||||
		if (sortOrderSpecText.indexOf(CommentPrefix) >= 0) {
 | 
			
		||||
			sortOrderSpecText = sortOrderSpecText.substring(0, sortOrderSpecText.indexOf(CommentPrefix))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		const sortLevels: Array<string> = `${prefixLexeme||''} ${sortOrderSpecText}`.trim().split(OrderLevelsSeparator)
 | 
			
		||||
		let sortOrderSpec: Array<CustomSortOrderSpec> = []
 | 
			
		||||
		let sortOrderSpec: Array<CustomSort> = []
 | 
			
		||||
 | 
			
		||||
		// Max two levels are supported, excess levels specs are ignored
 | 
			
		||||
		for (let level: number = 0; level <= MAX_SORT_LEVEL && level < sortLevels.length; level++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1592,22 +1573,18 @@ export class SortingSpecProcessor {
 | 
			
		|||
			}
 | 
			
		||||
			sortOrderSpec[level] = {
 | 
			
		||||
				order: order!,
 | 
			
		||||
				byMetadataField: metadataName,
 | 
			
		||||
				metadataFieldExtractor: metadataExtractor
 | 
			
		||||
				byMetadata: metadataName,
 | 
			
		||||
				metadataValueExtractor: metadataExtractor
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return sortOrderSpec
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private validateOrderAttrValue: AttrValueValidatorFn = (v: string, attr: Attribute, attrLexeme: string): RecognizedOrderValue|AttrError|null => {
 | 
			
		||||
		const recognized: Array<CustomSortOrderSpec>|AttrError|null = this.internalValidateOrderAttrValue(v, attrLexeme)
 | 
			
		||||
	private validateOrderAttrValue: AttrValueValidatorFn = (v: string, attr: Attribute, attrLexeme: string): RecognizedSorting|AttrError|null => {
 | 
			
		||||
		const recognized: Array<CustomSort>|AttrError|null = this.internalValidateOrderAttrValue(v, attrLexeme)
 | 
			
		||||
		return recognized ? (recognized instanceof AttrError ? recognized : {
 | 
			
		||||
			order: recognized[0].order,
 | 
			
		||||
			applyToMetadataField: recognized[0].byMetadataField,
 | 
			
		||||
			metadataValueExtractor: recognized[0].metadataFieldExtractor,
 | 
			
		||||
			secondaryOrder: recognized[1]?.order,
 | 
			
		||||
			secondaryApplyToMetadataField: recognized[1]?.byMetadataField,
 | 
			
		||||
			secondaryMetadataValueExtractor: recognized[1]?.metadataFieldExtractor
 | 
			
		||||
			primary: recognized[0],
 | 
			
		||||
			secondary: recognized[1]
 | 
			
		||||
		}) : null;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,7 +29,7 @@ describe('determineFolderDatesIfNeeded', () => {
 | 
			
		|||
            targetFoldersPaths: ['/'],
 | 
			
		||||
            groups: [{
 | 
			
		||||
                type: CustomSortGroupType.Outsiders,
 | 
			
		||||
                order: CustomSortOrder.alphabetical
 | 
			
		||||
                sorting: { order: CustomSortOrder.alphabetical }
 | 
			
		||||
            }],
 | 
			
		||||
            outsidersGroupIdx: OUTSIDERS_GROUP_IDX
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -58,10 +58,10 @@ describe('determineFolderDatesIfNeeded', () => {
 | 
			
		|||
        const OUTSIDERS_GROUP_IDX = 0
 | 
			
		||||
        const sortSpec: CustomSortSpec = {
 | 
			
		||||
            targetFoldersPaths: ['/'],
 | 
			
		||||
            defaultOrder: folderOrder,
 | 
			
		||||
            defaultSorting: folderOrder ? { order: folderOrder } : undefined,
 | 
			
		||||
            groups: [{
 | 
			
		||||
                type: CustomSortGroupType.Outsiders,
 | 
			
		||||
                order: order
 | 
			
		||||
                sorting: { order: order }
 | 
			
		||||
            }],
 | 
			
		||||
            outsidersGroupIdx: OUTSIDERS_GROUP_IDX
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -90,10 +90,10 @@ describe('determineFolderDatesIfNeeded', () => {
 | 
			
		|||
        const OUTSIDERS_GROUP_IDX = 0
 | 
			
		||||
        const sortSpec: CustomSortSpec = {
 | 
			
		||||
            targetFoldersPaths: ['/'],
 | 
			
		||||
            defaultOrder: folderOrder,
 | 
			
		||||
            defaultSorting: folderOrder ? { order: folderOrder} : undefined,
 | 
			
		||||
            groups: [{
 | 
			
		||||
                type: CustomSortGroupType.Outsiders,
 | 
			
		||||
                order: order
 | 
			
		||||
                sorting: { order: order }
 | 
			
		||||
            }],
 | 
			
		||||
            outsidersGroupIdx: OUTSIDERS_GROUP_IDX
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,18 +14,18 @@ const FlatLevelSortSpec: CustomSortSpec = {
 | 
			
		|||
	groups: [{  // Not relevant in unit test
 | 
			
		||||
		exactText: "Nothing",
 | 
			
		||||
		filesOnly: true,
 | 
			
		||||
		order: CustomSortOrder.alphabetical,
 | 
			
		||||
		sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
		type: CustomSortGroupType.ExactName
 | 
			
		||||
	},{  // prepared for unit test
 | 
			
		||||
		exactPrefix: "Fi",
 | 
			
		||||
		order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
		sorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse, },
 | 
			
		||||
		type: CustomSortGroupType.ExactPrefix
 | 
			
		||||
	},{  // Not relevant in unit test
 | 
			
		||||
		type: CustomSortGroupType.Outsiders,
 | 
			
		||||
		order: CustomSortOrder.byCreatedTime
 | 
			
		||||
		sorting: { order: CustomSortOrder.byCreatedTime },
 | 
			
		||||
	}],
 | 
			
		||||
	outsidersGroupIdx: 2,
 | 
			
		||||
	defaultOrder: CustomSortOrder.byCreatedTime,
 | 
			
		||||
	defaultSorting: { order: CustomSortOrder.byCreatedTime, },
 | 
			
		||||
	targetFoldersPaths: ['parent folder']
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -33,19 +33,19 @@ const MultiLevelSortSpecGroupLevel: CustomSortSpec = {
 | 
			
		|||
	groups: [{  // Not relevant in unit test
 | 
			
		||||
		exactText: "Nothing",
 | 
			
		||||
		filesOnly: true,
 | 
			
		||||
		order: CustomSortOrder.alphabetical,
 | 
			
		||||
		sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
		type: CustomSortGroupType.ExactName
 | 
			
		||||
	},{  // prepared for unit test
 | 
			
		||||
		exactPrefix: "Fi",
 | 
			
		||||
		order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
		secondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
		sorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse, },
 | 
			
		||||
		secondarySorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabetical, },
 | 
			
		||||
		type: CustomSortGroupType.ExactPrefix
 | 
			
		||||
	},{  // Not relevant in unit test
 | 
			
		||||
		type: CustomSortGroupType.Outsiders,
 | 
			
		||||
		order: CustomSortOrder.byCreatedTime
 | 
			
		||||
		sorting: { order: CustomSortOrder.byCreatedTime },
 | 
			
		||||
	}],
 | 
			
		||||
	outsidersGroupIdx: 2,
 | 
			
		||||
	defaultOrder: CustomSortOrder.byCreatedTime,
 | 
			
		||||
	defaultSorting: { order: CustomSortOrder.byCreatedTime, },
 | 
			
		||||
	targetFoldersPaths: ['parent folder']
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -53,19 +53,19 @@ const MultiLevelSortSpecTargetFolderLevel: CustomSortSpec = {
 | 
			
		|||
	groups: [{  // Not relevant in unit test
 | 
			
		||||
		exactText: "Nothing",
 | 
			
		||||
		filesOnly: true,
 | 
			
		||||
		order: CustomSortOrder.alphabetical,
 | 
			
		||||
		sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
		type: CustomSortGroupType.ExactName
 | 
			
		||||
	},{  // prepared for unit test
 | 
			
		||||
		exactPrefix: "Fi",
 | 
			
		||||
		order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
		sorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse, },
 | 
			
		||||
		type: CustomSortGroupType.ExactPrefix
 | 
			
		||||
	},{  // Not relevant in unit test
 | 
			
		||||
		type: CustomSortGroupType.Outsiders,
 | 
			
		||||
		order: CustomSortOrder.byCreatedTime
 | 
			
		||||
		sorting: { order: CustomSortOrder.byCreatedTime },
 | 
			
		||||
	}],
 | 
			
		||||
	outsidersGroupIdx: 2,
 | 
			
		||||
	defaultOrder: CustomSortOrder.byCreatedTime,
 | 
			
		||||
	defaultSecondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse,
 | 
			
		||||
	defaultSorting: { order: CustomSortOrder.byCreatedTime, },
 | 
			
		||||
	defaultSecondarySorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse, },
 | 
			
		||||
	targetFoldersPaths: ['parent folder']
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -73,20 +73,20 @@ const MultiLevelSortSpecAndTargetFolderLevel: CustomSortSpec = {
 | 
			
		|||
	groups: [{  // Not relevant in unit test
 | 
			
		||||
		exactText: "Nothing",
 | 
			
		||||
		filesOnly: true,
 | 
			
		||||
		order: CustomSortOrder.alphabetical,
 | 
			
		||||
		sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
		type: CustomSortGroupType.ExactName
 | 
			
		||||
	},{  // prepared for unit test
 | 
			
		||||
		exactPrefix: "Fi",
 | 
			
		||||
		order: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
		secondaryOrder: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
		sorting: { order: CustomSortOrder.byMetadataFieldAlphabetical, },
 | 
			
		||||
		secondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse, },
 | 
			
		||||
		type: CustomSortGroupType.ExactPrefix
 | 
			
		||||
	},{  // Not relevant in unit test
 | 
			
		||||
		type: CustomSortGroupType.Outsiders,
 | 
			
		||||
		order: CustomSortOrder.byCreatedTime
 | 
			
		||||
		sorting: { order: CustomSortOrder.byCreatedTime },
 | 
			
		||||
	}],
 | 
			
		||||
	outsidersGroupIdx: 2,
 | 
			
		||||
	defaultOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
	defaultSecondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse,
 | 
			
		||||
	defaultSorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabetical, },
 | 
			
		||||
	defaultSecondarySorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse, },
 | 
			
		||||
	targetFoldersPaths: ['parent folder']
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,7 +61,7 @@ describe('hasOnlyByBookmarkOrStandardObsidian and collectSortingAndGroupingTypes
 | 
			
		|||
    })
 | 
			
		||||
    it('should detect not matching default order', () => {
 | 
			
		||||
        const spec: Partial<CustomSortSpec>|undefined = {
 | 
			
		||||
            defaultOrder: CustomSortOrder.default,
 | 
			
		||||
            defaultSorting: { order: CustomSortOrder.default },
 | 
			
		||||
            groups: [
 | 
			
		||||
                {
 | 
			
		||||
                    type: CustomSortGroupType.ExactName,
 | 
			
		||||
| 
						 | 
				
			
			@ -79,8 +79,8 @@ describe('hasOnlyByBookmarkOrStandardObsidian and collectSortingAndGroupingTypes
 | 
			
		|||
    })
 | 
			
		||||
    it('should detect not matching default secondary order', () => {
 | 
			
		||||
        const spec: Partial<CustomSortSpec>|undefined = {
 | 
			
		||||
            defaultOrder: CustomSortOrder.byBookmarkOrder,
 | 
			
		||||
            defaultSecondaryOrder: CustomSortOrder.default,
 | 
			
		||||
            defaultSorting: { order: CustomSortOrder.byBookmarkOrder },
 | 
			
		||||
            defaultSecondarySorting: { order: CustomSortOrder.default },
 | 
			
		||||
            groups: [
 | 
			
		||||
                {
 | 
			
		||||
                    type: CustomSortGroupType.BookmarkedOnly,
 | 
			
		||||
| 
						 | 
				
			
			@ -98,12 +98,12 @@ describe('hasOnlyByBookmarkOrStandardObsidian and collectSortingAndGroupingTypes
 | 
			
		|||
    })
 | 
			
		||||
    it('should detect not matching order in group', () => {
 | 
			
		||||
        const spec: Partial<CustomSortSpec>|undefined = {
 | 
			
		||||
            defaultOrder: CustomSortOrder.byBookmarkOrder,
 | 
			
		||||
            defaultSecondaryOrder: CustomSortOrder.standardObsidian,
 | 
			
		||||
            defaultSorting: { order: CustomSortOrder.byBookmarkOrder },
 | 
			
		||||
            defaultSecondarySorting: { order: CustomSortOrder.standardObsidian },
 | 
			
		||||
            groups: [
 | 
			
		||||
                {
 | 
			
		||||
                    type: CustomSortGroupType.ExactName,
 | 
			
		||||
                    order: CustomSortOrder.byCreatedTimeReverse
 | 
			
		||||
                    sorting: { order: CustomSortOrder.byCreatedTimeReverse }
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    type: CustomSortGroupType.Outsiders,
 | 
			
		||||
| 
						 | 
				
			
			@ -118,18 +118,18 @@ describe('hasOnlyByBookmarkOrStandardObsidian and collectSortingAndGroupingTypes
 | 
			
		|||
    })
 | 
			
		||||
    it('should detect not matching secondary order in group', () => {
 | 
			
		||||
        const spec: Partial<CustomSortSpec>|undefined = {
 | 
			
		||||
            defaultOrder: CustomSortOrder.byBookmarkOrder,
 | 
			
		||||
            defaultSecondaryOrder: CustomSortOrder.standardObsidian,
 | 
			
		||||
            defaultSorting: { order: CustomSortOrder.byBookmarkOrder },
 | 
			
		||||
            defaultSecondarySorting: { order: CustomSortOrder.standardObsidian },
 | 
			
		||||
            groups: [
 | 
			
		||||
                {
 | 
			
		||||
                    type: CustomSortGroupType.ExactName,
 | 
			
		||||
                    order: CustomSortOrder.byBookmarkOrderReverse,
 | 
			
		||||
                    secondaryOrder: CustomSortOrder.standardObsidian
 | 
			
		||||
                    sorting: { order: CustomSortOrder.byBookmarkOrderReverse },
 | 
			
		||||
                    secondarySorting: { order: CustomSortOrder.standardObsidian }
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    type: CustomSortGroupType.Outsiders,
 | 
			
		||||
                    order: CustomSortOrder.byBookmarkOrder,
 | 
			
		||||
                    secondaryOrder: CustomSortOrder.alphabetical
 | 
			
		||||
                    sorting: { order: CustomSortOrder.byBookmarkOrder },
 | 
			
		||||
                    secondarySorting: { order: CustomSortOrder.alphabetical }
 | 
			
		||||
                }
 | 
			
		||||
            ]
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -141,18 +141,18 @@ describe('hasOnlyByBookmarkOrStandardObsidian and collectSortingAndGroupingTypes
 | 
			
		|||
    })
 | 
			
		||||
    it('should detect matching orders at all levels', () => {
 | 
			
		||||
        const spec: Partial<CustomSortSpec>|undefined = {
 | 
			
		||||
            defaultOrder: CustomSortOrder.byBookmarkOrder,
 | 
			
		||||
            defaultSecondaryOrder: CustomSortOrder.standardObsidian,
 | 
			
		||||
            defaultSorting: { order: CustomSortOrder.byBookmarkOrder },
 | 
			
		||||
            defaultSecondarySorting: { order: CustomSortOrder.standardObsidian },
 | 
			
		||||
            groups: [
 | 
			
		||||
                {
 | 
			
		||||
                    type: CustomSortGroupType.BookmarkedOnly,
 | 
			
		||||
                    order: CustomSortOrder.byBookmarkOrderReverse,
 | 
			
		||||
                    secondaryOrder: CustomSortOrder.standardObsidian
 | 
			
		||||
                    sorting: { order: CustomSortOrder.byBookmarkOrderReverse },
 | 
			
		||||
                    secondarySorting: { order: CustomSortOrder.standardObsidian }
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    type: CustomSortGroupType.Outsiders,
 | 
			
		||||
                    order: CustomSortOrder.byBookmarkOrder,
 | 
			
		||||
                    secondaryOrder: CustomSortOrder.byBookmarkOrderReverse
 | 
			
		||||
                    sorting: { order: CustomSortOrder.byBookmarkOrder },
 | 
			
		||||
                    secondarySorting: { order: CustomSortOrder.byBookmarkOrderReverse }
 | 
			
		||||
                }
 | 
			
		||||
            ]
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1469,9 +1469,10 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				targetFoldersPaths: ['/'],
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
					byMetadataField: 'metadata-field-for-sorting',
 | 
			
		||||
					exactPrefix: 'Ref',
 | 
			
		||||
					order: CustomSortOrder.byMetadataFieldAlphabetical
 | 
			
		||||
					sorting: { order: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
						byMetadata: 'metadata-field-for-sorting',
 | 
			
		||||
					},
 | 
			
		||||
				}]
 | 
			
		||||
			}
 | 
			
		||||
			const ctx: Partial<ProcessingContext> = {
 | 
			
		||||
| 
						 | 
				
			
			@ -1511,9 +1512,9 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				targetFoldersPaths: ['/'],
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
					byMetadataField: 'metadata-field-for-sorting',
 | 
			
		||||
					exactPrefix: 'Ref',
 | 
			
		||||
					order: CustomSortOrder.byMetadataFieldAlphabeticalReverse
 | 
			
		||||
					sorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
						byMetadata: 'metadata-field-for-sorting',},
 | 
			
		||||
				}]
 | 
			
		||||
			}
 | 
			
		||||
			const ctx: Partial<ProcessingContext> = {
 | 
			
		||||
| 
						 | 
				
			
			@ -1553,9 +1554,9 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				targetFoldersPaths: ['/'],
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
					byMetadataField: 'metadata-field-for-sorting',
 | 
			
		||||
					exactPrefix: 'Ref',
 | 
			
		||||
					order: CustomSortOrder.byMetadataFieldTrueAlphabetical
 | 
			
		||||
					sorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
						byMetadata: 'metadata-field-for-sorting', },
 | 
			
		||||
				}]
 | 
			
		||||
			}
 | 
			
		||||
			const ctx: Partial<ProcessingContext> = {
 | 
			
		||||
| 
						 | 
				
			
			@ -1595,9 +1596,9 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				targetFoldersPaths: ['/'],
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
					byMetadataField: 'metadata-field-for-sorting',
 | 
			
		||||
					exactPrefix: 'Ref',
 | 
			
		||||
					order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse
 | 
			
		||||
					sorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse,
 | 
			
		||||
						byMetadata: 'metadata-field-for-sorting', },
 | 
			
		||||
				}]
 | 
			
		||||
			}
 | 
			
		||||
			const ctx: Partial<ProcessingContext> = {
 | 
			
		||||
| 
						 | 
				
			
			@ -1638,8 +1639,8 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
					exactPrefix: 'Ref',
 | 
			
		||||
					byMetadataField: 'metadata-field-for-sorting',
 | 
			
		||||
					order: CustomSortOrder.byMetadataFieldAlphabeticalReverse
 | 
			
		||||
					sorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
						byMetadata: 'metadata-field-for-sorting', },
 | 
			
		||||
				}]
 | 
			
		||||
			}
 | 
			
		||||
			const ctx: Partial<ProcessingContext> = {
 | 
			
		||||
| 
						 | 
				
			
			@ -1681,10 +1682,11 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
					exactPrefix: 'Ref',
 | 
			
		||||
					order: CustomSortOrder.byMetadataFieldAlphabetical
 | 
			
		||||
					sorting: { order: CustomSortOrder.byMetadataFieldAlphabetical },
 | 
			
		||||
				}],
 | 
			
		||||
				defaultOrder: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
				byMetadataField: 'metadata-field-for-sorting-specified-on-target-folder'
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
					byMetadata: 'metadata-field-for-sorting-specified-on-target-folder'
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			const ctx: Partial<ProcessingContext> = {
 | 
			
		||||
				_mCache: {
 | 
			
		||||
| 
						 | 
				
			
			@ -1723,7 +1725,7 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				targetFoldersPaths: ['/'],
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.HasMetadataField,
 | 
			
		||||
					order: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
					sorting: { order: CustomSortOrder.byMetadataFieldAlphabetical, },
 | 
			
		||||
					withMetadataFieldName: 'field-used-with-with-metadata-syntax'
 | 
			
		||||
				}]
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -1765,7 +1767,7 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
					exactPrefix: 'Ref',
 | 
			
		||||
					order: CustomSortOrder.byMetadataFieldAlphabetical
 | 
			
		||||
					sorting: { order: CustomSortOrder.byMetadataFieldAlphabetical },
 | 
			
		||||
				}]
 | 
			
		||||
			}
 | 
			
		||||
			const ctx: Partial<ProcessingContext> = {
 | 
			
		||||
| 
						 | 
				
			
			@ -1808,10 +1810,10 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				targetFoldersPaths: ['/'],
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
					byMetadataFieldSecondary: 'metadata-field-for-sorting',
 | 
			
		||||
					exactPrefix: 'Ref',
 | 
			
		||||
					order: CustomSortOrder.alphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byMetadataFieldAlphabetical
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
						byMetadata: 'metadata-field-for-sorting', },
 | 
			
		||||
				}]
 | 
			
		||||
			}
 | 
			
		||||
			const ctx: Partial<ProcessingContext> = {
 | 
			
		||||
| 
						 | 
				
			
			@ -1851,10 +1853,10 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				targetFoldersPaths: ['/'],
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
					byMetadataFieldSecondary: 'metadata-field-for-sorting',
 | 
			
		||||
					exactPrefix: 'Ref',
 | 
			
		||||
					order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byMetadataFieldAlphabeticalReverse
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
						byMetadata: 'metadata-field-for-sorting', },
 | 
			
		||||
				}]
 | 
			
		||||
			}
 | 
			
		||||
			const ctx: Partial<ProcessingContext> = {
 | 
			
		||||
| 
						 | 
				
			
			@ -1894,11 +1896,11 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				targetFoldersPaths: ['/'],
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
					byMetadataField: 'non-existing-mdata',
 | 
			
		||||
					byMetadataFieldSecondary: 'metadata-field-for-sorting',
 | 
			
		||||
					exactPrefix: 'Ref',
 | 
			
		||||
					order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical
 | 
			
		||||
					sorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
						byMetadata: 'non-existing-mdata'},
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
						byMetadata: 'metadata-field-for-sorting'},
 | 
			
		||||
				}]
 | 
			
		||||
			}
 | 
			
		||||
			const ctx: Partial<ProcessingContext> = {
 | 
			
		||||
| 
						 | 
				
			
			@ -1938,11 +1940,13 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				targetFoldersPaths: ['/'],
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
					byMetadataField: 'metadata-field-for-sorting',
 | 
			
		||||
					byMetadataFieldSecondary: 'metadata-field-for-sorting secondary',
 | 
			
		||||
					exactPrefix: 'Ref',
 | 
			
		||||
					order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse
 | 
			
		||||
					sorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
						byMetadata: 'metadata-field-for-sorting',
 | 
			
		||||
					},
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse,
 | 
			
		||||
						byMetadata: 'metadata-field-for-sorting secondary',
 | 
			
		||||
					},
 | 
			
		||||
				}]
 | 
			
		||||
			}
 | 
			
		||||
			const ctx: Partial<ProcessingContext> = {
 | 
			
		||||
| 
						 | 
				
			
			@ -1985,9 +1989,10 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
					exactPrefix: 'Ref',
 | 
			
		||||
					byMetadataFieldSecondary: 'metadata-field-for-sorting',
 | 
			
		||||
					order: CustomSortOrder.standardObsidian,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byMetadataFieldAlphabeticalReverse
 | 
			
		||||
					sorting: { order: CustomSortOrder.standardObsidian },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
						byMetadata: 'metadata-field-for-sorting'
 | 
			
		||||
					},
 | 
			
		||||
				}]
 | 
			
		||||
			}
 | 
			
		||||
			const ctx: Partial<ProcessingContext> = {
 | 
			
		||||
| 
						 | 
				
			
			@ -2029,12 +2034,13 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
					exactPrefix: 'Ref',
 | 
			
		||||
					order: CustomSortOrder.trueAlphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byMetadataFieldAlphabetical
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabetical, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabetical },
 | 
			
		||||
				}],
 | 
			
		||||
				defaultOrder: CustomSortOrder.byCreatedTime,
 | 
			
		||||
				defaultSecondaryOrder: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
				byMetadataFieldSecondary: 'metadata-field-for-sorting-specified-on-target-folder'
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.byCreatedTime, },
 | 
			
		||||
				defaultSecondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
					byMetadata: 'metadata-field-for-sorting-specified-on-target-folder'
 | 
			
		||||
				},
 | 
			
		||||
			}
 | 
			
		||||
			const ctx: Partial<ProcessingContext> = {
 | 
			
		||||
				_mCache: {
 | 
			
		||||
| 
						 | 
				
			
			@ -2073,8 +2079,8 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				targetFoldersPaths: ['/'],
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.HasMetadataField,
 | 
			
		||||
					order: CustomSortOrder.standardObsidian,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
					sorting: { order: CustomSortOrder.standardObsidian, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabetical, },
 | 
			
		||||
					withMetadataFieldName: 'field-used-with-with-metadata-syntax'
 | 
			
		||||
				}]
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -2116,8 +2122,8 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
					exactPrefix: 'Ref',
 | 
			
		||||
					order: CustomSortOrder.byCreatedTimeReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byMetadataFieldAlphabetical
 | 
			
		||||
					sorting: { order: CustomSortOrder.byCreatedTimeReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabetical },
 | 
			
		||||
				}]
 | 
			
		||||
			}
 | 
			
		||||
			const ctx: Partial<ProcessingContext> = {
 | 
			
		||||
| 
						 | 
				
			
			@ -2161,15 +2167,19 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
					exactPrefix: 'Ref',
 | 
			
		||||
					order: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
					byMetadataField: 'mdata-for-primary',
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
					byMetadataFieldSecondary: 'mdata-for-secondary'
 | 
			
		||||
					sorting: { order: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
						byMetadata: 'mdata-for-primary',
 | 
			
		||||
					},
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
						byMetadata: 'mdata-for-secondary'
 | 
			
		||||
					},
 | 
			
		||||
				}],
 | 
			
		||||
				defaultOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
				byMetadataField: 'mdata-for-default-primary',
 | 
			
		||||
				defaultSecondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse,
 | 
			
		||||
				byMetadataFieldSecondary: 'mdata-for-default-secondary'
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
					byMetadata: 'mdata-for-default-primary',
 | 
			
		||||
				},
 | 
			
		||||
				defaultSecondarySorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse,
 | 
			
		||||
					byMetadata: 'mdata-for-default-secondary'
 | 
			
		||||
				},
 | 
			
		||||
			}
 | 
			
		||||
			const ctx: Partial<ProcessingContext> = {
 | 
			
		||||
				_mCache: {
 | 
			
		||||
| 
						 | 
				
			
			@ -2215,24 +2225,24 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
		const sortSpec: CustomSortSpec = {
 | 
			
		||||
			groups: [{
 | 
			
		||||
				filesOnly: true,
 | 
			
		||||
				order: CustomSortOrder.alphabetical,
 | 
			
		||||
				sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
				type: CustomSortGroupType.MatchAll
 | 
			
		||||
			}, {
 | 
			
		||||
				foldersOnly: true,
 | 
			
		||||
				order: CustomSortOrder.alphabetical,
 | 
			
		||||
				sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
				type: CustomSortGroupType.MatchAll
 | 
			
		||||
			}, {
 | 
			
		||||
				exactSuffix: "def!",
 | 
			
		||||
				priority: 2,
 | 
			
		||||
				order: CustomSortOrder.alphabetical,
 | 
			
		||||
				sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
				type: CustomSortGroupType.ExactSuffix
 | 
			
		||||
			}, {
 | 
			
		||||
				exactText: "Abcdef!",
 | 
			
		||||
				order: CustomSortOrder.alphabetical,
 | 
			
		||||
				sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
				priority: 3,
 | 
			
		||||
				type: CustomSortGroupType.ExactName
 | 
			
		||||
			}, {
 | 
			
		||||
				order: CustomSortOrder.alphabetical,
 | 
			
		||||
				sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
				type: CustomSortGroupType.Outsiders
 | 
			
		||||
			}],
 | 
			
		||||
			outsidersGroupIdx: 4,
 | 
			
		||||
| 
						 | 
				
			
			@ -2261,28 +2271,28 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
		const sortSpec: CustomSortSpec = {
 | 
			
		||||
			groups: [{
 | 
			
		||||
				exactSuffix: "def!",
 | 
			
		||||
				order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
				sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
				type: CustomSortGroupType.ExactSuffix
 | 
			
		||||
			}, {
 | 
			
		||||
				exactPrefix: "Hello :-)",
 | 
			
		||||
				order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
				sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
				type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
				combineWithIdx: 1
 | 
			
		||||
			}, {
 | 
			
		||||
				exactText: "Hello World :-)",
 | 
			
		||||
				order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
				sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
				type: CustomSortGroupType.ExactName,
 | 
			
		||||
				combineWithIdx: 1
 | 
			
		||||
			}, {
 | 
			
		||||
				filesOnly: true,
 | 
			
		||||
				order: CustomSortOrder.alphabetical,
 | 
			
		||||
				sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
				type: CustomSortGroupType.MatchAll
 | 
			
		||||
			}, {
 | 
			
		||||
				foldersOnly: true,
 | 
			
		||||
				order: CustomSortOrder.alphabetical,
 | 
			
		||||
				sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
				type: CustomSortGroupType.MatchAll
 | 
			
		||||
			}, {
 | 
			
		||||
				order: CustomSortOrder.alphabetical,
 | 
			
		||||
				sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
				type: CustomSortGroupType.Outsiders
 | 
			
		||||
			}],
 | 
			
		||||
			outsidersGroupIdx: 5,
 | 
			
		||||
| 
						 | 
				
			
			@ -2319,25 +2329,25 @@ describe('determineSortingGroup', () => {
 | 
			
		|||
		const sortSpec: CustomSortSpec = {
 | 
			
		||||
			groups: [{
 | 
			
		||||
				filesOnly: true,
 | 
			
		||||
				order: CustomSortOrder.alphabetical,
 | 
			
		||||
				sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
				type: CustomSortGroupType.MatchAll
 | 
			
		||||
			}, {
 | 
			
		||||
				foldersOnly: true,
 | 
			
		||||
				order: CustomSortOrder.alphabetical,
 | 
			
		||||
				sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
				type: CustomSortGroupType.MatchAll
 | 
			
		||||
			}, {
 | 
			
		||||
				exactSuffix: "def!",
 | 
			
		||||
				order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
				sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
				type: CustomSortGroupType.ExactSuffix,
 | 
			
		||||
				combineWithIdx: 2
 | 
			
		||||
			}, {
 | 
			
		||||
				exactText: "Hello :-)",
 | 
			
		||||
				order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
				sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
				type: CustomSortGroupType.ExactName,
 | 
			
		||||
				priority: 1,
 | 
			
		||||
				combineWithIdx: 2
 | 
			
		||||
			}, {
 | 
			
		||||
				order: CustomSortOrder.alphabetical,
 | 
			
		||||
				sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
				type: CustomSortGroupType.Outsiders
 | 
			
		||||
			}],
 | 
			
		||||
			outsidersGroupIdx: 4,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ import {
 | 
			
		|||
	detectSortingSymbols,
 | 
			
		||||
	escapeRegexUnsafeCharacters,
 | 
			
		||||
	extractSortingSymbol,
 | 
			
		||||
	FolderPathToSortSpecMap,
 | 
			
		||||
	hasMoreThanOneSortingSymbol,
 | 
			
		||||
	NumberNormalizerFn,
 | 
			
		||||
	RegexpUsedAs,
 | 
			
		||||
| 
						 | 
				
			
			@ -158,7 +159,7 @@ target-folder: Same rules as for References
 | 
			
		|||
 | 
			
		||||
const expectedSortSpecsExampleA: { [key: string]: CustomSortSpec } = {
 | 
			
		||||
	"mock-folder": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.alphabetical,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			foldersOnly: true,
 | 
			
		||||
			type: CustomSortGroupType.MatchAll
 | 
			
		||||
| 
						 | 
				
			
			@ -188,12 +189,14 @@ const expectedSortSpecsExampleA: { [key: string]: CustomSortSpec } = {
 | 
			
		|||
			filesOnly: true,
 | 
			
		||||
			type: CustomSortGroupType.HasMetadataField,
 | 
			
		||||
			withMetadataFieldName: 'sort-index-value',
 | 
			
		||||
			order: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
			byMetadataField: 'Some-dedicated-field',
 | 
			
		||||
			sorting: {
 | 
			
		||||
				order: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
				byMetadata: 'Some-dedicated-field',
 | 
			
		||||
			}
 | 
			
		||||
		}, {
 | 
			
		||||
			type: CustomSortGroupType.HasMetadataField,
 | 
			
		||||
			withMetadataFieldName: 'Pages',
 | 
			
		||||
			order: CustomSortOrder.byMetadataFieldAlphabeticalReverse
 | 
			
		||||
			sorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse },
 | 
			
		||||
		}, {
 | 
			
		||||
			type: CustomSortGroupType.HasIcon,
 | 
			
		||||
			filesOnly: true
 | 
			
		||||
| 
						 | 
				
			
			@ -217,17 +220,17 @@ const expectedSortSpecsExampleA: { [key: string]: CustomSortSpec } = {
 | 
			
		|||
		]
 | 
			
		||||
	},
 | 
			
		||||
	"folder of bookmarks": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.byBookmarkOrder,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.byBookmarkOrder, },
 | 
			
		||||
		groups: [
 | 
			
		||||
			{
 | 
			
		||||
				filesOnly: true,
 | 
			
		||||
				order: CustomSortOrder.byBookmarkOrder,
 | 
			
		||||
				sorting: { order: CustomSortOrder.byBookmarkOrder, },
 | 
			
		||||
				type: CustomSortGroupType.BookmarkedOnly
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				exactText: "Abc",
 | 
			
		||||
				foldersOnly: true,
 | 
			
		||||
				order: CustomSortOrder.byBookmarkOrderReverse,
 | 
			
		||||
				sorting: { order: CustomSortOrder.byBookmarkOrderReverse, },
 | 
			
		||||
				type: CustomSortGroupType.ExactName
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
| 
						 | 
				
			
			@ -257,11 +260,11 @@ const expectedSortSpecsExampleA: { [key: string]: CustomSortSpec } = {
 | 
			
		|||
			type: CustomSortGroupType.ExactPrefix
 | 
			
		||||
		}, {
 | 
			
		||||
			foldersOnly: true,
 | 
			
		||||
			order: CustomSortOrder.byModifiedTimeReverseAdvanced,
 | 
			
		||||
			sorting: { order: CustomSortOrder.byModifiedTimeReverseAdvanced, },
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}, {
 | 
			
		||||
			filesOnly: true,
 | 
			
		||||
			order: CustomSortOrder.byModifiedTime,
 | 
			
		||||
			sorting: { order: CustomSortOrder.byModifiedTime, },
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}, {
 | 
			
		||||
			exactPrefix: "Ref",
 | 
			
		||||
| 
						 | 
				
			
			@ -287,7 +290,7 @@ const expectedSortSpecsExampleA: { [key: string]: CustomSortSpec } = {
 | 
			
		|||
		targetFoldersPaths: ['/']
 | 
			
		||||
	},
 | 
			
		||||
	"Sandbox": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.byModifiedTimeReverse,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.byModifiedTimeReverse, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			exactText: "adfsasda",
 | 
			
		||||
			filesOnly: true,
 | 
			
		||||
| 
						 | 
				
			
			@ -295,12 +298,12 @@ const expectedSortSpecsExampleA: { [key: string]: CustomSortSpec } = {
 | 
			
		|||
		}, {
 | 
			
		||||
			exactText: "sdsadasdsa",
 | 
			
		||||
			foldersOnly: true,
 | 
			
		||||
			order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
			sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
			type: CustomSortGroupType.ExactName
 | 
			
		||||
		}, {
 | 
			
		||||
			exactText: "fdsfdsfdsfs",
 | 
			
		||||
			foldersOnly: true,
 | 
			
		||||
			order: CustomSortOrder.byCreatedTimeReverse,
 | 
			
		||||
			sorting: { order: CustomSortOrder.byCreatedTimeReverse, },
 | 
			
		||||
			type: CustomSortGroupType.ExactName
 | 
			
		||||
		}, {
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
| 
						 | 
				
			
			@ -309,20 +312,20 @@ const expectedSortSpecsExampleA: { [key: string]: CustomSortSpec } = {
 | 
			
		|||
		targetFoldersPaths: ['Sandbox']
 | 
			
		||||
	},
 | 
			
		||||
	"Abcd efgh ijk": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			exactPrefix: "Plain text spec bla bla bla (matches files and folders)",
 | 
			
		||||
			type: CustomSortGroupType.ExactPrefix
 | 
			
		||||
		}, {
 | 
			
		||||
			exactText: "files only matching",
 | 
			
		||||
			filesOnly: true,
 | 
			
		||||
			order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
			sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
			matchFilenameWithExt: true,
 | 
			
		||||
			type: CustomSortGroupType.ExactName
 | 
			
		||||
		}, {
 | 
			
		||||
			exactText: "folders only matching",
 | 
			
		||||
			foldersOnly: true,
 | 
			
		||||
			order: CustomSortOrder.alphabetical,
 | 
			
		||||
			sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
			type: CustomSortGroupType.ExactName
 | 
			
		||||
		}, {
 | 
			
		||||
			exactText: "some-file (or folder)",
 | 
			
		||||
| 
						 | 
				
			
			@ -444,15 +447,15 @@ Here goes ASCII word \\a+
 | 
			
		|||
\\[Mmm-dd-yyyy] for the specific date format of Apr-01-2024
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
// Tricky elements captured:
 | 
			
		||||
// - Order a-z. for by metadata is transformed to a-z (there is no notion of 'file extension' in metadata values)
 | 
			
		||||
 | 
			
		||||
const txtInputExampleMDataExtractors1: string = `
 | 
			
		||||
< a-z by-metadata: created-by using-extractor: date(dd/mm/yyyy)
 | 
			
		||||
/folders Chapter...
 | 
			
		||||
  > a-z by-metadata: updated-on using-extractor: date(mm/dd/yyyy)
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
// Tricky elements captured:
 | 
			
		||||
// - Order a-z. for by metadata is transformed to a-z (there is no notion of 'file extension' in metadata values)
 | 
			
		||||
 | 
			
		||||
const txtInputExampleMDataExtractors2: string = `
 | 
			
		||||
< a-z. by-metadata: created by using-extractor: date(mm/dd/yyyy), < true a-z. by-metadata: using-extractor: date(dd/mm/yyyy)
 | 
			
		||||
/folders ...Chapter
 | 
			
		||||
| 
						 | 
				
			
			@ -461,16 +464,20 @@ const txtInputExampleMDataExtractors2: string = `
 | 
			
		|||
 | 
			
		||||
const expectedSortSpecsExampleMDataExtractors1: { [key: string]: CustomSortSpec } = {
 | 
			
		||||
	"mock-folder": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
		byMetadataField: 'created-by',
 | 
			
		||||
		metadataFieldValueExtractor: _unitTests.extractorFnForDate_ddmmyyyy,
 | 
			
		||||
		defaultSorting: {
 | 
			
		||||
			order: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
			byMetadata: 'created-by',
 | 
			
		||||
			metadataValueExtractor: _unitTests.extractorFnForDate_ddmmyyyy
 | 
			
		||||
		},
 | 
			
		||||
		groups: [{
 | 
			
		||||
			foldersOnly: true,
 | 
			
		||||
			type: CustomSortGroupType.ExactPrefix,
 | 
			
		||||
			exactPrefix: 'Chapter',
 | 
			
		||||
			order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
			byMetadataField: 'updated-on',
 | 
			
		||||
			metadataFieldValueExtractor: _unitTests.extractorFnForDate_mmddyyyy
 | 
			
		||||
			sorting: {
 | 
			
		||||
				order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
				byMetadata: 'updated-on',
 | 
			
		||||
				metadataValueExtractor: _unitTests.extractorFnForDate_mmddyyyy
 | 
			
		||||
			}
 | 
			
		||||
		}, {
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -481,22 +488,30 @@ const expectedSortSpecsExampleMDataExtractors1: { [key: string]: CustomSortSpec
 | 
			
		|||
 | 
			
		||||
const expectedSortSpecsExampleMDataExtractors2: { [key: string]: CustomSortSpec } = {
 | 
			
		||||
	"mock-folder": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
		byMetadataField: 'created by',
 | 
			
		||||
		metadataFieldValueExtractor: _unitTests.extractorFnForDate_mmddyyyy,
 | 
			
		||||
		defaultSecondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
		byMetadataFieldSecondary: '',
 | 
			
		||||
		metadataFieldSecondaryValueExtractor: _unitTests.extractorFnForDate_ddmmyyyy,
 | 
			
		||||
		defaultSorting: {
 | 
			
		||||
			order: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
			byMetadata: 'created by',
 | 
			
		||||
			metadataValueExtractor: _unitTests.extractorFnForDate_mmddyyyy
 | 
			
		||||
		},
 | 
			
		||||
		defaultSecondarySorting: {
 | 
			
		||||
			order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
			byMetadata: '',
 | 
			
		||||
			metadataValueExtractor: _unitTests.extractorFnForDate_ddmmyyyy
 | 
			
		||||
		},
 | 
			
		||||
		groups: [{
 | 
			
		||||
			foldersOnly: true,
 | 
			
		||||
			type: CustomSortGroupType.ExactSuffix,
 | 
			
		||||
			exactSuffix: 'Chapter',
 | 
			
		||||
			order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
			byMetadataField: 'updated-on',
 | 
			
		||||
			metadataFieldValueExtractor: _unitTests.extractorFnForDate_ddmmyyyy,
 | 
			
		||||
			secondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse,
 | 
			
		||||
			byMetadataFieldSecondary: 'md2',
 | 
			
		||||
			metadataFieldSecondaryValueExtractor: _unitTests.extractorFnForDate_mmddyyyy
 | 
			
		||||
			sorting: {
 | 
			
		||||
				order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
				byMetadata: 'updated-on',
 | 
			
		||||
				metadataValueExtractor: _unitTests.extractorFnForDate_ddmmyyyy
 | 
			
		||||
			},
 | 
			
		||||
			secondarySorting: {
 | 
			
		||||
				order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse,
 | 
			
		||||
				byMetadata: 'md2',
 | 
			
		||||
				metadataValueExtractor: _unitTests.extractorFnForDate_mmddyyyy
 | 
			
		||||
			}
 | 
			
		||||
		}, {
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -505,6 +520,8 @@ const expectedSortSpecsExampleMDataExtractors2: { [key: string]: CustomSortSpec
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
describe('SortingSpecProcessor', () => {
 | 
			
		||||
	let processor: SortingSpecProcessor;
 | 
			
		||||
	beforeEach(() => {
 | 
			
		||||
| 
						 | 
				
			
			@ -546,7 +563,7 @@ target-folder: BBB
 | 
			
		|||
 | 
			
		||||
const expectedSortSpecsNotDuplicatedSortSpec: { [key: string]: CustomSortSpec } = {
 | 
			
		||||
	"AAA": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -586,11 +603,11 @@ sorting: standard
 | 
			
		|||
 | 
			
		||||
const expectedSortSpecForObsidianStandardSorting: { [key: string]: CustomSortSpec } = {
 | 
			
		||||
	"AAA": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.standardObsidian,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.standardObsidian, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			exactText: 'Some folder',
 | 
			
		||||
			foldersOnly: true,
 | 
			
		||||
			order: CustomSortOrder.standardObsidian,
 | 
			
		||||
			sorting: { order: CustomSortOrder.standardObsidian, },
 | 
			
		||||
			type: CustomSortGroupType.ExactName
 | 
			
		||||
		}, {
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
| 
						 | 
				
			
			@ -623,17 +640,17 @@ subitems2...
 | 
			
		|||
 | 
			
		||||
const expectedSortSpecForFilesOrFoldersPreferred: { [key: string]: CustomSortSpec } = {
 | 
			
		||||
	"AAA": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.alphabetical,
 | 
			
		||||
		defaultSecondaryOrder: CustomSortOrder.fileFirst,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
		defaultSecondarySorting: { order: CustomSortOrder.fileFirst, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			exactPrefix: 'subitems1',
 | 
			
		||||
			order: CustomSortOrder.folderFirst,
 | 
			
		||||
			secondaryOrder: CustomSortOrder.trueAlphabeticalWithFileExt,
 | 
			
		||||
			sorting: { order: CustomSortOrder.folderFirst, },
 | 
			
		||||
			secondarySorting: { order: CustomSortOrder.trueAlphabeticalWithFileExt, },
 | 
			
		||||
			type: CustomSortGroupType.ExactPrefix
 | 
			
		||||
		},{
 | 
			
		||||
			exactPrefix: 'subitems2',
 | 
			
		||||
			order: CustomSortOrder.byCreatedTime,
 | 
			
		||||
			secondaryOrder: CustomSortOrder.folderFirst,
 | 
			
		||||
			sorting: { order: CustomSortOrder.byCreatedTime, },
 | 
			
		||||
			secondarySorting: { order: CustomSortOrder.folderFirst, },
 | 
			
		||||
			type: CustomSortGroupType.ExactPrefix
 | 
			
		||||
		}, {
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
| 
						 | 
				
			
			@ -734,7 +751,7 @@ target-folder: by-meta True Alpha Rev
 | 
			
		|||
 | 
			
		||||
const expectedSortSpecForTrueAlphabeticalSorting: { [key: string]: CustomSortSpec } = {
 | 
			
		||||
	"True Alpha": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.trueAlphabetical,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.trueAlphabetical, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -742,7 +759,7 @@ const expectedSortSpecForTrueAlphabeticalSorting: { [key: string]: CustomSortSpe
 | 
			
		|||
		targetFoldersPaths: ['True Alpha']
 | 
			
		||||
	},
 | 
			
		||||
	"True Alpha Rev": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.trueAlphabeticalReverse,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -750,7 +767,7 @@ const expectedSortSpecForTrueAlphabeticalSorting: { [key: string]: CustomSortSpe
 | 
			
		|||
		targetFoldersPaths: ['True Alpha Rev']
 | 
			
		||||
	},
 | 
			
		||||
	"True Alpha withExt": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.trueAlphabeticalWithFileExt,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.trueAlphabeticalWithFileExt, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -758,7 +775,7 @@ const expectedSortSpecForTrueAlphabeticalSorting: { [key: string]: CustomSortSpe
 | 
			
		|||
		targetFoldersPaths: ['True Alpha withExt']
 | 
			
		||||
	},
 | 
			
		||||
	"True Alpha Rev withExt": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.trueAlphabeticalReverseWithFileExt,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.trueAlphabeticalReverseWithFileExt, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -766,7 +783,7 @@ const expectedSortSpecForTrueAlphabeticalSorting: { [key: string]: CustomSortSpe
 | 
			
		|||
		targetFoldersPaths: ['True Alpha Rev withExt']
 | 
			
		||||
	},
 | 
			
		||||
	"by-meta True Alpha": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabetical, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -774,8 +791,10 @@ const expectedSortSpecForTrueAlphabeticalSorting: { [key: string]: CustomSortSpe
 | 
			
		|||
		targetFoldersPaths: ['by-meta True Alpha']
 | 
			
		||||
	},
 | 
			
		||||
	"by-meta True Alpha Rev": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse,
 | 
			
		||||
		byMetadataField: 'Some-attr',
 | 
			
		||||
		defaultSorting: {
 | 
			
		||||
			order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse,
 | 
			
		||||
			byMetadata: 'Some-attr'
 | 
			
		||||
		},
 | 
			
		||||
		groups: [{
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -810,19 +829,19 @@ target-folder: VS Code unicode lexicographic reverse
 | 
			
		|||
 | 
			
		||||
const expectedSortSpecForExoticExperimentalSorting: { [key: string]: CustomSortSpec } = {
 | 
			
		||||
	"VS Code unicode lexicographic": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.vscUnicode,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.vscUnicode, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			type: CustomSortGroupType.Outsiders,
 | 
			
		||||
			order: CustomSortOrder.vscUnicodeReverse
 | 
			
		||||
			sorting: { order: CustomSortOrder.vscUnicodeReverse },
 | 
			
		||||
		}],
 | 
			
		||||
		outsidersGroupIdx: 0,
 | 
			
		||||
		targetFoldersPaths: ['VS Code unicode lexicographic']
 | 
			
		||||
	},
 | 
			
		||||
	"VS Code unicode lexicographic reverse": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.vscUnicodeReverse,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.vscUnicodeReverse, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			type: CustomSortGroupType.Outsiders,
 | 
			
		||||
			order: CustomSortOrder.vscUnicode
 | 
			
		||||
			sorting: { order: CustomSortOrder.vscUnicode },
 | 
			
		||||
		}],
 | 
			
		||||
		outsidersGroupIdx: 0,
 | 
			
		||||
		targetFoldersPaths: ['VS Code unicode lexicographic reverse']
 | 
			
		||||
| 
						 | 
				
			
			@ -1080,7 +1099,7 @@ target-folder: regexp: /!: debug: ^r10 /[^/]/.+$
 | 
			
		|||
`
 | 
			
		||||
 | 
			
		||||
const expectedSortSpecTargetFolderRegexAndName1 = {
 | 
			
		||||
	defaultOrder: CustomSortOrder.byModifiedTimeReverseAdvanced,
 | 
			
		||||
	defaultSorting: { order: CustomSortOrder.byModifiedTimeReverseAdvanced, },
 | 
			
		||||
	groups: [{
 | 
			
		||||
		type: CustomSortGroupType.Outsiders
 | 
			
		||||
	}],
 | 
			
		||||
| 
						 | 
				
			
			@ -1089,7 +1108,7 @@ const expectedSortSpecTargetFolderRegexAndName1 = {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
const expectedSortSpecTargetFolderByName = {
 | 
			
		||||
	defaultOrder: CustomSortOrder.alphabetical,
 | 
			
		||||
	defaultSorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
	groups: [{
 | 
			
		||||
		type: CustomSortGroupType.Outsiders
 | 
			
		||||
	}],
 | 
			
		||||
| 
						 | 
				
			
			@ -1480,7 +1499,7 @@ describe('SortingSpecProcessor', () => {
 | 
			
		|||
			"/": {
 | 
			
		||||
				groups: [{
 | 
			
		||||
					exactText: "Nothing",
 | 
			
		||||
					order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				}, {
 | 
			
		||||
					combineWithIdx: 1,
 | 
			
		||||
| 
						 | 
				
			
			@ -1498,16 +1517,16 @@ describe('SortingSpecProcessor', () => {
 | 
			
		|||
				}, {
 | 
			
		||||
					combineWithIdx: 4,
 | 
			
		||||
					exactPrefix: "Abc",
 | 
			
		||||
					order: CustomSortOrder.byModifiedTimeReverse,
 | 
			
		||||
					sorting: { order: CustomSortOrder.byModifiedTimeReverse, },
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix
 | 
			
		||||
				}, {
 | 
			
		||||
					combineWithIdx: 4,
 | 
			
		||||
					exactSuffix: "Def",
 | 
			
		||||
					order: CustomSortOrder.byModifiedTimeReverse,
 | 
			
		||||
					sorting: { order: CustomSortOrder.byModifiedTimeReverse, },
 | 
			
		||||
					type: CustomSortGroupType.ExactSuffix
 | 
			
		||||
				}, {
 | 
			
		||||
					combineWithIdx: 4,
 | 
			
		||||
					order: CustomSortOrder.byModifiedTimeReverse,
 | 
			
		||||
					sorting: { order: CustomSortOrder.byModifiedTimeReverse, },
 | 
			
		||||
					type: CustomSortGroupType.MatchAll
 | 
			
		||||
				}, {
 | 
			
		||||
					exactText: "Unreachable line",
 | 
			
		||||
| 
						 | 
				
			
			@ -1539,13 +1558,15 @@ describe('SortingSpecProcessor', () => {
 | 
			
		|||
		const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
 | 
			
		||||
		expect(result?.sortSpecByPath).toEqual({
 | 
			
		||||
			"/": {
 | 
			
		||||
				defaultOrder: CustomSortOrder.byCreatedTime,
 | 
			
		||||
				defaultSecondaryOrder: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
				byMetadataFieldSecondary: "someMdataFld",
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.byCreatedTime, },
 | 
			
		||||
				defaultSecondarySorting: {
 | 
			
		||||
					order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
 | 
			
		||||
					byMetadata: "someMdataFld"
 | 
			
		||||
				},
 | 
			
		||||
				groups: [{
 | 
			
		||||
					exactText: "Nothing",
 | 
			
		||||
					order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.alphabetical,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				}, {
 | 
			
		||||
					combineWithIdx: 1,
 | 
			
		||||
| 
						 | 
				
			
			@ -1563,25 +1584,37 @@ describe('SortingSpecProcessor', () => {
 | 
			
		|||
				}, {
 | 
			
		||||
					combineWithIdx: 4,
 | 
			
		||||
					exactPrefix: "Abc",
 | 
			
		||||
					order: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
					byMetadataField: "abc-def",
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
					byMetadataFieldSecondary: "ghi-jkl1",
 | 
			
		||||
					sorting: {
 | 
			
		||||
						order: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
						byMetadata: "abc-def",
 | 
			
		||||
					},
 | 
			
		||||
					secondarySorting: {
 | 
			
		||||
						order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
						byMetadata: "ghi-jkl1"
 | 
			
		||||
					},
 | 
			
		||||
					type: CustomSortGroupType.ExactPrefix
 | 
			
		||||
				}, {
 | 
			
		||||
					combineWithIdx: 4,
 | 
			
		||||
					exactSuffix: "Def",
 | 
			
		||||
					order: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
					byMetadataField: "abc-def",
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
					byMetadataFieldSecondary: "ghi-jkl1",
 | 
			
		||||
					sorting: {
 | 
			
		||||
						order: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
						byMetadata: "abc-def",
 | 
			
		||||
					},
 | 
			
		||||
					secondarySorting: {
 | 
			
		||||
						order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
						byMetadata: "ghi-jkl1"
 | 
			
		||||
					},
 | 
			
		||||
					type: CustomSortGroupType.ExactSuffix
 | 
			
		||||
				}, {
 | 
			
		||||
					combineWithIdx: 4,
 | 
			
		||||
					order: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
					byMetadataField: "abc-def",
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
					byMetadataFieldSecondary: "ghi-jkl1",
 | 
			
		||||
					sorting: {
 | 
			
		||||
						order: CustomSortOrder.byMetadataFieldAlphabetical,
 | 
			
		||||
						byMetadata: "abc-def"
 | 
			
		||||
					},
 | 
			
		||||
					secondarySorting: {
 | 
			
		||||
						order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
 | 
			
		||||
						byMetadata: "ghi-jkl1"
 | 
			
		||||
					},
 | 
			
		||||
					type: CustomSortGroupType.MatchAll
 | 
			
		||||
				}, {
 | 
			
		||||
					exactText: "Unreachable line",
 | 
			
		||||
| 
						 | 
				
			
			@ -1592,7 +1625,7 @@ describe('SortingSpecProcessor', () => {
 | 
			
		|||
				outsidersGroupIdx: 8,
 | 
			
		||||
				targetFoldersPaths: ['/']
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
		} as FolderPathToSortSpecMap)
 | 
			
		||||
		expect(result?.sortSpecByWildcard).toBeUndefined()
 | 
			
		||||
	})
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -1611,11 +1644,11 @@ order-desc: standard desc, < ui selected asc
 | 
			
		|||
 | 
			
		||||
const expectedSortSpecsStandardSortingVariants: { [key: string]: CustomSortSpec } = {
 | 
			
		||||
	"mock-folder": {
 | 
			
		||||
		defaultOrder: CustomSortOrder.standardObsidian,
 | 
			
		||||
		defaultSecondaryOrder: CustomSortOrder.standardObsidian,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.standardObsidian, },
 | 
			
		||||
		defaultSecondarySorting: { order: CustomSortOrder.standardObsidian, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			order: CustomSortOrder.standardObsidian,
 | 
			
		||||
			secondaryOrder: CustomSortOrder.standardObsidian,
 | 
			
		||||
			sorting: { order: CustomSortOrder.standardObsidian, },
 | 
			
		||||
			secondarySorting: { order: CustomSortOrder.standardObsidian, },
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
		outsidersGroupIdx: 0,
 | 
			
		||||
| 
						 | 
				
			
			@ -1652,7 +1685,7 @@ describe('comments and higher level specs in sorting order spec', () => {
 | 
			
		|||
		const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
 | 
			
		||||
		expect(result?.sortSpecByPath).toEqual({
 | 
			
		||||
			"mock-folder": {
 | 
			
		||||
				defaultOrder: CustomSortOrder.byCreatedTimeReverse,
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.byCreatedTimeReverse, },
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.Outsiders
 | 
			
		||||
				}],
 | 
			
		||||
| 
						 | 
				
			
			@ -1669,7 +1702,7 @@ describe('comments and higher level specs in sorting order spec', () => {
 | 
			
		|||
		const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
 | 
			
		||||
		expect(result?.sortSpecByPath).toEqual({
 | 
			
		||||
			"mock-folder": {
 | 
			
		||||
				defaultOrder: CustomSortOrder.byCreatedTimeReverse,
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.byCreatedTimeReverse, },
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.Outsiders
 | 
			
		||||
				}],
 | 
			
		||||
| 
						 | 
				
			
			@ -1686,8 +1719,8 @@ describe('comments and higher level specs in sorting order spec', () => {
 | 
			
		|||
		const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
 | 
			
		||||
		expect(result?.sortSpecByPath).toEqual({
 | 
			
		||||
			"mock-folder": {
 | 
			
		||||
				defaultOrder: CustomSortOrder.byCreatedTimeReverse,
 | 
			
		||||
				defaultSecondaryOrder: CustomSortOrder.byModifiedTime,
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.byCreatedTimeReverse, },
 | 
			
		||||
				defaultSecondarySorting: { order: CustomSortOrder.byModifiedTime, },
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.Outsiders
 | 
			
		||||
				}],
 | 
			
		||||
| 
						 | 
				
			
			@ -1744,83 +1777,83 @@ describe('multi-level sorting', () => {
 | 
			
		|||
			"mock-folder": {
 | 
			
		||||
				groups: [{
 | 
			
		||||
					exactText: "a pre",
 | 
			
		||||
					order: CustomSortOrder.trueAlphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTime,
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabetical, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTime, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "a pre 2",
 | 
			
		||||
					order: CustomSortOrder.trueAlphabeticalWithFileExt,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTime,
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabeticalWithFileExt, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTime, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "a post 1",
 | 
			
		||||
					order: CustomSortOrder.trueAlphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTime,
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabetical, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTime, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "a post 2",
 | 
			
		||||
					order: CustomSortOrder.trueAlphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTime,
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabetical, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTime, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "a post",
 | 
			
		||||
					order: CustomSortOrder.trueAlphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTime,
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabetical, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTime, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "a none",
 | 
			
		||||
					order: CustomSortOrder.trueAlphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTime,
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabetical, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTime, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "a unspecified",
 | 
			
		||||
					order: CustomSortOrder.trueAlphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTime,
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabetical, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTime, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				}, {
 | 
			
		||||
					exactText: "a dbl specified",
 | 
			
		||||
					order: CustomSortOrder.trueAlphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTime,
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabetical, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTime, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "d pre",
 | 
			
		||||
					order: CustomSortOrder.trueAlphabeticalReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTimeReverse,
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTimeReverse, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "d pre 2",
 | 
			
		||||
					order: CustomSortOrder.trueAlphabeticalReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTimeReverse,
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTimeReverse, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "d post 1",
 | 
			
		||||
					order: CustomSortOrder.trueAlphabeticalReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTimeReverse,
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTimeReverse, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "d post 2",
 | 
			
		||||
					order: CustomSortOrder.trueAlphabeticalReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTimeReverse,
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTimeReverse, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "d post",
 | 
			
		||||
					order: CustomSortOrder.trueAlphabeticalReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTimeReverse,
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTimeReverse, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "d none",
 | 
			
		||||
					order: CustomSortOrder.trueAlphabeticalReverseWithFileExt,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTime,
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabeticalReverseWithFileExt, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTime, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "d unspecified",
 | 
			
		||||
					order: CustomSortOrder.trueAlphabeticalReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTime,
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTime, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				}, {
 | 
			
		||||
					exactText: "d dbl specified",
 | 
			
		||||
					order: CustomSortOrder.trueAlphabeticalReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTimeReverse,
 | 
			
		||||
					sorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTimeReverse, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					type: CustomSortGroupType.Outsiders
 | 
			
		||||
| 
						 | 
				
			
			@ -1871,83 +1904,83 @@ describe('multi-level sorting', () => {
 | 
			
		|||
			"mock-folder": {
 | 
			
		||||
				groups: [{
 | 
			
		||||
					exactText: "a c a",
 | 
			
		||||
					order: CustomSortOrder.alphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byCreatedTime,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byCreatedTime, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				}, {
 | 
			
		||||
					exactText: "a c d",
 | 
			
		||||
					order: CustomSortOrder.alphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byCreatedTimeReverse,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byCreatedTimeReverse, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "a ac a",
 | 
			
		||||
					order: CustomSortOrder.alphabeticalWithFileExt,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byCreatedTimeAdvanced,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabeticalWithFileExt, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byCreatedTimeAdvanced, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "a ac d",
 | 
			
		||||
					order: CustomSortOrder.alphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byCreatedTimeReverseAdvanced,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byCreatedTimeReverseAdvanced, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "a m a",
 | 
			
		||||
					order: CustomSortOrder.alphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTime,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTime, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "a m d",
 | 
			
		||||
					order: CustomSortOrder.alphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTimeReverse,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTimeReverse, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "a am a",
 | 
			
		||||
					order: CustomSortOrder.alphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTimeAdvanced,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTimeAdvanced, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "a am d",
 | 
			
		||||
					order: CustomSortOrder.alphabetical,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTimeReverseAdvanced,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTimeReverseAdvanced, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "d c a",
 | 
			
		||||
					order: CustomSortOrder.alphabeticalReverseWithFileExt,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byCreatedTime,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabeticalReverseWithFileExt, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byCreatedTime, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				}, {
 | 
			
		||||
					exactText: "d c d",
 | 
			
		||||
					order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byCreatedTimeReverse,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byCreatedTimeReverse, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "d ac a",
 | 
			
		||||
					order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byCreatedTimeAdvanced,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byCreatedTimeAdvanced, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "d ac d",
 | 
			
		||||
					order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byCreatedTimeReverseAdvanced,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byCreatedTimeReverseAdvanced, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "d m a",
 | 
			
		||||
					order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTime,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTime, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "d m d",
 | 
			
		||||
					order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTimeReverse,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTimeReverse, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "d am a",
 | 
			
		||||
					order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTimeAdvanced,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTimeAdvanced, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					exactText: "d am d",
 | 
			
		||||
					order: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTimeReverseAdvanced,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTimeReverseAdvanced, },
 | 
			
		||||
					type: CustomSortGroupType.ExactName
 | 
			
		||||
				},{
 | 
			
		||||
					type: CustomSortGroupType.Outsiders
 | 
			
		||||
| 
						 | 
				
			
			@ -1972,7 +2005,7 @@ describe('the sorting: prefix', () => {
 | 
			
		|||
		const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
 | 
			
		||||
		expect(result?.sortSpecByPath).toEqual({
 | 
			
		||||
			'mock-folder': {
 | 
			
		||||
				defaultOrder: CustomSortOrder.alphabetical,
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.Outsiders
 | 
			
		||||
				}],
 | 
			
		||||
| 
						 | 
				
			
			@ -1988,8 +2021,8 @@ describe('the sorting: prefix', () => {
 | 
			
		|||
		const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
 | 
			
		||||
		expect(result?.sortSpecByPath).toEqual({
 | 
			
		||||
			'mock-folder': {
 | 
			
		||||
				defaultOrder: CustomSortOrder.trueAlphabetical,
 | 
			
		||||
				defaultSecondaryOrder: CustomSortOrder.byModifiedTimeAdvanced,
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.trueAlphabetical, },
 | 
			
		||||
				defaultSecondarySorting: { order: CustomSortOrder.byModifiedTimeAdvanced, },
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.Outsiders
 | 
			
		||||
				}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2005,7 +2038,7 @@ describe('the sorting: prefix', () => {
 | 
			
		|||
		const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
 | 
			
		||||
		expect(result?.sortSpecByPath).toEqual({
 | 
			
		||||
			'mock-folder': {
 | 
			
		||||
				defaultOrder: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.Outsiders
 | 
			
		||||
				}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2021,8 +2054,8 @@ describe('the sorting: prefix', () => {
 | 
			
		|||
		const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
 | 
			
		||||
		expect(result?.sortSpecByPath).toEqual({
 | 
			
		||||
			'mock-folder': {
 | 
			
		||||
				defaultOrder: CustomSortOrder.trueAlphabeticalReverse,
 | 
			
		||||
				defaultSecondaryOrder: CustomSortOrder.byModifiedTimeReverseAdvanced,
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
 | 
			
		||||
				defaultSecondarySorting: { order: CustomSortOrder.byModifiedTimeReverseAdvanced, },
 | 
			
		||||
				groups: [{
 | 
			
		||||
					type: CustomSortGroupType.Outsiders
 | 
			
		||||
				}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2040,8 +2073,8 @@ describe('the sorting: prefix', () => {
 | 
			
		|||
		expect(result?.sortSpecByPath).toEqual({
 | 
			
		||||
			'mock-folder': {
 | 
			
		||||
				groups: [{
 | 
			
		||||
					order: CustomSortOrder.alphabeticalReverseWithFileExt,
 | 
			
		||||
					secondaryOrder: CustomSortOrder.byModifiedTimeAdvanced,
 | 
			
		||||
					sorting: { order: CustomSortOrder.alphabeticalReverseWithFileExt, },
 | 
			
		||||
					secondarySorting: { order: CustomSortOrder.byModifiedTimeAdvanced, },
 | 
			
		||||
					type: CustomSortGroupType.Outsiders
 | 
			
		||||
				}],
 | 
			
		||||
				outsidersGroupIdx: 0,
 | 
			
		||||
| 
						 | 
				
			
			@ -2071,7 +2104,7 @@ target-folder: .
 | 
			
		|||
 | 
			
		||||
const expectedSortSpecForMultiSpecAandB: { [key: string]: CustomSortSpec } = {
 | 
			
		||||
	'mock-folder': {
 | 
			
		||||
		defaultOrder: CustomSortOrder.alphabetical,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.alphabetical, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2084,7 +2117,7 @@ const expectedWildcardMatchingTreeForMultiSpecAandB: FolderMatchingTreeNode<Cust
 | 
			
		|||
	subtree: {
 | 
			
		||||
		"mock-folder": {
 | 
			
		||||
			matchAll: {
 | 
			
		||||
				"defaultOrder": CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.alphabeticalReverse },
 | 
			
		||||
				"groups": [{
 | 
			
		||||
					"type": CustomSortGroupType.Outsiders
 | 
			
		||||
					}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2092,7 +2125,7 @@ const expectedWildcardMatchingTreeForMultiSpecAandB: FolderMatchingTreeNode<Cust
 | 
			
		|||
				"targetFoldersPaths": ["mock-folder/*"]
 | 
			
		||||
			},
 | 
			
		||||
			matchChildren: {
 | 
			
		||||
				"defaultOrder": CustomSortOrder.byModifiedTime,
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.byModifiedTime },
 | 
			
		||||
				"groups": [{
 | 
			
		||||
					"type": CustomSortGroupType.Outsiders
 | 
			
		||||
					}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2125,7 +2158,7 @@ const expectedWildcardMatchingTreeForMultiSpecC: FolderMatchingTreeNode<CustomSo
 | 
			
		|||
	subtree: {
 | 
			
		||||
		"mock-folder": {
 | 
			
		||||
			matchAll: {
 | 
			
		||||
				"defaultOrder": CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.alphabeticalReverse },
 | 
			
		||||
				"groups": [{
 | 
			
		||||
					"type": CustomSortGroupType.Outsiders
 | 
			
		||||
				}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2168,7 +2201,7 @@ const expectedSortSpecForMultiSpecD: { [key: string]: CustomSortSpec } = {
 | 
			
		|||
 | 
			
		||||
const expectedSortSpecForMultiSpecD_implicitCase: { [key: string]: CustomSortSpec } = {
 | 
			
		||||
	'mock-folder': {
 | 
			
		||||
		defaultOrder: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2198,7 +2231,7 @@ const expectedWildcardMatchingTreeForMultiSpecD_implicitCase: FolderMatchingTree
 | 
			
		|||
	subtree: {
 | 
			
		||||
		"mock-folder": {
 | 
			
		||||
			matchAll: {
 | 
			
		||||
				defaultOrder: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
				"groups": [{
 | 
			
		||||
					"type": CustomSortGroupType.Outsiders
 | 
			
		||||
				}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2235,7 +2268,7 @@ const expectedSortSpecForMultiSpecE: { [key: string]: CustomSortSpec } = {
 | 
			
		|||
 | 
			
		||||
const expectedSortSpecForMultiSpecE_implicitCase: { [key: string]: CustomSortSpec } = {
 | 
			
		||||
	'mock-folder': {
 | 
			
		||||
		defaultOrder: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2265,7 +2298,7 @@ const expectedWildcardMatchingTreeForMultiSpecE_implicitCase: FolderMatchingTree
 | 
			
		|||
	subtree: {
 | 
			
		||||
		"mock-folder": {
 | 
			
		||||
			matchChildren: {
 | 
			
		||||
				defaultOrder: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
				"groups": [{
 | 
			
		||||
					"type": CustomSortGroupType.Outsiders
 | 
			
		||||
				}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2290,7 +2323,7 @@ const expectedWildcardMatchingTreeForMultiSpecDplusE_implicitCase: FolderMatchin
 | 
			
		|||
				"targetFoldersPaths": ["mock-folder/*"]
 | 
			
		||||
			},
 | 
			
		||||
			matchChildren: {
 | 
			
		||||
				defaultOrder: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
				defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
				"groups": [{
 | 
			
		||||
					"type": CustomSortGroupType.Outsiders
 | 
			
		||||
				}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2313,7 +2346,7 @@ target-folder: mock-folder
 | 
			
		|||
 | 
			
		||||
const expectedSortSpecForMultiSpecF_implicitCase: { [key: string]: CustomSortSpec } = {
 | 
			
		||||
	'mock-folder': {
 | 
			
		||||
		defaultOrder: CustomSortOrder.alphabeticalReverse,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2430,7 +2463,7 @@ target-folder: AA
 | 
			
		|||
 | 
			
		||||
const expectedSortSpecForAdvancedFolderDateSortingMethods: { [key: string]: CustomSortSpec } = {
 | 
			
		||||
	'A': {
 | 
			
		||||
		defaultOrder: CustomSortOrder.byModifiedTimeAdvanced,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.byModifiedTimeAdvanced, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
			type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2438,7 +2471,7 @@ const expectedSortSpecForAdvancedFolderDateSortingMethods: { [key: string]: Cust
 | 
			
		|||
		targetFoldersPaths: ['A']
 | 
			
		||||
	},
 | 
			
		||||
	'B': {
 | 
			
		||||
		defaultOrder: CustomSortOrder.byModifiedTimeReverseAdvanced,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.byModifiedTimeReverseAdvanced, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
				type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2446,7 +2479,7 @@ const expectedSortSpecForAdvancedFolderDateSortingMethods: { [key: string]: Cust
 | 
			
		|||
		targetFoldersPaths: ['B']
 | 
			
		||||
	},
 | 
			
		||||
	'C': {
 | 
			
		||||
		defaultOrder: CustomSortOrder.byCreatedTimeAdvanced,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.byCreatedTimeAdvanced, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
				type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2454,7 +2487,7 @@ const expectedSortSpecForAdvancedFolderDateSortingMethods: { [key: string]: Cust
 | 
			
		|||
		targetFoldersPaths: ['C']
 | 
			
		||||
	},
 | 
			
		||||
	'D': {
 | 
			
		||||
		defaultOrder: CustomSortOrder.byCreatedTimeReverseAdvanced,
 | 
			
		||||
		defaultSorting: { order: CustomSortOrder.byCreatedTimeReverseAdvanced, },
 | 
			
		||||
		groups: [{
 | 
			
		||||
				type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}],
 | 
			
		||||
| 
						 | 
				
			
			@ -2464,41 +2497,41 @@ const expectedSortSpecForAdvancedFolderDateSortingMethods: { [key: string]: Cust
 | 
			
		|||
	'AA': {
 | 
			
		||||
		groups: [{
 | 
			
		||||
				foldersOnly: true,
 | 
			
		||||
				order: CustomSortOrder.byModifiedTimeAdvanced,
 | 
			
		||||
				sorting: { order: CustomSortOrder.byModifiedTimeAdvanced, },
 | 
			
		||||
				type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}, {
 | 
			
		||||
				filesOnly: true,
 | 
			
		||||
				order: CustomSortOrder.byModifiedTimeReverseAdvanced,
 | 
			
		||||
				sorting: { order: CustomSortOrder.byModifiedTimeReverseAdvanced, },
 | 
			
		||||
				type: CustomSortGroupType.Outsiders
 | 
			
		||||
		}, {
 | 
			
		||||
				exactPrefix: 'Archive',
 | 
			
		||||
				foldersOnly: true,
 | 
			
		||||
				order: CustomSortOrder.byCreatedTimeAdvanced,
 | 
			
		||||
				sorting: { order: CustomSortOrder.byCreatedTimeAdvanced, },
 | 
			
		||||
				type: CustomSortGroupType.ExactPrefix
 | 
			
		||||
		}, {
 | 
			
		||||
				exactPrefix: 'Archive',
 | 
			
		||||
				filesOnly: true,
 | 
			
		||||
				order: CustomSortOrder.byCreatedTimeReverseAdvanced,
 | 
			
		||||
				sorting: { order: CustomSortOrder.byCreatedTimeReverseAdvanced, },
 | 
			
		||||
				type: CustomSortGroupType.ExactPrefix
 | 
			
		||||
		}, {
 | 
			
		||||
				exactPrefix: 'Deep1',
 | 
			
		||||
				foldersOnly: true,
 | 
			
		||||
				order: CustomSortOrder.byCreatedTimeAdvancedRecursive,
 | 
			
		||||
				sorting: { order: CustomSortOrder.byCreatedTimeAdvancedRecursive, },
 | 
			
		||||
				type: CustomSortGroupType.ExactPrefix
 | 
			
		||||
		}, {
 | 
			
		||||
				exactPrefix: 'Deep2',
 | 
			
		||||
				filesOnly: true,
 | 
			
		||||
				order: CustomSortOrder.byCreatedTimeReverseAdvancedRecursive,
 | 
			
		||||
				sorting: { order: CustomSortOrder.byCreatedTimeReverseAdvancedRecursive, },
 | 
			
		||||
				type: CustomSortGroupType.ExactPrefix
 | 
			
		||||
		}, {
 | 
			
		||||
				exactPrefix: 'Deep3',
 | 
			
		||||
				foldersOnly: true,
 | 
			
		||||
				order: CustomSortOrder.byModifiedTimeAdvancedRecursive,
 | 
			
		||||
				sorting: { order: CustomSortOrder.byModifiedTimeAdvancedRecursive, },
 | 
			
		||||
				type: CustomSortGroupType.ExactPrefix
 | 
			
		||||
		}, {
 | 
			
		||||
				exactPrefix: 'Deep4',
 | 
			
		||||
				filesOnly: true,
 | 
			
		||||
				order: CustomSortOrder.byModifiedTimeReverseAdvancedRecursive,
 | 
			
		||||
				sorting: { order: CustomSortOrder.byModifiedTimeReverseAdvancedRecursive, },
 | 
			
		||||
				type: CustomSortGroupType.ExactPrefix
 | 
			
		||||
		}],
 | 
			
		||||
		outsidersFilesGroupIdx: 1,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue