Merge pull request #174 from SebastianMC/nov-2024-refactoring-regroup-sorting-structures

Major refactoring of sorting structures.
This commit is contained in:
SebastianMC 2025-01-03 20:16:49 +01:00 committed by GitHub
commit 2c2053d853
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 411 additions and 396 deletions

View File

@ -49,15 +49,6 @@ export enum CustomSortOrder {
default = alphabeticalWithFilesPreferred 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 type NormalizerFn = (s: string) => string | null
export const IdentityNormalizerFn: NormalizerFn = (s: string) => s export const IdentityNormalizerFn: NormalizerFn = (s: string) => s
@ -66,6 +57,17 @@ export interface RegExpSpec {
normalizerFn?: NormalizerFn normalizerFn?: NormalizerFn
} }
export interface CustomSort {
order: CustomSortOrder // mandatory
byMetadata?: string
metadataValueExtractor?: MDataExtractor
}
export interface RecognizedSorting {
primary?: CustomSort
secondary?: CustomSort
}
export interface CustomSortGroup { export interface CustomSortGroup {
type: CustomSortGroupType type: CustomSortGroupType
exactText?: string exactText?: string
@ -73,12 +75,8 @@ export interface CustomSortGroup {
regexPrefix?: RegExpSpec regexPrefix?: RegExpSpec
exactSuffix?: string exactSuffix?: string
regexSuffix?: RegExpSpec regexSuffix?: RegExpSpec
order?: CustomSortOrder sorting?: CustomSort
byMetadataField?: string // for 'by-metadata:' sorting if the order is by metadata alphabetical or reverse secondarySorting?: CustomSort
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
filesOnly?: boolean filesOnly?: boolean
matchFilenameWithExt?: boolean matchFilenameWithExt?: boolean
foldersOnly?: boolean foldersOnly?: boolean
@ -91,12 +89,8 @@ export interface CustomSortGroup {
export interface CustomSortSpec { export interface CustomSortSpec {
// plays only informative role about the original parsed 'target-folder:' values // plays only informative role about the original parsed 'target-folder:' values
targetFoldersPaths: Array<string> // For root use '/' targetFoldersPaths: Array<string> // For root use '/'
defaultOrder?: CustomSortOrder defaultSorting?: CustomSort
defaultSecondaryOrder?: CustomSortOrder defaultSecondarySorting?: CustomSort
byMetadataField?: string // for 'by-metadata:' if the defaultOrder is by metadata
metadataFieldValueExtractor?: MDataExtractor // and its sorting value extractor
byMetadataFieldSecondary?: string
metadataFieldSecondaryValueExtractor?: MDataExtractor
groups: Array<CustomSortGroup> groups: Array<CustomSortGroup>
groupsShadow?: Array<CustomSortGroup> // A shallow copy of groups, used at applying sorting for items in a folder. 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) // Stores folder-specific values (e.g. macros expanded with folder-specific values)

View File

@ -57,12 +57,12 @@ export const collectSortingAndGroupingTypes = (sortSpec?: CustomSortSpec|null):
} }
} }
if (!sortSpec) return has if (!sortSpec) return has
doCheck(has, sortSpec.defaultOrder) doCheck(has, sortSpec.defaultSorting?.order)
doCheck(has, sortSpec.defaultSecondaryOrder) doCheck(has, sortSpec.defaultSecondarySorting?.order)
if (sortSpec.groups) { if (sortSpec.groups) {
for (let group of sortSpec.groups) { for (let group of sortSpec.groups) {
doCheck(has, group.order, group.type) doCheck(has, group.sorting?.order, group.type)
doCheck(has, group.secondaryOrder) doCheck(has, group.secondarySorting?.order)
} }
} }
return has return has

View File

@ -11,6 +11,7 @@ import {
ObsidianIconFolder_PluginInstance ObsidianIconFolder_PluginInstance
} from '../utils/ObsidianIconFolderPluginSignature' } from '../utils/ObsidianIconFolderPluginSignature'
import { import {
CustomSort,
CustomSortGroup, CustomSortGroup,
CustomSortGroupType, CustomSortGroupType,
CustomSortOrder, CustomSortOrder,
@ -287,18 +288,18 @@ export const StandardPlainObsidianComparator = (order: string): PlainSorterFn =>
} }
} }
export const getSorterFnFor = (sorting: CustomSortOrder, currentUIselectedSorting?: string, sortLevelId?: SortingLevelId): SorterFn => { export const getSorterFnFor = (order: CustomSortOrder, currentUIselectedSorting?: string, sortLevelId?: SortingLevelId): SorterFn => {
if (sorting === CustomSortOrder.standardObsidian) { if (order === CustomSortOrder.standardObsidian) {
sorting = StandardObsidianToCustomSort[currentUIselectedSorting ?? 'alphabetical'] ?? CustomSortOrder.alphabetical order = StandardObsidianToCustomSort[currentUIselectedSorting ?? 'alphabetical'] ?? CustomSortOrder.alphabetical
return StandardObsidianComparator(sorting) return StandardObsidianComparator(order)
} else { } else {
// Some sorters have to know at which sorting level they are used // Some sorters have to know at which sorting level they are used
switch(sortLevelId) { switch(sortLevelId) {
case SortingLevelId.forSecondary: return SortersForSecondary[sorting] ?? Sorters[sorting] case SortingLevelId.forSecondary: return SortersForSecondary[order] ?? Sorters[order]
case SortingLevelId.forDerivedPrimary: return SortersForDerivedPrimary[sorting] ?? Sorters[sorting] case SortingLevelId.forDerivedPrimary: return SortersForDerivedPrimary[order] ?? Sorters[order]
case SortingLevelId.forDerivedSecondary: return SortersForDerivedSecondary[sorting] ?? Sorters[sorting] case SortingLevelId.forDerivedSecondary: return SortersForDerivedSecondary[order] ?? Sorters[order]
case SortingLevelId.forPrimary: 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 != undefined && itB.groupIdx != undefined) {
if (itA.groupIdx === itB.groupIdx) { if (itA.groupIdx === itB.groupIdx) {
const group: CustomSortGroup | undefined = sortSpec.groups[itA.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 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 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 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 if (folderLevelSecondary !== EQUAL_OR_UNCOMPARABLE) return folderLevelSecondary
const defaultForUnspecified: number = getSorterFnFor(CustomSortOrder.default, undefined, SortingLevelId.forDefaultWhenUnspecified)(itA, itB) const defaultForUnspecified: number = getSorterFnFor(CustomSortOrder.default, undefined, SortingLevelId.forDefaultWhenUnspecified)(itA, itB)
return defaultForUnspecified return defaultForUnspecified
@ -552,10 +553,10 @@ export const determineSortingGroup = function (entry: TFile | TFolder, spec: Cus
if (determined && determinedGroupIdx !== undefined) { // <-- defensive code, maybe too defensive if (determined && determinedGroupIdx !== undefined) { // <-- defensive code, maybe too defensive
const group: CustomSortGroup = spec.groups[determinedGroupIdx]; const group: CustomSortGroup = spec.groups[determinedGroupIdx];
const isPrimaryOrderByMetadata: boolean = isByMetadata(group?.order) const isPrimaryOrderByMetadata: boolean = isByMetadata(group?.sorting?.order)
const isSecondaryOrderByMetadata: boolean = isByMetadata(group?.secondaryOrder) const isSecondaryOrderByMetadata: boolean = isByMetadata(group?.secondarySorting?.order)
const isDerivedPrimaryByMetadata: boolean = isByMetadata(spec.defaultOrder) const isDerivedPrimaryByMetadata: boolean = isByMetadata(spec.defaultSorting?.order)
const isDerivedSecondaryByMetadata: boolean = isByMetadata(spec.defaultSecondaryOrder) const isDerivedSecondaryByMetadata: boolean = isByMetadata(spec.defaultSecondarySorting?.order)
if (isPrimaryOrderByMetadata || isSecondaryOrderByMetadata || isDerivedPrimaryByMetadata || isDerivedSecondaryByMetadata) { if (isPrimaryOrderByMetadata || isSecondaryOrderByMetadata || isDerivedPrimaryByMetadata || isDerivedSecondaryByMetadata) {
if (ctx?._mCache) { if (ctx?._mCache) {
// For folders - scan metadata of 'folder note' // For folders - scan metadata of 'folder note'
@ -571,26 +572,26 @@ export const determineSortingGroup = function (entry: TFile | TFolder, spec: Cus
} }
if (isPrimaryOrderByMetadata) metadataValueToSortBy = if (isPrimaryOrderByMetadata) metadataValueToSortBy =
mdataValueFromFMCaches ( mdataValueFromFMCaches (
group?.byMetadataField || group?.withMetadataFieldName || DEFAULT_METADATA_FIELD_FOR_SORTING, group.sorting!.byMetadata || group.withMetadataFieldName || DEFAULT_METADATA_FIELD_FOR_SORTING,
group?.metadataFieldValueExtractor, group.sorting!.metadataValueExtractor,
frontMatterCache, frontMatterCache,
prioFrontMatterCache) prioFrontMatterCache)
if (isSecondaryOrderByMetadata) metadataValueSecondaryToSortBy = if (isSecondaryOrderByMetadata) metadataValueSecondaryToSortBy =
mdataValueFromFMCaches ( mdataValueFromFMCaches (
group?.byMetadataFieldSecondary || group?.withMetadataFieldName || DEFAULT_METADATA_FIELD_FOR_SORTING, group.secondarySorting!.byMetadata || group.withMetadataFieldName || DEFAULT_METADATA_FIELD_FOR_SORTING,
group?.metadataFieldSecondaryValueExtractor, group.secondarySorting!.metadataValueExtractor,
frontMatterCache, frontMatterCache,
prioFrontMatterCache) prioFrontMatterCache)
if (isDerivedPrimaryByMetadata) metadataValueDerivedPrimaryToSortBy = if (isDerivedPrimaryByMetadata) metadataValueDerivedPrimaryToSortBy =
mdataValueFromFMCaches ( mdataValueFromFMCaches (
spec.byMetadataField || DEFAULT_METADATA_FIELD_FOR_SORTING, spec.defaultSorting!.byMetadata || DEFAULT_METADATA_FIELD_FOR_SORTING,
spec.metadataFieldValueExtractor, spec.defaultSorting!.metadataValueExtractor,
frontMatterCache, frontMatterCache,
prioFrontMatterCache) prioFrontMatterCache)
if (isDerivedSecondaryByMetadata) metadataValueDerivedSecondaryToSortBy = if (isDerivedSecondaryByMetadata) metadataValueDerivedSecondaryToSortBy =
mdataValueFromFMCaches ( mdataValueFromFMCaches (
spec.byMetadataFieldSecondary || DEFAULT_METADATA_FIELD_FOR_SORTING, spec.defaultSecondarySorting!.byMetadata || DEFAULT_METADATA_FIELD_FOR_SORTING,
spec.metadataFieldSecondaryValueExtractor, spec.defaultSecondarySorting!.metadataValueExtractor,
frontMatterCache, frontMatterCache,
prioFrontMatterCache) prioFrontMatterCache)
} }
@ -692,12 +693,12 @@ export const determineDatesForFolder = (folder: TFolder, recursive?: boolean): [
} }
export const determineFolderDatesIfNeeded = (folderItems: Array<FolderItemForSorting>, sortingSpec: CustomSortSpec) => { export const determineFolderDatesIfNeeded = (folderItems: Array<FolderItemForSorting>, sortingSpec: CustomSortSpec) => {
const foldersDatesNeeded = sortOrderNeedsFolderDates(sortingSpec.defaultOrder, sortingSpec.defaultSecondaryOrder) const foldersDatesNeeded = sortOrderNeedsFolderDates(sortingSpec.defaultSorting?.order, sortingSpec.defaultSecondarySorting?.order)
const foldersDeepDatesNeeded = sortOrderNeedsFolderDeepDates(sortingSpec.defaultOrder, sortingSpec.defaultSecondaryOrder) const foldersDeepDatesNeeded = sortOrderNeedsFolderDeepDates(sortingSpec.defaultSorting?.order, sortingSpec.defaultSecondarySorting?.order)
const groupOrders = sortingSpec.groups?.map((group) => ({ const groupOrders = sortingSpec.groups?.map((group) => ({
foldersDatesNeeded: sortOrderNeedsFolderDates(group.order, group.secondaryOrder), foldersDatesNeeded: sortOrderNeedsFolderDates(group.sorting?.order, group.secondarySorting?.order),
foldersDeepDatesNeeded: sortOrderNeedsFolderDeepDates(group.order, group.secondaryOrder) foldersDeepDatesNeeded: sortOrderNeedsFolderDeepDates(group.sorting?.order, group.secondarySorting?.order)
})) }))
folderItems.forEach((item) => { folderItems.forEach((item) => {
@ -717,15 +718,15 @@ export const determineFolderDatesIfNeeded = (folderItems: Array<FolderItemForSor
export const determineBookmarksOrderIfNeeded = (folderItems: Array<FolderItemForSorting>, sortingSpec: CustomSortSpec, plugin: BookmarksPluginInterface) => { export const determineBookmarksOrderIfNeeded = (folderItems: Array<FolderItemForSorting>, sortingSpec: CustomSortSpec, plugin: BookmarksPluginInterface) => {
if (!plugin) return 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) => { folderItems.forEach((item) => {
let groupSortRequiresBookmarksOrder: boolean = false let groupSortRequiresBookmarksOrder: boolean = false
if (!folderDefaultSortRequiresBookmarksOrder) { if (!folderDefaultSortRequiresBookmarksOrder) {
const groupIdx: number | undefined = item.groupIdx const groupIdx: number | undefined = item.groupIdx
if (groupIdx !== undefined) { if (groupIdx !== undefined) {
const groupOrder: CustomSortOrder | undefined = sortingSpec.groups[groupIdx].order const groupOrder: CustomSortOrder | undefined = sortingSpec.groups[groupIdx].sorting?.order
const groupSecondaryOrder: CustomSortOrder | undefined = sortingSpec.groups[groupIdx].secondaryOrder const groupSecondaryOrder: CustomSortOrder | undefined = sortingSpec.groups[groupIdx].secondarySorting?.order
groupSortRequiresBookmarksOrder = sortOrderNeedsBookmarksOrder(groupOrder, groupSecondaryOrder) groupSortRequiresBookmarksOrder = sortOrderNeedsBookmarksOrder(groupOrder, groupSecondaryOrder)
} }
} }

View File

@ -1,4 +1,5 @@
import { import {
CustomSort,
CustomSortGroup, CustomSortGroup,
CustomSortGroupType, CustomSortGroupType,
CustomSortOrder, CustomSortOrder,
@ -6,7 +7,7 @@ import {
DEFAULT_METADATA_FIELD_FOR_SORTING, DEFAULT_METADATA_FIELD_FOR_SORTING,
IdentityNormalizerFn, IdentityNormalizerFn,
NormalizerFn, NormalizerFn,
RecognizedOrderValue, RecognizedSorting,
RegExpSpec RegExpSpec
} from "./custom-sort-types"; } from "./custom-sort-types";
import {isDefined, last} from "../utils/utils"; import {isDefined, last} from "../utils/utils";
@ -115,12 +116,6 @@ interface CustomSortOrderAscDescPair {
desc: CustomSortOrder desc: CustomSortOrder
} }
interface CustomSortOrderSpec {
order: CustomSortOrder
byMetadataField?: string
metadataFieldExtractor?: MDataExtractor
}
const MAX_SORT_LEVEL: number = 1 const MAX_SORT_LEVEL: number = 1
// remember about .toLowerCase() before comparison! // remember about .toLowerCase() before comparison!
@ -1090,34 +1085,28 @@ export class SortingSpecProcessor {
if (!this.ctx.currentSpec) { if (!this.ctx.currentSpec) {
this.ctx.currentSpec = this.putNewSpecForNewTargetFolder() this.ctx.currentSpec = this.putNewSpecForNewTargetFolder()
} }
if (this.ctx.currentSpec.defaultOrder) { if (this.ctx.currentSpec.defaultSorting) {
const folderPathsForProblemMsg: string = this.ctx.currentSpec.targetFoldersPaths.join(' :: '); const folderPathsForProblemMsg: string = this.ctx.currentSpec.targetFoldersPaths.join(' :: ');
this.problem(ProblemCode.DuplicateOrderAttr, `Duplicate order specification for folder(s) ${folderPathsForProblemMsg}`) this.problem(ProblemCode.DuplicateOrderAttr, `Duplicate order specification for folder(s) ${folderPathsForProblemMsg}`)
return false; return false;
} }
this.ctx.currentSpec.defaultOrder = (attr.value as RecognizedOrderValue).order const rs: RecognizedSorting = attr.value // Syntax sugar
this.ctx.currentSpec.byMetadataField = (attr.value as RecognizedOrderValue).applyToMetadataField this.ctx.currentSpec.defaultSorting = rs.primary
this.ctx.currentSpec.metadataFieldValueExtractor = (attr.value as RecognizedOrderValue).metadataValueExtractor this.ctx.currentSpec.defaultSecondarySorting = rs.secondary
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
return true; return true;
} else if (attr.nesting > 0) { // For now only distinguishing nested (indented) and not-nested (not-indented), the depth doesn't matter } 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) { if (!this.ctx.currentSpec || !this.ctx.currentSpecGroup) {
this.problem(ProblemCode.DanglingOrderAttr, `Nested (indented) attribute requires prior sorting group definition`) this.problem(ProblemCode.DanglingOrderAttr, `Nested (indented) attribute requires prior sorting group definition`)
return false; return false;
} }
if (this.ctx.currentSpecGroup.order) { if (this.ctx.currentSpecGroup.sorting) {
const folderPathsForProblemMsg: string = this.ctx.currentSpec.targetFoldersPaths.join(' :: '); const folderPathsForProblemMsg: string = this.ctx.currentSpec.targetFoldersPaths.join(' :: ');
this.problem(ProblemCode.DuplicateOrderAttr, `Duplicate order specification for a sorting rule of folder ${folderPathsForProblemMsg}`) this.problem(ProblemCode.DuplicateOrderAttr, `Duplicate order specification for a sorting rule of folder ${folderPathsForProblemMsg}`)
return false; return false;
} }
this.ctx.currentSpecGroup.order = (attr.value as RecognizedOrderValue).order const rs: RecognizedSorting = attr.value // Syntax sugar
this.ctx.currentSpecGroup.byMetadataField = (attr.value as RecognizedOrderValue).applyToMetadataField this.ctx.currentSpecGroup.sorting = rs.primary
this.ctx.currentSpecGroup.metadataFieldValueExtractor = (attr.value as RecognizedOrderValue).metadataValueExtractor this.ctx.currentSpecGroup.secondarySorting = rs.secondary
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
return true; return true;
} }
} }
@ -1406,7 +1395,7 @@ export class SortingSpecProcessor {
currentCombinedGroupIdx = i currentCombinedGroupIdx = i
} else { } else {
// Ensure that the preceding group doesn't contain sorting order // 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') 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 return false
} }
@ -1421,34 +1410,26 @@ export class SortingSpecProcessor {
// Populate sorting order within combined groups // Populate sorting order within combined groups
if (anyCombinedGroupPresent) { if (anyCombinedGroupPresent) {
let orderForCombinedGroup: CustomSortOrder | undefined let sortingForCombinedGroup: CustomSort|undefined
let byMetadataFieldForCombinedGroup: string | undefined let secondarySortingForCombinedGroup: CustomSort|undefined
let secondaryOrderForCombinedGroup: CustomSortOrder | undefined
let secondaryByMetadataFieldForCombinedGroup: string | undefined
let idxOfCurrentCombinedGroup: number | undefined = undefined let idxOfCurrentCombinedGroup: number | undefined = undefined
for (let i = spec.groups.length - 1; i >= 0; i--) { for (let i = spec.groups.length - 1; i >= 0; i--) {
const group: CustomSortGroup = spec.groups[i] const group: CustomSortGroup = spec.groups[i]
if (group.combineWithIdx !== undefined) { if (group.combineWithIdx !== undefined) {
if (group.combineWithIdx === idxOfCurrentCombinedGroup) { // a subsequent (2nd, 3rd, ...) group of combined (counting from the end) if (group.combineWithIdx === idxOfCurrentCombinedGroup) { // a subsequent (2nd, 3rd, ...) group of combined (counting from the end)
group.order = orderForCombinedGroup group.sorting = sortingForCombinedGroup
group.byMetadataField = byMetadataFieldForCombinedGroup group.secondarySorting = secondarySortingForCombinedGroup
group.secondaryOrder = secondaryOrderForCombinedGroup
group.byMetadataFieldSecondary = secondaryByMetadataFieldForCombinedGroup
} else { // the first group of combined (counting from the end) } else { // the first group of combined (counting from the end)
idxOfCurrentCombinedGroup = group.combineWithIdx idxOfCurrentCombinedGroup = group.combineWithIdx
orderForCombinedGroup = group.order // could be undefined sortingForCombinedGroup = group.sorting
byMetadataFieldForCombinedGroup = group.byMetadataField // could be undefined secondarySortingForCombinedGroup = group.secondarySorting
secondaryOrderForCombinedGroup = group.secondaryOrder // could be undefined
secondaryByMetadataFieldForCombinedGroup = group.byMetadataFieldSecondary // could be undefined
} }
} else { } else {
// for sanity // for sanity
idxOfCurrentCombinedGroup = undefined idxOfCurrentCombinedGroup = undefined
orderForCombinedGroup = undefined sortingForCombinedGroup = undefined
byMetadataFieldForCombinedGroup = undefined secondarySortingForCombinedGroup = undefined
secondaryOrderForCombinedGroup = undefined
secondaryByMetadataFieldForCombinedGroup = 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) { if (sortOrderSpecText.indexOf(CommentPrefix) >= 0) {
sortOrderSpecText = sortOrderSpecText.substring(0, sortOrderSpecText.indexOf(CommentPrefix)) sortOrderSpecText = sortOrderSpecText.substring(0, sortOrderSpecText.indexOf(CommentPrefix))
} }
const sortLevels: Array<string> = `${prefixLexeme||''} ${sortOrderSpecText}`.trim().split(OrderLevelsSeparator) 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 // Max two levels are supported, excess levels specs are ignored
for (let level: number = 0; level <= MAX_SORT_LEVEL && level < sortLevels.length; level++) { for (let level: number = 0; level <= MAX_SORT_LEVEL && level < sortLevels.length; level++) {
@ -1592,22 +1573,18 @@ export class SortingSpecProcessor {
} }
sortOrderSpec[level] = { sortOrderSpec[level] = {
order: order!, order: order!,
byMetadataField: metadataName, byMetadata: metadataName,
metadataFieldExtractor: metadataExtractor metadataValueExtractor: metadataExtractor
} }
} }
return sortOrderSpec return sortOrderSpec
} }
private validateOrderAttrValue: AttrValueValidatorFn = (v: string, attr: Attribute, attrLexeme: string): RecognizedOrderValue|AttrError|null => { private validateOrderAttrValue: AttrValueValidatorFn = (v: string, attr: Attribute, attrLexeme: string): RecognizedSorting|AttrError|null => {
const recognized: Array<CustomSortOrderSpec>|AttrError|null = this.internalValidateOrderAttrValue(v, attrLexeme) const recognized: Array<CustomSort>|AttrError|null = this.internalValidateOrderAttrValue(v, attrLexeme)
return recognized ? (recognized instanceof AttrError ? recognized : { return recognized ? (recognized instanceof AttrError ? recognized : {
order: recognized[0].order, primary: recognized[0],
applyToMetadataField: recognized[0].byMetadataField, secondary: recognized[1]
metadataValueExtractor: recognized[0].metadataFieldExtractor,
secondaryOrder: recognized[1]?.order,
secondaryApplyToMetadataField: recognized[1]?.byMetadataField,
secondaryMetadataValueExtractor: recognized[1]?.metadataFieldExtractor
}) : null; }) : null;
} }

View File

@ -29,7 +29,7 @@ describe('determineFolderDatesIfNeeded', () => {
targetFoldersPaths: ['/'], targetFoldersPaths: ['/'],
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders, type: CustomSortGroupType.Outsiders,
order: CustomSortOrder.alphabetical sorting: { order: CustomSortOrder.alphabetical }
}], }],
outsidersGroupIdx: OUTSIDERS_GROUP_IDX outsidersGroupIdx: OUTSIDERS_GROUP_IDX
} }
@ -58,10 +58,10 @@ describe('determineFolderDatesIfNeeded', () => {
const OUTSIDERS_GROUP_IDX = 0 const OUTSIDERS_GROUP_IDX = 0
const sortSpec: CustomSortSpec = { const sortSpec: CustomSortSpec = {
targetFoldersPaths: ['/'], targetFoldersPaths: ['/'],
defaultOrder: folderOrder, defaultSorting: folderOrder ? { order: folderOrder } : undefined,
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders, type: CustomSortGroupType.Outsiders,
order: order sorting: { order: order }
}], }],
outsidersGroupIdx: OUTSIDERS_GROUP_IDX outsidersGroupIdx: OUTSIDERS_GROUP_IDX
} }
@ -90,10 +90,10 @@ describe('determineFolderDatesIfNeeded', () => {
const OUTSIDERS_GROUP_IDX = 0 const OUTSIDERS_GROUP_IDX = 0
const sortSpec: CustomSortSpec = { const sortSpec: CustomSortSpec = {
targetFoldersPaths: ['/'], targetFoldersPaths: ['/'],
defaultOrder: folderOrder, defaultSorting: folderOrder ? { order: folderOrder} : undefined,
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders, type: CustomSortGroupType.Outsiders,
order: order sorting: { order: order }
}], }],
outsidersGroupIdx: OUTSIDERS_GROUP_IDX outsidersGroupIdx: OUTSIDERS_GROUP_IDX
} }

View File

@ -14,18 +14,18 @@ const FlatLevelSortSpec: CustomSortSpec = {
groups: [{ // Not relevant in unit test groups: [{ // Not relevant in unit test
exactText: "Nothing", exactText: "Nothing",
filesOnly: true, filesOnly: true,
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ // prepared for unit test },{ // prepared for unit test
exactPrefix: "Fi", exactPrefix: "Fi",
order: CustomSortOrder.byMetadataFieldAlphabeticalReverse, sorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse, },
type: CustomSortGroupType.ExactPrefix type: CustomSortGroupType.ExactPrefix
},{ // Not relevant in unit test },{ // Not relevant in unit test
type: CustomSortGroupType.Outsiders, type: CustomSortGroupType.Outsiders,
order: CustomSortOrder.byCreatedTime sorting: { order: CustomSortOrder.byCreatedTime },
}], }],
outsidersGroupIdx: 2, outsidersGroupIdx: 2,
defaultOrder: CustomSortOrder.byCreatedTime, defaultSorting: { order: CustomSortOrder.byCreatedTime, },
targetFoldersPaths: ['parent folder'] targetFoldersPaths: ['parent folder']
} }
@ -33,19 +33,19 @@ const MultiLevelSortSpecGroupLevel: CustomSortSpec = {
groups: [{ // Not relevant in unit test groups: [{ // Not relevant in unit test
exactText: "Nothing", exactText: "Nothing",
filesOnly: true, filesOnly: true,
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ // prepared for unit test },{ // prepared for unit test
exactPrefix: "Fi", exactPrefix: "Fi",
order: CustomSortOrder.byMetadataFieldAlphabeticalReverse, sorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse, },
secondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical, secondarySorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabetical, },
type: CustomSortGroupType.ExactPrefix type: CustomSortGroupType.ExactPrefix
},{ // Not relevant in unit test },{ // Not relevant in unit test
type: CustomSortGroupType.Outsiders, type: CustomSortGroupType.Outsiders,
order: CustomSortOrder.byCreatedTime sorting: { order: CustomSortOrder.byCreatedTime },
}], }],
outsidersGroupIdx: 2, outsidersGroupIdx: 2,
defaultOrder: CustomSortOrder.byCreatedTime, defaultSorting: { order: CustomSortOrder.byCreatedTime, },
targetFoldersPaths: ['parent folder'] targetFoldersPaths: ['parent folder']
} }
@ -53,19 +53,19 @@ const MultiLevelSortSpecTargetFolderLevel: CustomSortSpec = {
groups: [{ // Not relevant in unit test groups: [{ // Not relevant in unit test
exactText: "Nothing", exactText: "Nothing",
filesOnly: true, filesOnly: true,
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ // prepared for unit test },{ // prepared for unit test
exactPrefix: "Fi", exactPrefix: "Fi",
order: CustomSortOrder.byMetadataFieldAlphabeticalReverse, sorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse, },
type: CustomSortGroupType.ExactPrefix type: CustomSortGroupType.ExactPrefix
},{ // Not relevant in unit test },{ // Not relevant in unit test
type: CustomSortGroupType.Outsiders, type: CustomSortGroupType.Outsiders,
order: CustomSortOrder.byCreatedTime sorting: { order: CustomSortOrder.byCreatedTime },
}], }],
outsidersGroupIdx: 2, outsidersGroupIdx: 2,
defaultOrder: CustomSortOrder.byCreatedTime, defaultSorting: { order: CustomSortOrder.byCreatedTime, },
defaultSecondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse, defaultSecondarySorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse, },
targetFoldersPaths: ['parent folder'] targetFoldersPaths: ['parent folder']
} }
@ -73,20 +73,20 @@ const MultiLevelSortSpecAndTargetFolderLevel: CustomSortSpec = {
groups: [{ // Not relevant in unit test groups: [{ // Not relevant in unit test
exactText: "Nothing", exactText: "Nothing",
filesOnly: true, filesOnly: true,
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ // prepared for unit test },{ // prepared for unit test
exactPrefix: "Fi", exactPrefix: "Fi",
order: CustomSortOrder.byMetadataFieldAlphabetical, sorting: { order: CustomSortOrder.byMetadataFieldAlphabetical, },
secondaryOrder: CustomSortOrder.byMetadataFieldAlphabeticalReverse, secondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse, },
type: CustomSortGroupType.ExactPrefix type: CustomSortGroupType.ExactPrefix
},{ // Not relevant in unit test },{ // Not relevant in unit test
type: CustomSortGroupType.Outsiders, type: CustomSortGroupType.Outsiders,
order: CustomSortOrder.byCreatedTime sorting: { order: CustomSortOrder.byCreatedTime },
}], }],
outsidersGroupIdx: 2, outsidersGroupIdx: 2,
defaultOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical, defaultSorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabetical, },
defaultSecondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse, defaultSecondarySorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse, },
targetFoldersPaths: ['parent folder'] targetFoldersPaths: ['parent folder']
} }

View File

@ -61,7 +61,7 @@ describe('hasOnlyByBookmarkOrStandardObsidian and collectSortingAndGroupingTypes
}) })
it('should detect not matching default order', () => { it('should detect not matching default order', () => {
const spec: Partial<CustomSortSpec>|undefined = { const spec: Partial<CustomSortSpec>|undefined = {
defaultOrder: CustomSortOrder.default, defaultSorting: { order: CustomSortOrder.default },
groups: [ groups: [
{ {
type: CustomSortGroupType.ExactName, type: CustomSortGroupType.ExactName,
@ -79,8 +79,8 @@ describe('hasOnlyByBookmarkOrStandardObsidian and collectSortingAndGroupingTypes
}) })
it('should detect not matching default secondary order', () => { it('should detect not matching default secondary order', () => {
const spec: Partial<CustomSortSpec>|undefined = { const spec: Partial<CustomSortSpec>|undefined = {
defaultOrder: CustomSortOrder.byBookmarkOrder, defaultSorting: { order: CustomSortOrder.byBookmarkOrder },
defaultSecondaryOrder: CustomSortOrder.default, defaultSecondarySorting: { order: CustomSortOrder.default },
groups: [ groups: [
{ {
type: CustomSortGroupType.BookmarkedOnly, type: CustomSortGroupType.BookmarkedOnly,
@ -98,12 +98,12 @@ describe('hasOnlyByBookmarkOrStandardObsidian and collectSortingAndGroupingTypes
}) })
it('should detect not matching order in group', () => { it('should detect not matching order in group', () => {
const spec: Partial<CustomSortSpec>|undefined = { const spec: Partial<CustomSortSpec>|undefined = {
defaultOrder: CustomSortOrder.byBookmarkOrder, defaultSorting: { order: CustomSortOrder.byBookmarkOrder },
defaultSecondaryOrder: CustomSortOrder.standardObsidian, defaultSecondarySorting: { order: CustomSortOrder.standardObsidian },
groups: [ groups: [
{ {
type: CustomSortGroupType.ExactName, type: CustomSortGroupType.ExactName,
order: CustomSortOrder.byCreatedTimeReverse sorting: { order: CustomSortOrder.byCreatedTimeReverse }
}, },
{ {
type: CustomSortGroupType.Outsiders, type: CustomSortGroupType.Outsiders,
@ -118,18 +118,18 @@ describe('hasOnlyByBookmarkOrStandardObsidian and collectSortingAndGroupingTypes
}) })
it('should detect not matching secondary order in group', () => { it('should detect not matching secondary order in group', () => {
const spec: Partial<CustomSortSpec>|undefined = { const spec: Partial<CustomSortSpec>|undefined = {
defaultOrder: CustomSortOrder.byBookmarkOrder, defaultSorting: { order: CustomSortOrder.byBookmarkOrder },
defaultSecondaryOrder: CustomSortOrder.standardObsidian, defaultSecondarySorting: { order: CustomSortOrder.standardObsidian },
groups: [ groups: [
{ {
type: CustomSortGroupType.ExactName, type: CustomSortGroupType.ExactName,
order: CustomSortOrder.byBookmarkOrderReverse, sorting: { order: CustomSortOrder.byBookmarkOrderReverse },
secondaryOrder: CustomSortOrder.standardObsidian secondarySorting: { order: CustomSortOrder.standardObsidian }
}, },
{ {
type: CustomSortGroupType.Outsiders, type: CustomSortGroupType.Outsiders,
order: CustomSortOrder.byBookmarkOrder, sorting: { order: CustomSortOrder.byBookmarkOrder },
secondaryOrder: CustomSortOrder.alphabetical secondarySorting: { order: CustomSortOrder.alphabetical }
} }
] ]
} }
@ -141,18 +141,18 @@ describe('hasOnlyByBookmarkOrStandardObsidian and collectSortingAndGroupingTypes
}) })
it('should detect matching orders at all levels', () => { it('should detect matching orders at all levels', () => {
const spec: Partial<CustomSortSpec>|undefined = { const spec: Partial<CustomSortSpec>|undefined = {
defaultOrder: CustomSortOrder.byBookmarkOrder, defaultSorting: { order: CustomSortOrder.byBookmarkOrder },
defaultSecondaryOrder: CustomSortOrder.standardObsidian, defaultSecondarySorting: { order: CustomSortOrder.standardObsidian },
groups: [ groups: [
{ {
type: CustomSortGroupType.BookmarkedOnly, type: CustomSortGroupType.BookmarkedOnly,
order: CustomSortOrder.byBookmarkOrderReverse, sorting: { order: CustomSortOrder.byBookmarkOrderReverse },
secondaryOrder: CustomSortOrder.standardObsidian secondarySorting: { order: CustomSortOrder.standardObsidian }
}, },
{ {
type: CustomSortGroupType.Outsiders, type: CustomSortGroupType.Outsiders,
order: CustomSortOrder.byBookmarkOrder, sorting: { order: CustomSortOrder.byBookmarkOrder },
secondaryOrder: CustomSortOrder.byBookmarkOrderReverse secondarySorting: { order: CustomSortOrder.byBookmarkOrderReverse }
} }
] ]
} }

View File

@ -1469,9 +1469,10 @@ describe('determineSortingGroup', () => {
targetFoldersPaths: ['/'], targetFoldersPaths: ['/'],
groups: [{ groups: [{
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
byMetadataField: 'metadata-field-for-sorting',
exactPrefix: 'Ref', exactPrefix: 'Ref',
order: CustomSortOrder.byMetadataFieldAlphabetical sorting: { order: CustomSortOrder.byMetadataFieldAlphabetical,
byMetadata: 'metadata-field-for-sorting',
},
}] }]
} }
const ctx: Partial<ProcessingContext> = { const ctx: Partial<ProcessingContext> = {
@ -1511,9 +1512,9 @@ describe('determineSortingGroup', () => {
targetFoldersPaths: ['/'], targetFoldersPaths: ['/'],
groups: [{ groups: [{
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
byMetadataField: 'metadata-field-for-sorting',
exactPrefix: 'Ref', exactPrefix: 'Ref',
order: CustomSortOrder.byMetadataFieldAlphabeticalReverse sorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
byMetadata: 'metadata-field-for-sorting',},
}] }]
} }
const ctx: Partial<ProcessingContext> = { const ctx: Partial<ProcessingContext> = {
@ -1553,9 +1554,9 @@ describe('determineSortingGroup', () => {
targetFoldersPaths: ['/'], targetFoldersPaths: ['/'],
groups: [{ groups: [{
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
byMetadataField: 'metadata-field-for-sorting',
exactPrefix: 'Ref', exactPrefix: 'Ref',
order: CustomSortOrder.byMetadataFieldTrueAlphabetical sorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
byMetadata: 'metadata-field-for-sorting', },
}] }]
} }
const ctx: Partial<ProcessingContext> = { const ctx: Partial<ProcessingContext> = {
@ -1595,9 +1596,9 @@ describe('determineSortingGroup', () => {
targetFoldersPaths: ['/'], targetFoldersPaths: ['/'],
groups: [{ groups: [{
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
byMetadataField: 'metadata-field-for-sorting',
exactPrefix: 'Ref', exactPrefix: 'Ref',
order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse sorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse,
byMetadata: 'metadata-field-for-sorting', },
}] }]
} }
const ctx: Partial<ProcessingContext> = { const ctx: Partial<ProcessingContext> = {
@ -1638,8 +1639,8 @@ describe('determineSortingGroup', () => {
groups: [{ groups: [{
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
exactPrefix: 'Ref', exactPrefix: 'Ref',
byMetadataField: 'metadata-field-for-sorting', sorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
order: CustomSortOrder.byMetadataFieldAlphabeticalReverse byMetadata: 'metadata-field-for-sorting', },
}] }]
} }
const ctx: Partial<ProcessingContext> = { const ctx: Partial<ProcessingContext> = {
@ -1681,10 +1682,11 @@ describe('determineSortingGroup', () => {
groups: [{ groups: [{
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
exactPrefix: 'Ref', exactPrefix: 'Ref',
order: CustomSortOrder.byMetadataFieldAlphabetical sorting: { order: CustomSortOrder.byMetadataFieldAlphabetical },
}], }],
defaultOrder: CustomSortOrder.byMetadataFieldAlphabeticalReverse, defaultSorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
byMetadataField: 'metadata-field-for-sorting-specified-on-target-folder' byMetadata: 'metadata-field-for-sorting-specified-on-target-folder'
}
} }
const ctx: Partial<ProcessingContext> = { const ctx: Partial<ProcessingContext> = {
_mCache: { _mCache: {
@ -1723,7 +1725,7 @@ describe('determineSortingGroup', () => {
targetFoldersPaths: ['/'], targetFoldersPaths: ['/'],
groups: [{ groups: [{
type: CustomSortGroupType.HasMetadataField, type: CustomSortGroupType.HasMetadataField,
order: CustomSortOrder.byMetadataFieldAlphabetical, sorting: { order: CustomSortOrder.byMetadataFieldAlphabetical, },
withMetadataFieldName: 'field-used-with-with-metadata-syntax' withMetadataFieldName: 'field-used-with-with-metadata-syntax'
}] }]
} }
@ -1765,7 +1767,7 @@ describe('determineSortingGroup', () => {
groups: [{ groups: [{
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
exactPrefix: 'Ref', exactPrefix: 'Ref',
order: CustomSortOrder.byMetadataFieldAlphabetical sorting: { order: CustomSortOrder.byMetadataFieldAlphabetical },
}] }]
} }
const ctx: Partial<ProcessingContext> = { const ctx: Partial<ProcessingContext> = {
@ -1808,10 +1810,10 @@ describe('determineSortingGroup', () => {
targetFoldersPaths: ['/'], targetFoldersPaths: ['/'],
groups: [{ groups: [{
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
byMetadataFieldSecondary: 'metadata-field-for-sorting',
exactPrefix: 'Ref', exactPrefix: 'Ref',
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
secondaryOrder: CustomSortOrder.byMetadataFieldAlphabetical secondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabetical,
byMetadata: 'metadata-field-for-sorting', },
}] }]
} }
const ctx: Partial<ProcessingContext> = { const ctx: Partial<ProcessingContext> = {
@ -1851,10 +1853,10 @@ describe('determineSortingGroup', () => {
targetFoldersPaths: ['/'], targetFoldersPaths: ['/'],
groups: [{ groups: [{
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
byMetadataFieldSecondary: 'metadata-field-for-sorting',
exactPrefix: 'Ref', exactPrefix: 'Ref',
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
secondaryOrder: CustomSortOrder.byMetadataFieldAlphabeticalReverse secondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
byMetadata: 'metadata-field-for-sorting', },
}] }]
} }
const ctx: Partial<ProcessingContext> = { const ctx: Partial<ProcessingContext> = {
@ -1894,11 +1896,11 @@ describe('determineSortingGroup', () => {
targetFoldersPaths: ['/'], targetFoldersPaths: ['/'],
groups: [{ groups: [{
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
byMetadataField: 'non-existing-mdata',
byMetadataFieldSecondary: 'metadata-field-for-sorting',
exactPrefix: 'Ref', exactPrefix: 'Ref',
order: CustomSortOrder.byMetadataFieldTrueAlphabetical, sorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
secondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical byMetadata: 'non-existing-mdata'},
secondarySorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
byMetadata: 'metadata-field-for-sorting'},
}] }]
} }
const ctx: Partial<ProcessingContext> = { const ctx: Partial<ProcessingContext> = {
@ -1938,11 +1940,13 @@ describe('determineSortingGroup', () => {
targetFoldersPaths: ['/'], targetFoldersPaths: ['/'],
groups: [{ groups: [{
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
byMetadataField: 'metadata-field-for-sorting',
byMetadataFieldSecondary: 'metadata-field-for-sorting secondary',
exactPrefix: 'Ref', exactPrefix: 'Ref',
order: CustomSortOrder.byMetadataFieldTrueAlphabetical, sorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
secondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse byMetadata: 'metadata-field-for-sorting',
},
secondarySorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse,
byMetadata: 'metadata-field-for-sorting secondary',
},
}] }]
} }
const ctx: Partial<ProcessingContext> = { const ctx: Partial<ProcessingContext> = {
@ -1985,9 +1989,10 @@ describe('determineSortingGroup', () => {
groups: [{ groups: [{
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
exactPrefix: 'Ref', exactPrefix: 'Ref',
byMetadataFieldSecondary: 'metadata-field-for-sorting', sorting: { order: CustomSortOrder.standardObsidian },
order: CustomSortOrder.standardObsidian, secondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
secondaryOrder: CustomSortOrder.byMetadataFieldAlphabeticalReverse byMetadata: 'metadata-field-for-sorting'
},
}] }]
} }
const ctx: Partial<ProcessingContext> = { const ctx: Partial<ProcessingContext> = {
@ -2029,12 +2034,13 @@ describe('determineSortingGroup', () => {
groups: [{ groups: [{
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
exactPrefix: 'Ref', exactPrefix: 'Ref',
order: CustomSortOrder.trueAlphabetical, sorting: { order: CustomSortOrder.trueAlphabetical, },
secondaryOrder: CustomSortOrder.byMetadataFieldAlphabetical secondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabetical },
}], }],
defaultOrder: CustomSortOrder.byCreatedTime, defaultSorting: { order: CustomSortOrder.byCreatedTime, },
defaultSecondaryOrder: CustomSortOrder.byMetadataFieldAlphabeticalReverse, defaultSecondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
byMetadataFieldSecondary: 'metadata-field-for-sorting-specified-on-target-folder' byMetadata: 'metadata-field-for-sorting-specified-on-target-folder'
},
} }
const ctx: Partial<ProcessingContext> = { const ctx: Partial<ProcessingContext> = {
_mCache: { _mCache: {
@ -2073,8 +2079,8 @@ describe('determineSortingGroup', () => {
targetFoldersPaths: ['/'], targetFoldersPaths: ['/'],
groups: [{ groups: [{
type: CustomSortGroupType.HasMetadataField, type: CustomSortGroupType.HasMetadataField,
order: CustomSortOrder.standardObsidian, sorting: { order: CustomSortOrder.standardObsidian, },
secondaryOrder: CustomSortOrder.byMetadataFieldAlphabetical, secondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabetical, },
withMetadataFieldName: 'field-used-with-with-metadata-syntax' withMetadataFieldName: 'field-used-with-with-metadata-syntax'
}] }]
} }
@ -2116,8 +2122,8 @@ describe('determineSortingGroup', () => {
groups: [{ groups: [{
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
exactPrefix: 'Ref', exactPrefix: 'Ref',
order: CustomSortOrder.byCreatedTimeReverse, sorting: { order: CustomSortOrder.byCreatedTimeReverse, },
secondaryOrder: CustomSortOrder.byMetadataFieldAlphabetical secondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabetical },
}] }]
} }
const ctx: Partial<ProcessingContext> = { const ctx: Partial<ProcessingContext> = {
@ -2161,15 +2167,19 @@ describe('determineSortingGroup', () => {
groups: [{ groups: [{
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
exactPrefix: 'Ref', exactPrefix: 'Ref',
order: CustomSortOrder.byMetadataFieldAlphabetical, sorting: { order: CustomSortOrder.byMetadataFieldAlphabetical,
byMetadataField: 'mdata-for-primary', byMetadata: 'mdata-for-primary',
secondaryOrder: CustomSortOrder.byMetadataFieldAlphabeticalReverse, },
byMetadataFieldSecondary: 'mdata-for-secondary' secondarySorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
byMetadata: 'mdata-for-secondary'
},
}], }],
defaultOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical, defaultSorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
byMetadataField: 'mdata-for-default-primary', byMetadata: 'mdata-for-default-primary',
defaultSecondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse, },
byMetadataFieldSecondary: 'mdata-for-default-secondary' defaultSecondarySorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse,
byMetadata: 'mdata-for-default-secondary'
},
} }
const ctx: Partial<ProcessingContext> = { const ctx: Partial<ProcessingContext> = {
_mCache: { _mCache: {
@ -2215,24 +2225,24 @@ describe('determineSortingGroup', () => {
const sortSpec: CustomSortSpec = { const sortSpec: CustomSortSpec = {
groups: [{ groups: [{
filesOnly: true, filesOnly: true,
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
type: CustomSortGroupType.MatchAll type: CustomSortGroupType.MatchAll
}, { }, {
foldersOnly: true, foldersOnly: true,
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
type: CustomSortGroupType.MatchAll type: CustomSortGroupType.MatchAll
}, { }, {
exactSuffix: "def!", exactSuffix: "def!",
priority: 2, priority: 2,
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
type: CustomSortGroupType.ExactSuffix type: CustomSortGroupType.ExactSuffix
}, { }, {
exactText: "Abcdef!", exactText: "Abcdef!",
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
priority: 3, priority: 3,
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
}, { }, {
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
outsidersGroupIdx: 4, outsidersGroupIdx: 4,
@ -2261,28 +2271,28 @@ describe('determineSortingGroup', () => {
const sortSpec: CustomSortSpec = { const sortSpec: CustomSortSpec = {
groups: [{ groups: [{
exactSuffix: "def!", exactSuffix: "def!",
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
type: CustomSortGroupType.ExactSuffix type: CustomSortGroupType.ExactSuffix
}, { }, {
exactPrefix: "Hello :-)", exactPrefix: "Hello :-)",
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
combineWithIdx: 1 combineWithIdx: 1
}, { }, {
exactText: "Hello World :-)", exactText: "Hello World :-)",
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
type: CustomSortGroupType.ExactName, type: CustomSortGroupType.ExactName,
combineWithIdx: 1 combineWithIdx: 1
}, { }, {
filesOnly: true, filesOnly: true,
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
type: CustomSortGroupType.MatchAll type: CustomSortGroupType.MatchAll
}, { }, {
foldersOnly: true, foldersOnly: true,
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
type: CustomSortGroupType.MatchAll type: CustomSortGroupType.MatchAll
}, { }, {
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
outsidersGroupIdx: 5, outsidersGroupIdx: 5,
@ -2319,25 +2329,25 @@ describe('determineSortingGroup', () => {
const sortSpec: CustomSortSpec = { const sortSpec: CustomSortSpec = {
groups: [{ groups: [{
filesOnly: true, filesOnly: true,
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
type: CustomSortGroupType.MatchAll type: CustomSortGroupType.MatchAll
}, { }, {
foldersOnly: true, foldersOnly: true,
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
type: CustomSortGroupType.MatchAll type: CustomSortGroupType.MatchAll
}, { }, {
exactSuffix: "def!", exactSuffix: "def!",
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
type: CustomSortGroupType.ExactSuffix, type: CustomSortGroupType.ExactSuffix,
combineWithIdx: 2 combineWithIdx: 2
}, { }, {
exactText: "Hello :-)", exactText: "Hello :-)",
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
type: CustomSortGroupType.ExactName, type: CustomSortGroupType.ExactName,
priority: 1, priority: 1,
combineWithIdx: 2 combineWithIdx: 2
}, { }, {
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
outsidersGroupIdx: 4, outsidersGroupIdx: 4,

View File

@ -10,6 +10,7 @@ import {
detectSortingSymbols, detectSortingSymbols,
escapeRegexUnsafeCharacters, escapeRegexUnsafeCharacters,
extractSortingSymbol, extractSortingSymbol,
FolderPathToSortSpecMap,
hasMoreThanOneSortingSymbol, hasMoreThanOneSortingSymbol,
NumberNormalizerFn, NumberNormalizerFn,
RegexpUsedAs, RegexpUsedAs,
@ -158,7 +159,7 @@ target-folder: Same rules as for References
const expectedSortSpecsExampleA: { [key: string]: CustomSortSpec } = { const expectedSortSpecsExampleA: { [key: string]: CustomSortSpec } = {
"mock-folder": { "mock-folder": {
defaultOrder: CustomSortOrder.alphabetical, defaultSorting: { order: CustomSortOrder.alphabetical, },
groups: [{ groups: [{
foldersOnly: true, foldersOnly: true,
type: CustomSortGroupType.MatchAll type: CustomSortGroupType.MatchAll
@ -188,12 +189,14 @@ const expectedSortSpecsExampleA: { [key: string]: CustomSortSpec } = {
filesOnly: true, filesOnly: true,
type: CustomSortGroupType.HasMetadataField, type: CustomSortGroupType.HasMetadataField,
withMetadataFieldName: 'sort-index-value', withMetadataFieldName: 'sort-index-value',
order: CustomSortOrder.byMetadataFieldAlphabetical, sorting: {
byMetadataField: 'Some-dedicated-field', order: CustomSortOrder.byMetadataFieldAlphabetical,
byMetadata: 'Some-dedicated-field',
}
}, { }, {
type: CustomSortGroupType.HasMetadataField, type: CustomSortGroupType.HasMetadataField,
withMetadataFieldName: 'Pages', withMetadataFieldName: 'Pages',
order: CustomSortOrder.byMetadataFieldAlphabeticalReverse sorting: { order: CustomSortOrder.byMetadataFieldAlphabeticalReverse },
}, { }, {
type: CustomSortGroupType.HasIcon, type: CustomSortGroupType.HasIcon,
filesOnly: true filesOnly: true
@ -217,17 +220,17 @@ const expectedSortSpecsExampleA: { [key: string]: CustomSortSpec } = {
] ]
}, },
"folder of bookmarks": { "folder of bookmarks": {
defaultOrder: CustomSortOrder.byBookmarkOrder, defaultSorting: { order: CustomSortOrder.byBookmarkOrder, },
groups: [ groups: [
{ {
filesOnly: true, filesOnly: true,
order: CustomSortOrder.byBookmarkOrder, sorting: { order: CustomSortOrder.byBookmarkOrder, },
type: CustomSortGroupType.BookmarkedOnly type: CustomSortGroupType.BookmarkedOnly
}, },
{ {
exactText: "Abc", exactText: "Abc",
foldersOnly: true, foldersOnly: true,
order: CustomSortOrder.byBookmarkOrderReverse, sorting: { order: CustomSortOrder.byBookmarkOrderReverse, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
}, },
{ {
@ -257,11 +260,11 @@ const expectedSortSpecsExampleA: { [key: string]: CustomSortSpec } = {
type: CustomSortGroupType.ExactPrefix type: CustomSortGroupType.ExactPrefix
}, { }, {
foldersOnly: true, foldersOnly: true,
order: CustomSortOrder.byModifiedTimeReverseAdvanced, sorting: { order: CustomSortOrder.byModifiedTimeReverseAdvanced, },
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}, { }, {
filesOnly: true, filesOnly: true,
order: CustomSortOrder.byModifiedTime, sorting: { order: CustomSortOrder.byModifiedTime, },
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}, { }, {
exactPrefix: "Ref", exactPrefix: "Ref",
@ -287,7 +290,7 @@ const expectedSortSpecsExampleA: { [key: string]: CustomSortSpec } = {
targetFoldersPaths: ['/'] targetFoldersPaths: ['/']
}, },
"Sandbox": { "Sandbox": {
defaultOrder: CustomSortOrder.byModifiedTimeReverse, defaultSorting: { order: CustomSortOrder.byModifiedTimeReverse, },
groups: [{ groups: [{
exactText: "adfsasda", exactText: "adfsasda",
filesOnly: true, filesOnly: true,
@ -295,12 +298,12 @@ const expectedSortSpecsExampleA: { [key: string]: CustomSortSpec } = {
}, { }, {
exactText: "sdsadasdsa", exactText: "sdsadasdsa",
foldersOnly: true, foldersOnly: true,
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
}, { }, {
exactText: "fdsfdsfdsfs", exactText: "fdsfdsfdsfs",
foldersOnly: true, foldersOnly: true,
order: CustomSortOrder.byCreatedTimeReverse, sorting: { order: CustomSortOrder.byCreatedTimeReverse, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
}, { }, {
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
@ -309,20 +312,20 @@ const expectedSortSpecsExampleA: { [key: string]: CustomSortSpec } = {
targetFoldersPaths: ['Sandbox'] targetFoldersPaths: ['Sandbox']
}, },
"Abcd efgh ijk": { "Abcd efgh ijk": {
defaultOrder: CustomSortOrder.alphabeticalReverse, defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
groups: [{ groups: [{
exactPrefix: "Plain text spec bla bla bla (matches files and folders)", exactPrefix: "Plain text spec bla bla bla (matches files and folders)",
type: CustomSortGroupType.ExactPrefix type: CustomSortGroupType.ExactPrefix
}, { }, {
exactText: "files only matching", exactText: "files only matching",
filesOnly: true, filesOnly: true,
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
matchFilenameWithExt: true, matchFilenameWithExt: true,
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
}, { }, {
exactText: "folders only matching", exactText: "folders only matching",
foldersOnly: true, foldersOnly: true,
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
}, { }, {
exactText: "some-file (or folder)", 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 \\[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 = ` const txtInputExampleMDataExtractors1: string = `
< a-z by-metadata: created-by using-extractor: date(dd/mm/yyyy) < a-z by-metadata: created-by using-extractor: date(dd/mm/yyyy)
/folders Chapter... /folders Chapter...
> a-z by-metadata: updated-on using-extractor: date(mm/dd/yyyy) > 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 = ` 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) < 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 /folders ...Chapter
@ -461,16 +464,20 @@ const txtInputExampleMDataExtractors2: string = `
const expectedSortSpecsExampleMDataExtractors1: { [key: string]: CustomSortSpec } = { const expectedSortSpecsExampleMDataExtractors1: { [key: string]: CustomSortSpec } = {
"mock-folder": { "mock-folder": {
defaultOrder: CustomSortOrder.byMetadataFieldAlphabetical, defaultSorting: {
byMetadataField: 'created-by', order: CustomSortOrder.byMetadataFieldAlphabetical,
metadataFieldValueExtractor: _unitTests.extractorFnForDate_ddmmyyyy, byMetadata: 'created-by',
metadataValueExtractor: _unitTests.extractorFnForDate_ddmmyyyy
},
groups: [{ groups: [{
foldersOnly: true, foldersOnly: true,
type: CustomSortGroupType.ExactPrefix, type: CustomSortGroupType.ExactPrefix,
exactPrefix: 'Chapter', exactPrefix: 'Chapter',
order: CustomSortOrder.byMetadataFieldAlphabeticalReverse, sorting: {
byMetadataField: 'updated-on', order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
metadataFieldValueExtractor: _unitTests.extractorFnForDate_mmddyyyy byMetadata: 'updated-on',
metadataValueExtractor: _unitTests.extractorFnForDate_mmddyyyy
}
}, { }, {
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -481,22 +488,30 @@ const expectedSortSpecsExampleMDataExtractors1: { [key: string]: CustomSortSpec
const expectedSortSpecsExampleMDataExtractors2: { [key: string]: CustomSortSpec } = { const expectedSortSpecsExampleMDataExtractors2: { [key: string]: CustomSortSpec } = {
"mock-folder": { "mock-folder": {
defaultOrder: CustomSortOrder.byMetadataFieldAlphabetical, defaultSorting: {
byMetadataField: 'created by', order: CustomSortOrder.byMetadataFieldAlphabetical,
metadataFieldValueExtractor: _unitTests.extractorFnForDate_mmddyyyy, byMetadata: 'created by',
defaultSecondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical, metadataValueExtractor: _unitTests.extractorFnForDate_mmddyyyy
byMetadataFieldSecondary: '', },
metadataFieldSecondaryValueExtractor: _unitTests.extractorFnForDate_ddmmyyyy, defaultSecondarySorting: {
order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
byMetadata: '',
metadataValueExtractor: _unitTests.extractorFnForDate_ddmmyyyy
},
groups: [{ groups: [{
foldersOnly: true, foldersOnly: true,
type: CustomSortGroupType.ExactSuffix, type: CustomSortGroupType.ExactSuffix,
exactSuffix: 'Chapter', exactSuffix: 'Chapter',
order: CustomSortOrder.byMetadataFieldAlphabeticalReverse, sorting: {
byMetadataField: 'updated-on', order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
metadataFieldValueExtractor: _unitTests.extractorFnForDate_ddmmyyyy, byMetadata: 'updated-on',
secondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse, metadataValueExtractor: _unitTests.extractorFnForDate_ddmmyyyy
byMetadataFieldSecondary: 'md2', },
metadataFieldSecondaryValueExtractor: _unitTests.extractorFnForDate_mmddyyyy secondarySorting: {
order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse,
byMetadata: 'md2',
metadataValueExtractor: _unitTests.extractorFnForDate_mmddyyyy
}
}, { }, {
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -505,6 +520,8 @@ const expectedSortSpecsExampleMDataExtractors2: { [key: string]: CustomSortSpec
} }
} }
describe('SortingSpecProcessor', () => { describe('SortingSpecProcessor', () => {
let processor: SortingSpecProcessor; let processor: SortingSpecProcessor;
beforeEach(() => { beforeEach(() => {
@ -546,7 +563,7 @@ target-folder: BBB
const expectedSortSpecsNotDuplicatedSortSpec: { [key: string]: CustomSortSpec } = { const expectedSortSpecsNotDuplicatedSortSpec: { [key: string]: CustomSortSpec } = {
"AAA": { "AAA": {
defaultOrder: CustomSortOrder.alphabeticalReverse, defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -586,11 +603,11 @@ sorting: standard
const expectedSortSpecForObsidianStandardSorting: { [key: string]: CustomSortSpec } = { const expectedSortSpecForObsidianStandardSorting: { [key: string]: CustomSortSpec } = {
"AAA": { "AAA": {
defaultOrder: CustomSortOrder.standardObsidian, defaultSorting: { order: CustomSortOrder.standardObsidian, },
groups: [{ groups: [{
exactText: 'Some folder', exactText: 'Some folder',
foldersOnly: true, foldersOnly: true,
order: CustomSortOrder.standardObsidian, sorting: { order: CustomSortOrder.standardObsidian, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
}, { }, {
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
@ -623,17 +640,17 @@ subitems2...
const expectedSortSpecForFilesOrFoldersPreferred: { [key: string]: CustomSortSpec } = { const expectedSortSpecForFilesOrFoldersPreferred: { [key: string]: CustomSortSpec } = {
"AAA": { "AAA": {
defaultOrder: CustomSortOrder.alphabetical, defaultSorting: { order: CustomSortOrder.alphabetical, },
defaultSecondaryOrder: CustomSortOrder.fileFirst, defaultSecondarySorting: { order: CustomSortOrder.fileFirst, },
groups: [{ groups: [{
exactPrefix: 'subitems1', exactPrefix: 'subitems1',
order: CustomSortOrder.folderFirst, sorting: { order: CustomSortOrder.folderFirst, },
secondaryOrder: CustomSortOrder.trueAlphabeticalWithFileExt, secondarySorting: { order: CustomSortOrder.trueAlphabeticalWithFileExt, },
type: CustomSortGroupType.ExactPrefix type: CustomSortGroupType.ExactPrefix
},{ },{
exactPrefix: 'subitems2', exactPrefix: 'subitems2',
order: CustomSortOrder.byCreatedTime, sorting: { order: CustomSortOrder.byCreatedTime, },
secondaryOrder: CustomSortOrder.folderFirst, secondarySorting: { order: CustomSortOrder.folderFirst, },
type: CustomSortGroupType.ExactPrefix type: CustomSortGroupType.ExactPrefix
}, { }, {
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
@ -734,7 +751,7 @@ target-folder: by-meta True Alpha Rev
const expectedSortSpecForTrueAlphabeticalSorting: { [key: string]: CustomSortSpec } = { const expectedSortSpecForTrueAlphabeticalSorting: { [key: string]: CustomSortSpec } = {
"True Alpha": { "True Alpha": {
defaultOrder: CustomSortOrder.trueAlphabetical, defaultSorting: { order: CustomSortOrder.trueAlphabetical, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -742,7 +759,7 @@ const expectedSortSpecForTrueAlphabeticalSorting: { [key: string]: CustomSortSpe
targetFoldersPaths: ['True Alpha'] targetFoldersPaths: ['True Alpha']
}, },
"True Alpha Rev": { "True Alpha Rev": {
defaultOrder: CustomSortOrder.trueAlphabeticalReverse, defaultSorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -750,7 +767,7 @@ const expectedSortSpecForTrueAlphabeticalSorting: { [key: string]: CustomSortSpe
targetFoldersPaths: ['True Alpha Rev'] targetFoldersPaths: ['True Alpha Rev']
}, },
"True Alpha withExt": { "True Alpha withExt": {
defaultOrder: CustomSortOrder.trueAlphabeticalWithFileExt, defaultSorting: { order: CustomSortOrder.trueAlphabeticalWithFileExt, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -758,7 +775,7 @@ const expectedSortSpecForTrueAlphabeticalSorting: { [key: string]: CustomSortSpe
targetFoldersPaths: ['True Alpha withExt'] targetFoldersPaths: ['True Alpha withExt']
}, },
"True Alpha Rev withExt": { "True Alpha Rev withExt": {
defaultOrder: CustomSortOrder.trueAlphabeticalReverseWithFileExt, defaultSorting: { order: CustomSortOrder.trueAlphabeticalReverseWithFileExt, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -766,7 +783,7 @@ const expectedSortSpecForTrueAlphabeticalSorting: { [key: string]: CustomSortSpe
targetFoldersPaths: ['True Alpha Rev withExt'] targetFoldersPaths: ['True Alpha Rev withExt']
}, },
"by-meta True Alpha": { "by-meta True Alpha": {
defaultOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical, defaultSorting: { order: CustomSortOrder.byMetadataFieldTrueAlphabetical, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -774,8 +791,10 @@ const expectedSortSpecForTrueAlphabeticalSorting: { [key: string]: CustomSortSpe
targetFoldersPaths: ['by-meta True Alpha'] targetFoldersPaths: ['by-meta True Alpha']
}, },
"by-meta True Alpha Rev": { "by-meta True Alpha Rev": {
defaultOrder: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse, defaultSorting: {
byMetadataField: 'Some-attr', order: CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse,
byMetadata: 'Some-attr'
},
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -810,19 +829,19 @@ target-folder: VS Code unicode lexicographic reverse
const expectedSortSpecForExoticExperimentalSorting: { [key: string]: CustomSortSpec } = { const expectedSortSpecForExoticExperimentalSorting: { [key: string]: CustomSortSpec } = {
"VS Code unicode lexicographic": { "VS Code unicode lexicographic": {
defaultOrder: CustomSortOrder.vscUnicode, defaultSorting: { order: CustomSortOrder.vscUnicode, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders, type: CustomSortGroupType.Outsiders,
order: CustomSortOrder.vscUnicodeReverse sorting: { order: CustomSortOrder.vscUnicodeReverse },
}], }],
outsidersGroupIdx: 0, outsidersGroupIdx: 0,
targetFoldersPaths: ['VS Code unicode lexicographic'] targetFoldersPaths: ['VS Code unicode lexicographic']
}, },
"VS Code unicode lexicographic reverse": { "VS Code unicode lexicographic reverse": {
defaultOrder: CustomSortOrder.vscUnicodeReverse, defaultSorting: { order: CustomSortOrder.vscUnicodeReverse, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders, type: CustomSortGroupType.Outsiders,
order: CustomSortOrder.vscUnicode sorting: { order: CustomSortOrder.vscUnicode },
}], }],
outsidersGroupIdx: 0, outsidersGroupIdx: 0,
targetFoldersPaths: ['VS Code unicode lexicographic reverse'] targetFoldersPaths: ['VS Code unicode lexicographic reverse']
@ -1080,7 +1099,7 @@ target-folder: regexp: /!: debug: ^r10 /[^/]/.+$
` `
const expectedSortSpecTargetFolderRegexAndName1 = { const expectedSortSpecTargetFolderRegexAndName1 = {
defaultOrder: CustomSortOrder.byModifiedTimeReverseAdvanced, defaultSorting: { order: CustomSortOrder.byModifiedTimeReverseAdvanced, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -1089,7 +1108,7 @@ const expectedSortSpecTargetFolderRegexAndName1 = {
} }
const expectedSortSpecTargetFolderByName = { const expectedSortSpecTargetFolderByName = {
defaultOrder: CustomSortOrder.alphabetical, defaultSorting: { order: CustomSortOrder.alphabetical, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -1480,7 +1499,7 @@ describe('SortingSpecProcessor', () => {
"/": { "/": {
groups: [{ groups: [{
exactText: "Nothing", exactText: "Nothing",
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
}, { }, {
combineWithIdx: 1, combineWithIdx: 1,
@ -1498,16 +1517,16 @@ describe('SortingSpecProcessor', () => {
}, { }, {
combineWithIdx: 4, combineWithIdx: 4,
exactPrefix: "Abc", exactPrefix: "Abc",
order: CustomSortOrder.byModifiedTimeReverse, sorting: { order: CustomSortOrder.byModifiedTimeReverse, },
type: CustomSortGroupType.ExactPrefix type: CustomSortGroupType.ExactPrefix
}, { }, {
combineWithIdx: 4, combineWithIdx: 4,
exactSuffix: "Def", exactSuffix: "Def",
order: CustomSortOrder.byModifiedTimeReverse, sorting: { order: CustomSortOrder.byModifiedTimeReverse, },
type: CustomSortGroupType.ExactSuffix type: CustomSortGroupType.ExactSuffix
}, { }, {
combineWithIdx: 4, combineWithIdx: 4,
order: CustomSortOrder.byModifiedTimeReverse, sorting: { order: CustomSortOrder.byModifiedTimeReverse, },
type: CustomSortGroupType.MatchAll type: CustomSortGroupType.MatchAll
}, { }, {
exactText: "Unreachable line", exactText: "Unreachable line",
@ -1539,13 +1558,15 @@ describe('SortingSpecProcessor', () => {
const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md') const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
expect(result?.sortSpecByPath).toEqual({ expect(result?.sortSpecByPath).toEqual({
"/": { "/": {
defaultOrder: CustomSortOrder.byCreatedTime, defaultSorting: { order: CustomSortOrder.byCreatedTime, },
defaultSecondaryOrder: CustomSortOrder.byMetadataFieldAlphabeticalReverse, defaultSecondarySorting: {
byMetadataFieldSecondary: "someMdataFld", order: CustomSortOrder.byMetadataFieldAlphabeticalReverse,
byMetadata: "someMdataFld"
},
groups: [{ groups: [{
exactText: "Nothing", exactText: "Nothing",
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
secondaryOrder: CustomSortOrder.alphabetical, secondarySorting: { order: CustomSortOrder.alphabetical, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
}, { }, {
combineWithIdx: 1, combineWithIdx: 1,
@ -1563,25 +1584,37 @@ describe('SortingSpecProcessor', () => {
}, { }, {
combineWithIdx: 4, combineWithIdx: 4,
exactPrefix: "Abc", exactPrefix: "Abc",
order: CustomSortOrder.byMetadataFieldAlphabetical, sorting: {
byMetadataField: "abc-def", order: CustomSortOrder.byMetadataFieldAlphabetical,
secondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical, byMetadata: "abc-def",
byMetadataFieldSecondary: "ghi-jkl1", },
secondarySorting: {
order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
byMetadata: "ghi-jkl1"
},
type: CustomSortGroupType.ExactPrefix type: CustomSortGroupType.ExactPrefix
}, { }, {
combineWithIdx: 4, combineWithIdx: 4,
exactSuffix: "Def", exactSuffix: "Def",
order: CustomSortOrder.byMetadataFieldAlphabetical, sorting: {
byMetadataField: "abc-def", order: CustomSortOrder.byMetadataFieldAlphabetical,
secondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical, byMetadata: "abc-def",
byMetadataFieldSecondary: "ghi-jkl1", },
secondarySorting: {
order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
byMetadata: "ghi-jkl1"
},
type: CustomSortGroupType.ExactSuffix type: CustomSortGroupType.ExactSuffix
}, { }, {
combineWithIdx: 4, combineWithIdx: 4,
order: CustomSortOrder.byMetadataFieldAlphabetical, sorting: {
byMetadataField: "abc-def", order: CustomSortOrder.byMetadataFieldAlphabetical,
secondaryOrder: CustomSortOrder.byMetadataFieldTrueAlphabetical, byMetadata: "abc-def"
byMetadataFieldSecondary: "ghi-jkl1", },
secondarySorting: {
order: CustomSortOrder.byMetadataFieldTrueAlphabetical,
byMetadata: "ghi-jkl1"
},
type: CustomSortGroupType.MatchAll type: CustomSortGroupType.MatchAll
}, { }, {
exactText: "Unreachable line", exactText: "Unreachable line",
@ -1592,7 +1625,7 @@ describe('SortingSpecProcessor', () => {
outsidersGroupIdx: 8, outsidersGroupIdx: 8,
targetFoldersPaths: ['/'] targetFoldersPaths: ['/']
} }
}) } as FolderPathToSortSpecMap)
expect(result?.sortSpecByWildcard).toBeUndefined() expect(result?.sortSpecByWildcard).toBeUndefined()
}) })
}) })
@ -1611,11 +1644,11 @@ order-desc: standard desc, < ui selected asc
const expectedSortSpecsStandardSortingVariants: { [key: string]: CustomSortSpec } = { const expectedSortSpecsStandardSortingVariants: { [key: string]: CustomSortSpec } = {
"mock-folder": { "mock-folder": {
defaultOrder: CustomSortOrder.standardObsidian, defaultSorting: { order: CustomSortOrder.standardObsidian, },
defaultSecondaryOrder: CustomSortOrder.standardObsidian, defaultSecondarySorting: { order: CustomSortOrder.standardObsidian, },
groups: [{ groups: [{
order: CustomSortOrder.standardObsidian, sorting: { order: CustomSortOrder.standardObsidian, },
secondaryOrder: CustomSortOrder.standardObsidian, secondarySorting: { order: CustomSortOrder.standardObsidian, },
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
outsidersGroupIdx: 0, 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') const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
expect(result?.sortSpecByPath).toEqual({ expect(result?.sortSpecByPath).toEqual({
"mock-folder": { "mock-folder": {
defaultOrder: CustomSortOrder.byCreatedTimeReverse, defaultSorting: { order: CustomSortOrder.byCreatedTimeReverse, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders 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') const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
expect(result?.sortSpecByPath).toEqual({ expect(result?.sortSpecByPath).toEqual({
"mock-folder": { "mock-folder": {
defaultOrder: CustomSortOrder.byCreatedTimeReverse, defaultSorting: { order: CustomSortOrder.byCreatedTimeReverse, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders 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') const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
expect(result?.sortSpecByPath).toEqual({ expect(result?.sortSpecByPath).toEqual({
"mock-folder": { "mock-folder": {
defaultOrder: CustomSortOrder.byCreatedTimeReverse, defaultSorting: { order: CustomSortOrder.byCreatedTimeReverse, },
defaultSecondaryOrder: CustomSortOrder.byModifiedTime, defaultSecondarySorting: { order: CustomSortOrder.byModifiedTime, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -1744,83 +1777,83 @@ describe('multi-level sorting', () => {
"mock-folder": { "mock-folder": {
groups: [{ groups: [{
exactText: "a pre", exactText: "a pre",
order: CustomSortOrder.trueAlphabetical, sorting: { order: CustomSortOrder.trueAlphabetical, },
secondaryOrder: CustomSortOrder.byModifiedTime, secondarySorting: { order: CustomSortOrder.byModifiedTime, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "a pre 2", exactText: "a pre 2",
order: CustomSortOrder.trueAlphabeticalWithFileExt, sorting: { order: CustomSortOrder.trueAlphabeticalWithFileExt, },
secondaryOrder: CustomSortOrder.byModifiedTime, secondarySorting: { order: CustomSortOrder.byModifiedTime, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "a post 1", exactText: "a post 1",
order: CustomSortOrder.trueAlphabetical, sorting: { order: CustomSortOrder.trueAlphabetical, },
secondaryOrder: CustomSortOrder.byModifiedTime, secondarySorting: { order: CustomSortOrder.byModifiedTime, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "a post 2", exactText: "a post 2",
order: CustomSortOrder.trueAlphabetical, sorting: { order: CustomSortOrder.trueAlphabetical, },
secondaryOrder: CustomSortOrder.byModifiedTime, secondarySorting: { order: CustomSortOrder.byModifiedTime, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "a post", exactText: "a post",
order: CustomSortOrder.trueAlphabetical, sorting: { order: CustomSortOrder.trueAlphabetical, },
secondaryOrder: CustomSortOrder.byModifiedTime, secondarySorting: { order: CustomSortOrder.byModifiedTime, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "a none", exactText: "a none",
order: CustomSortOrder.trueAlphabetical, sorting: { order: CustomSortOrder.trueAlphabetical, },
secondaryOrder: CustomSortOrder.byModifiedTime, secondarySorting: { order: CustomSortOrder.byModifiedTime, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "a unspecified", exactText: "a unspecified",
order: CustomSortOrder.trueAlphabetical, sorting: { order: CustomSortOrder.trueAlphabetical, },
secondaryOrder: CustomSortOrder.byModifiedTime, secondarySorting: { order: CustomSortOrder.byModifiedTime, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
}, { }, {
exactText: "a dbl specified", exactText: "a dbl specified",
order: CustomSortOrder.trueAlphabetical, sorting: { order: CustomSortOrder.trueAlphabetical, },
secondaryOrder: CustomSortOrder.byModifiedTime, secondarySorting: { order: CustomSortOrder.byModifiedTime, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "d pre", exactText: "d pre",
order: CustomSortOrder.trueAlphabeticalReverse, sorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
secondaryOrder: CustomSortOrder.byModifiedTimeReverse, secondarySorting: { order: CustomSortOrder.byModifiedTimeReverse, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "d pre 2", exactText: "d pre 2",
order: CustomSortOrder.trueAlphabeticalReverse, sorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
secondaryOrder: CustomSortOrder.byModifiedTimeReverse, secondarySorting: { order: CustomSortOrder.byModifiedTimeReverse, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "d post 1", exactText: "d post 1",
order: CustomSortOrder.trueAlphabeticalReverse, sorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
secondaryOrder: CustomSortOrder.byModifiedTimeReverse, secondarySorting: { order: CustomSortOrder.byModifiedTimeReverse, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "d post 2", exactText: "d post 2",
order: CustomSortOrder.trueAlphabeticalReverse, sorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
secondaryOrder: CustomSortOrder.byModifiedTimeReverse, secondarySorting: { order: CustomSortOrder.byModifiedTimeReverse, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "d post", exactText: "d post",
order: CustomSortOrder.trueAlphabeticalReverse, sorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
secondaryOrder: CustomSortOrder.byModifiedTimeReverse, secondarySorting: { order: CustomSortOrder.byModifiedTimeReverse, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "d none", exactText: "d none",
order: CustomSortOrder.trueAlphabeticalReverseWithFileExt, sorting: { order: CustomSortOrder.trueAlphabeticalReverseWithFileExt, },
secondaryOrder: CustomSortOrder.byModifiedTime, secondarySorting: { order: CustomSortOrder.byModifiedTime, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "d unspecified", exactText: "d unspecified",
order: CustomSortOrder.trueAlphabeticalReverse, sorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
secondaryOrder: CustomSortOrder.byModifiedTime, secondarySorting: { order: CustomSortOrder.byModifiedTime, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
}, { }, {
exactText: "d dbl specified", exactText: "d dbl specified",
order: CustomSortOrder.trueAlphabeticalReverse, sorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
secondaryOrder: CustomSortOrder.byModifiedTimeReverse, secondarySorting: { order: CustomSortOrder.byModifiedTimeReverse, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
@ -1871,83 +1904,83 @@ describe('multi-level sorting', () => {
"mock-folder": { "mock-folder": {
groups: [{ groups: [{
exactText: "a c a", exactText: "a c a",
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
secondaryOrder: CustomSortOrder.byCreatedTime, secondarySorting: { order: CustomSortOrder.byCreatedTime, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
}, { }, {
exactText: "a c d", exactText: "a c d",
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
secondaryOrder: CustomSortOrder.byCreatedTimeReverse, secondarySorting: { order: CustomSortOrder.byCreatedTimeReverse, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "a ac a", exactText: "a ac a",
order: CustomSortOrder.alphabeticalWithFileExt, sorting: { order: CustomSortOrder.alphabeticalWithFileExt, },
secondaryOrder: CustomSortOrder.byCreatedTimeAdvanced, secondarySorting: { order: CustomSortOrder.byCreatedTimeAdvanced, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "a ac d", exactText: "a ac d",
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
secondaryOrder: CustomSortOrder.byCreatedTimeReverseAdvanced, secondarySorting: { order: CustomSortOrder.byCreatedTimeReverseAdvanced, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "a m a", exactText: "a m a",
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
secondaryOrder: CustomSortOrder.byModifiedTime, secondarySorting: { order: CustomSortOrder.byModifiedTime, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "a m d", exactText: "a m d",
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
secondaryOrder: CustomSortOrder.byModifiedTimeReverse, secondarySorting: { order: CustomSortOrder.byModifiedTimeReverse, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "a am a", exactText: "a am a",
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
secondaryOrder: CustomSortOrder.byModifiedTimeAdvanced, secondarySorting: { order: CustomSortOrder.byModifiedTimeAdvanced, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "a am d", exactText: "a am d",
order: CustomSortOrder.alphabetical, sorting: { order: CustomSortOrder.alphabetical, },
secondaryOrder: CustomSortOrder.byModifiedTimeReverseAdvanced, secondarySorting: { order: CustomSortOrder.byModifiedTimeReverseAdvanced, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "d c a", exactText: "d c a",
order: CustomSortOrder.alphabeticalReverseWithFileExt, sorting: { order: CustomSortOrder.alphabeticalReverseWithFileExt, },
secondaryOrder: CustomSortOrder.byCreatedTime, secondarySorting: { order: CustomSortOrder.byCreatedTime, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
}, { }, {
exactText: "d c d", exactText: "d c d",
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
secondaryOrder: CustomSortOrder.byCreatedTimeReverse, secondarySorting: { order: CustomSortOrder.byCreatedTimeReverse, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "d ac a", exactText: "d ac a",
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
secondaryOrder: CustomSortOrder.byCreatedTimeAdvanced, secondarySorting: { order: CustomSortOrder.byCreatedTimeAdvanced, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "d ac d", exactText: "d ac d",
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
secondaryOrder: CustomSortOrder.byCreatedTimeReverseAdvanced, secondarySorting: { order: CustomSortOrder.byCreatedTimeReverseAdvanced, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "d m a", exactText: "d m a",
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
secondaryOrder: CustomSortOrder.byModifiedTime, secondarySorting: { order: CustomSortOrder.byModifiedTime, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "d m d", exactText: "d m d",
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
secondaryOrder: CustomSortOrder.byModifiedTimeReverse, secondarySorting: { order: CustomSortOrder.byModifiedTimeReverse, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "d am a", exactText: "d am a",
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
secondaryOrder: CustomSortOrder.byModifiedTimeAdvanced, secondarySorting: { order: CustomSortOrder.byModifiedTimeAdvanced, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
exactText: "d am d", exactText: "d am d",
order: CustomSortOrder.alphabeticalReverse, sorting: { order: CustomSortOrder.alphabeticalReverse, },
secondaryOrder: CustomSortOrder.byModifiedTimeReverseAdvanced, secondarySorting: { order: CustomSortOrder.byModifiedTimeReverseAdvanced, },
type: CustomSortGroupType.ExactName type: CustomSortGroupType.ExactName
},{ },{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
@ -1972,7 +2005,7 @@ describe('the sorting: prefix', () => {
const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md') const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
expect(result?.sortSpecByPath).toEqual({ expect(result?.sortSpecByPath).toEqual({
'mock-folder': { 'mock-folder': {
defaultOrder: CustomSortOrder.alphabetical, defaultSorting: { order: CustomSortOrder.alphabetical, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -1988,8 +2021,8 @@ describe('the sorting: prefix', () => {
const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md') const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
expect(result?.sortSpecByPath).toEqual({ expect(result?.sortSpecByPath).toEqual({
'mock-folder': { 'mock-folder': {
defaultOrder: CustomSortOrder.trueAlphabetical, defaultSorting: { order: CustomSortOrder.trueAlphabetical, },
defaultSecondaryOrder: CustomSortOrder.byModifiedTimeAdvanced, defaultSecondarySorting: { order: CustomSortOrder.byModifiedTimeAdvanced, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -2005,7 +2038,7 @@ describe('the sorting: prefix', () => {
const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md') const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
expect(result?.sortSpecByPath).toEqual({ expect(result?.sortSpecByPath).toEqual({
'mock-folder': { 'mock-folder': {
defaultOrder: CustomSortOrder.alphabeticalReverse, defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -2021,8 +2054,8 @@ describe('the sorting: prefix', () => {
const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md') const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
expect(result?.sortSpecByPath).toEqual({ expect(result?.sortSpecByPath).toEqual({
'mock-folder': { 'mock-folder': {
defaultOrder: CustomSortOrder.trueAlphabeticalReverse, defaultSorting: { order: CustomSortOrder.trueAlphabeticalReverse, },
defaultSecondaryOrder: CustomSortOrder.byModifiedTimeReverseAdvanced, defaultSecondarySorting: { order: CustomSortOrder.byModifiedTimeReverseAdvanced, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -2040,8 +2073,8 @@ describe('the sorting: prefix', () => {
expect(result?.sortSpecByPath).toEqual({ expect(result?.sortSpecByPath).toEqual({
'mock-folder': { 'mock-folder': {
groups: [{ groups: [{
order: CustomSortOrder.alphabeticalReverseWithFileExt, sorting: { order: CustomSortOrder.alphabeticalReverseWithFileExt, },
secondaryOrder: CustomSortOrder.byModifiedTimeAdvanced, secondarySorting: { order: CustomSortOrder.byModifiedTimeAdvanced, },
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
outsidersGroupIdx: 0, outsidersGroupIdx: 0,
@ -2071,7 +2104,7 @@ target-folder: .
const expectedSortSpecForMultiSpecAandB: { [key: string]: CustomSortSpec } = { const expectedSortSpecForMultiSpecAandB: { [key: string]: CustomSortSpec } = {
'mock-folder': { 'mock-folder': {
defaultOrder: CustomSortOrder.alphabetical, defaultSorting: { order: CustomSortOrder.alphabetical, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -2084,7 +2117,7 @@ const expectedWildcardMatchingTreeForMultiSpecAandB: FolderMatchingTreeNode<Cust
subtree: { subtree: {
"mock-folder": { "mock-folder": {
matchAll: { matchAll: {
"defaultOrder": CustomSortOrder.alphabeticalReverse, defaultSorting: { order: CustomSortOrder.alphabeticalReverse },
"groups": [{ "groups": [{
"type": CustomSortGroupType.Outsiders "type": CustomSortGroupType.Outsiders
}], }],
@ -2092,7 +2125,7 @@ const expectedWildcardMatchingTreeForMultiSpecAandB: FolderMatchingTreeNode<Cust
"targetFoldersPaths": ["mock-folder/*"] "targetFoldersPaths": ["mock-folder/*"]
}, },
matchChildren: { matchChildren: {
"defaultOrder": CustomSortOrder.byModifiedTime, defaultSorting: { order: CustomSortOrder.byModifiedTime },
"groups": [{ "groups": [{
"type": CustomSortGroupType.Outsiders "type": CustomSortGroupType.Outsiders
}], }],
@ -2125,7 +2158,7 @@ const expectedWildcardMatchingTreeForMultiSpecC: FolderMatchingTreeNode<CustomSo
subtree: { subtree: {
"mock-folder": { "mock-folder": {
matchAll: { matchAll: {
"defaultOrder": CustomSortOrder.alphabeticalReverse, defaultSorting: { order: CustomSortOrder.alphabeticalReverse },
"groups": [{ "groups": [{
"type": CustomSortGroupType.Outsiders "type": CustomSortGroupType.Outsiders
}], }],
@ -2168,7 +2201,7 @@ const expectedSortSpecForMultiSpecD: { [key: string]: CustomSortSpec } = {
const expectedSortSpecForMultiSpecD_implicitCase: { [key: string]: CustomSortSpec } = { const expectedSortSpecForMultiSpecD_implicitCase: { [key: string]: CustomSortSpec } = {
'mock-folder': { 'mock-folder': {
defaultOrder: CustomSortOrder.alphabeticalReverse, defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -2198,7 +2231,7 @@ const expectedWildcardMatchingTreeForMultiSpecD_implicitCase: FolderMatchingTree
subtree: { subtree: {
"mock-folder": { "mock-folder": {
matchAll: { matchAll: {
defaultOrder: CustomSortOrder.alphabeticalReverse, defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
"groups": [{ "groups": [{
"type": CustomSortGroupType.Outsiders "type": CustomSortGroupType.Outsiders
}], }],
@ -2235,7 +2268,7 @@ const expectedSortSpecForMultiSpecE: { [key: string]: CustomSortSpec } = {
const expectedSortSpecForMultiSpecE_implicitCase: { [key: string]: CustomSortSpec } = { const expectedSortSpecForMultiSpecE_implicitCase: { [key: string]: CustomSortSpec } = {
'mock-folder': { 'mock-folder': {
defaultOrder: CustomSortOrder.alphabeticalReverse, defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -2265,7 +2298,7 @@ const expectedWildcardMatchingTreeForMultiSpecE_implicitCase: FolderMatchingTree
subtree: { subtree: {
"mock-folder": { "mock-folder": {
matchChildren: { matchChildren: {
defaultOrder: CustomSortOrder.alphabeticalReverse, defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
"groups": [{ "groups": [{
"type": CustomSortGroupType.Outsiders "type": CustomSortGroupType.Outsiders
}], }],
@ -2290,7 +2323,7 @@ const expectedWildcardMatchingTreeForMultiSpecDplusE_implicitCase: FolderMatchin
"targetFoldersPaths": ["mock-folder/*"] "targetFoldersPaths": ["mock-folder/*"]
}, },
matchChildren: { matchChildren: {
defaultOrder: CustomSortOrder.alphabeticalReverse, defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
"groups": [{ "groups": [{
"type": CustomSortGroupType.Outsiders "type": CustomSortGroupType.Outsiders
}], }],
@ -2313,7 +2346,7 @@ target-folder: mock-folder
const expectedSortSpecForMultiSpecF_implicitCase: { [key: string]: CustomSortSpec } = { const expectedSortSpecForMultiSpecF_implicitCase: { [key: string]: CustomSortSpec } = {
'mock-folder': { 'mock-folder': {
defaultOrder: CustomSortOrder.alphabeticalReverse, defaultSorting: { order: CustomSortOrder.alphabeticalReverse, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -2430,7 +2463,7 @@ target-folder: AA
const expectedSortSpecForAdvancedFolderDateSortingMethods: { [key: string]: CustomSortSpec } = { const expectedSortSpecForAdvancedFolderDateSortingMethods: { [key: string]: CustomSortSpec } = {
'A': { 'A': {
defaultOrder: CustomSortOrder.byModifiedTimeAdvanced, defaultSorting: { order: CustomSortOrder.byModifiedTimeAdvanced, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -2438,7 +2471,7 @@ const expectedSortSpecForAdvancedFolderDateSortingMethods: { [key: string]: Cust
targetFoldersPaths: ['A'] targetFoldersPaths: ['A']
}, },
'B': { 'B': {
defaultOrder: CustomSortOrder.byModifiedTimeReverseAdvanced, defaultSorting: { order: CustomSortOrder.byModifiedTimeReverseAdvanced, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -2446,7 +2479,7 @@ const expectedSortSpecForAdvancedFolderDateSortingMethods: { [key: string]: Cust
targetFoldersPaths: ['B'] targetFoldersPaths: ['B']
}, },
'C': { 'C': {
defaultOrder: CustomSortOrder.byCreatedTimeAdvanced, defaultSorting: { order: CustomSortOrder.byCreatedTimeAdvanced, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -2454,7 +2487,7 @@ const expectedSortSpecForAdvancedFolderDateSortingMethods: { [key: string]: Cust
targetFoldersPaths: ['C'] targetFoldersPaths: ['C']
}, },
'D': { 'D': {
defaultOrder: CustomSortOrder.byCreatedTimeReverseAdvanced, defaultSorting: { order: CustomSortOrder.byCreatedTimeReverseAdvanced, },
groups: [{ groups: [{
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}], }],
@ -2464,41 +2497,41 @@ const expectedSortSpecForAdvancedFolderDateSortingMethods: { [key: string]: Cust
'AA': { 'AA': {
groups: [{ groups: [{
foldersOnly: true, foldersOnly: true,
order: CustomSortOrder.byModifiedTimeAdvanced, sorting: { order: CustomSortOrder.byModifiedTimeAdvanced, },
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}, { }, {
filesOnly: true, filesOnly: true,
order: CustomSortOrder.byModifiedTimeReverseAdvanced, sorting: { order: CustomSortOrder.byModifiedTimeReverseAdvanced, },
type: CustomSortGroupType.Outsiders type: CustomSortGroupType.Outsiders
}, { }, {
exactPrefix: 'Archive', exactPrefix: 'Archive',
foldersOnly: true, foldersOnly: true,
order: CustomSortOrder.byCreatedTimeAdvanced, sorting: { order: CustomSortOrder.byCreatedTimeAdvanced, },
type: CustomSortGroupType.ExactPrefix type: CustomSortGroupType.ExactPrefix
}, { }, {
exactPrefix: 'Archive', exactPrefix: 'Archive',
filesOnly: true, filesOnly: true,
order: CustomSortOrder.byCreatedTimeReverseAdvanced, sorting: { order: CustomSortOrder.byCreatedTimeReverseAdvanced, },
type: CustomSortGroupType.ExactPrefix type: CustomSortGroupType.ExactPrefix
}, { }, {
exactPrefix: 'Deep1', exactPrefix: 'Deep1',
foldersOnly: true, foldersOnly: true,
order: CustomSortOrder.byCreatedTimeAdvancedRecursive, sorting: { order: CustomSortOrder.byCreatedTimeAdvancedRecursive, },
type: CustomSortGroupType.ExactPrefix type: CustomSortGroupType.ExactPrefix
}, { }, {
exactPrefix: 'Deep2', exactPrefix: 'Deep2',
filesOnly: true, filesOnly: true,
order: CustomSortOrder.byCreatedTimeReverseAdvancedRecursive, sorting: { order: CustomSortOrder.byCreatedTimeReverseAdvancedRecursive, },
type: CustomSortGroupType.ExactPrefix type: CustomSortGroupType.ExactPrefix
}, { }, {
exactPrefix: 'Deep3', exactPrefix: 'Deep3',
foldersOnly: true, foldersOnly: true,
order: CustomSortOrder.byModifiedTimeAdvancedRecursive, sorting: { order: CustomSortOrder.byModifiedTimeAdvancedRecursive, },
type: CustomSortGroupType.ExactPrefix type: CustomSortGroupType.ExactPrefix
}, { }, {
exactPrefix: 'Deep4', exactPrefix: 'Deep4',
filesOnly: true, filesOnly: true,
order: CustomSortOrder.byModifiedTimeReverseAdvancedRecursive, sorting: { order: CustomSortOrder.byModifiedTimeReverseAdvancedRecursive, },
type: CustomSortGroupType.ExactPrefix type: CustomSortGroupType.ExactPrefix
}], }],
outsidersFilesGroupIdx: 1, outsidersFilesGroupIdx: 1,