import type { AttributeToken } from 'pug-lexer' ; import type { PugSortAttributes } from './index' ; /** Compare result. */ type CompareResult = - 1 | 0 | 1 ; /** Compare function. */ type CompareFunction < T > = ( a : T , b : T ) => CompareResult ; param a param b param sortAttributes param sortAttributesBeginning param sortAttributesEnd returns export function compareAttributeToken ( a , b , sortAttributes , sortAttributesBeginning , sortAttributesEnd ) { const sortPatternsBeginning = sortAttributesBeginning . map ( ( sort ) => new RegExp ( sort ) ) . reverse ( ) ; const sortPatternsEnd = sortAttributesEnd . map ( ( sort ) => new RegExp ( sort ) ) ; const aName = a . name ; const bName = b . name ; if ( sortPatternsBeginning . length > 0 ) { const aBeginningIndex = sortPatternsBeginning . findIndex ( ( pattern ) => pattern . test ( aName ) ) ; const bBeginningIndex = sortPatternsBeginning . findIndex ( ( pattern ) => pattern . test ( bName ) ) ; const beginning = aBeginningIndex - bBeginningIndex ; if ( beginning > 0 ) { return - 1 ; } if ( beginning < 0 ) { return 1 ; } } if ( sortPatternsEnd . length > 0 ) { const aEndIndex = sortPatternsEnd . findIndex ( ( pattern ) => pattern . test ( aName ) ) ; const bEndIndex = sortPatternsEnd . findIndex ( ( pattern ) => pattern . test ( bName ) ) ; const end = aEndIndex - bEndIndex ; if ( end > 0 ) { return 1 ; } if ( end < 0 ) { return - 1 ; } } switch ( sortAttributes ) { case 'asc' : { if ( aName > bName ) { return 1 ; } if ( aName < bName ) { return - 1 ; } break ; } case 'desc' : { if ( aName > bName ) { return - 1 ; } if ( aName < bName ) { return 1 ; } break ; } } return 0 ; } param array param compare returns export function stableSort < T > ( array , compare ) { const entries = array . map ( ( value , index ) => [ value , index , ] ) ; entries . sort ( ( a , b ) => { const order = compare ( a [ 0 ] , b [ 0 ] ) ; return order !== 0 ? order : a [ 1 ] - b [ 1 ] ; } ) ; return entries . map ( ( [ value ] ) => value ) ; } param arr param start param end param compareFn returns export function partialSort < T > ( arr , start , end , compareFn ) { const preSort = arr . slice ( 0 , start ) ; const postSort = arr . slice ( end ) ; const attributes = arr . slice ( start , end ) ; const sorted = stableSort ( attributes , compareFn ) ; return [ ... preSort , ... sorted , ... postSort ] ; }