Major refactoring of sorting structures. Refactored the code. Unit tests not touched, broken.
This commit is contained in:
parent
99cea92322
commit
eeb581120d
|
@ -50,15 +50,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
|
||||||
|
|
||||||
|
@ -67,6 +58,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
|
||||||
|
@ -74,12 +76,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
|
||||||
|
@ -92,12 +90,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)
|
||||||
|
|
|
@ -63,12 +63,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
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
ObsidianIconFolder_PluginInstance
|
ObsidianIconFolder_PluginInstance
|
||||||
} from '../utils/ObsidianIconFolderPluginSignature'
|
} from '../utils/ObsidianIconFolderPluginSignature'
|
||||||
import {
|
import {
|
||||||
|
CustomSort,
|
||||||
CustomSortGroup,
|
CustomSortGroup,
|
||||||
CustomSortGroupType,
|
CustomSortGroupType,
|
||||||
CustomSortOrder,
|
CustomSortOrder,
|
||||||
|
@ -294,18 +295,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]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,13 +316,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
|
||||||
|
@ -567,10 +568,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'
|
||||||
|
@ -586,26 +587,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)
|
||||||
}
|
}
|
||||||
|
@ -707,12 +708,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) => {
|
||||||
|
@ -732,15 +733,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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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";
|
||||||
|
@ -113,12 +114,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!
|
||||||
|
@ -1081,34 +1076,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1397,7 +1386,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
|
||||||
}
|
}
|
||||||
|
@ -1412,34 +1401,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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1481,13 +1462,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++) {
|
||||||
|
@ -1583,22 +1564,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue