@@ -35,6 +35,10 @@ import {
3535 MATCH_CHILDREN_2_SUFFIX ,
3636 NO_PRIORITY
3737} from "./folder-matching-rules"
38+ import {
39+ MDataExtractor ,
40+ tryParseAsMDataExtractorSpec
41+ } from "./mdata-extractors" ;
3842
3943interface ProcessingContext {
4044 folderPath : string
@@ -114,6 +118,7 @@ interface CustomSortOrderAscDescPair {
114118interface CustomSortOrderSpec {
115119 order : CustomSortOrder
116120 byMetadataField ?: string
121+ metadataFieldExtractor ?: MDataExtractor
117122}
118123
119124const MAX_SORT_LEVEL : number = 1
@@ -141,6 +146,8 @@ const OrderLiterals: { [key: string]: CustomSortOrderAscDescPair } = {
141146
142147const OrderByMetadataLexeme : string = 'by-metadata:'
143148
149+ const ValueExtractorLexeme : string = 'using-extractor:'
150+
144151const OrderLevelsSeparator : string = ','
145152
146153enum Attribute {
@@ -1090,8 +1097,10 @@ export class SortingSpecProcessor {
10901097 }
10911098 this . ctx . currentSpec . defaultOrder = ( attr . value as RecognizedOrderValue ) . order
10921099 this . ctx . currentSpec . byMetadataField = ( attr . value as RecognizedOrderValue ) . applyToMetadataField
1100+ this . ctx . currentSpec . metadataFieldValueExtractor = ( attr . value as RecognizedOrderValue ) . metadataValueExtractor
10931101 this . ctx . currentSpec . defaultSecondaryOrder = ( attr . value as RecognizedOrderValue ) . secondaryOrder
10941102 this . ctx . currentSpec . byMetadataFieldSecondary = ( attr . value as RecognizedOrderValue ) . secondaryApplyToMetadataField
1103+ this . ctx . currentSpec . metadataFieldSecondaryValueExtractor = ( attr . value as RecognizedOrderValue ) . secondaryMetadataValueExtractor
10951104 return true ;
10961105 } else if ( attr . nesting > 0 ) { // For now only distinguishing nested (indented) and not-nested (not-indented), the depth doesn't matter
10971106 if ( ! this . ctx . currentSpec || ! this . ctx . currentSpecGroup ) {
@@ -1105,8 +1114,10 @@ export class SortingSpecProcessor {
11051114 }
11061115 this . ctx . currentSpecGroup . order = ( attr . value as RecognizedOrderValue ) . order
11071116 this . ctx . currentSpecGroup . byMetadataField = ( attr . value as RecognizedOrderValue ) . applyToMetadataField
1117+ this . ctx . currentSpecGroup . metadataFieldValueExtractor = ( attr . value as RecognizedOrderValue ) . metadataValueExtractor
11081118 this . ctx . currentSpecGroup . secondaryOrder = ( attr . value as RecognizedOrderValue ) . secondaryOrder
11091119 this . ctx . currentSpecGroup . byMetadataFieldSecondary = ( attr . value as RecognizedOrderValue ) . secondaryApplyToMetadataField
1120+ this . ctx . currentSpecGroup . metadataFieldSecondaryValueExtractor = ( attr . value as RecognizedOrderValue ) . secondaryMetadataValueExtractor
11101121 return true ;
11111122 }
11121123 }
@@ -1506,10 +1517,29 @@ export class SortingSpecProcessor {
15061517 orderSpec = hasDirectionPostfix ? orderSpec . substring ( hasDirectionPostfix . lexeme . length ) . trim ( ) : orderSpec
15071518
15081519 let metadataName : string | undefined
1520+ let metadataExtractor : MDataExtractor | undefined
15091521 if ( orderSpec . startsWith ( OrderByMetadataLexeme ) ) {
15101522 applyToMetadata = true
1511- metadataName = orderSpec . substring ( OrderByMetadataLexeme . length ) . trim ( ) || undefined
1512- orderSpec = '' // metadataName is unparsed, consumes the remainder string, even if malformed, e.g. with infix spaces
1523+ const metadataNameAndOptionalExtractorSpec = orderSpec . substring ( OrderByMetadataLexeme . length ) . trim ( ) || undefined
1524+ if ( metadataNameAndOptionalExtractorSpec ) {
1525+ if ( metadataNameAndOptionalExtractorSpec . indexOf ( ValueExtractorLexeme ) > - 1 ) {
1526+ const metadataSpec = metadataNameAndOptionalExtractorSpec . split ( ValueExtractorLexeme )
1527+ metadataName = metadataSpec . shift ( ) ?. trim ( )
1528+ const metadataExtractorSpec = metadataSpec ?. shift ( ) ?. trim ( )
1529+ const hasMetadataExtractor = metadataExtractorSpec ? tryParseAsMDataExtractorSpec ( metadataExtractorSpec ) : undefined
1530+ if ( hasMetadataExtractor ) {
1531+ metadataExtractor = hasMetadataExtractor . m
1532+ } else {
1533+ return new AttrError ( `${ orderNameForErrorMsg } sorting order contains unrecognized value extractor: >>> ${ metadataExtractorSpec } <<<` )
1534+ }
1535+ orderSpec = '' // all consumed as metadata and extractor
1536+ } else {
1537+ metadataName = metadataNameAndOptionalExtractorSpec
1538+ orderSpec = '' // all consumed as metadata name
1539+ }
1540+ } else {
1541+ orderSpec = '' // no metadata name found
1542+ }
15131543 }
15141544
15151545 // check for any superfluous text
@@ -1562,7 +1592,8 @@ export class SortingSpecProcessor {
15621592 }
15631593 sortOrderSpec [ level ] = {
15641594 order : order ! ,
1565- byMetadataField : metadataName
1595+ byMetadataField : metadataName ,
1596+ metadataFieldExtractor : metadataExtractor
15661597 }
15671598 }
15681599 return sortOrderSpec
@@ -1573,8 +1604,10 @@ export class SortingSpecProcessor {
15731604 return recognized ? ( recognized instanceof AttrError ? recognized : {
15741605 order : recognized [ 0 ] . order ,
15751606 applyToMetadataField : recognized [ 0 ] . byMetadataField ,
1607+ metadataValueExtractor : recognized [ 0 ] . metadataFieldExtractor ,
15761608 secondaryOrder : recognized [ 1 ] ?. order ,
1577- secondaryApplyToMetadataField : recognized [ 1 ] ?. byMetadataField
1609+ secondaryApplyToMetadataField : recognized [ 1 ] ?. byMetadataField ,
1610+ secondaryMetadataValueExtractor : recognized [ 1 ] ?. metadataFieldExtractor
15781611 } ) : null ;
15791612 }
15801613
0 commit comments