add natsort
This commit is contained in:
		
							parent
							
								
									cb4766cc17
								
							
						
					
					
						commit
						2a9328665a
					
				
					 2 changed files with 185 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -4,6 +4,7 @@ import { extname, join } from "path/posix.ts";
 | 
			
		|||
import { ComponentChild } from "preact";
 | 
			
		||||
import UpList from "./UpList.tsx";
 | 
			
		||||
import { extToIcon } from "../src/media.ts";
 | 
			
		||||
import natsort from "../src/natsort.ts";
 | 
			
		||||
import { encodePath } from "../util/util.ts";
 | 
			
		||||
 | 
			
		||||
function ListItem(props: {
 | 
			
		||||
| 
						 | 
				
			
			@ -34,10 +35,15 @@ interface DirListProps {
 | 
			
		|||
  path: string;
 | 
			
		||||
  files: EntryInfo[];
 | 
			
		||||
}
 | 
			
		||||
const natsortCompare = natsort();
 | 
			
		||||
 | 
			
		||||
export function DirList(props: DirListProps) {
 | 
			
		||||
  const data = props;
 | 
			
		||||
  const [files, setFiles] = useState(data.files);
 | 
			
		||||
  const [files, setFiles] = useState(
 | 
			
		||||
    data.files.toSorted(
 | 
			
		||||
      (a,b)=> natsortCompare(a.name,b.name)
 | 
			
		||||
      )
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div>
 | 
			
		||||
| 
						 | 
				
			
			@ -95,7 +101,7 @@ export function DirList(props: DirListProps) {
 | 
			
		|||
    const sorted_files = files.map((x, i) => ([x, i] as [EntryInfo, number]))
 | 
			
		||||
      .sort(
 | 
			
		||||
        ([a, ai], [b, bi]) => {
 | 
			
		||||
          const ret = a.name.localeCompare(b.name);
 | 
			
		||||
          const ret = natsortCompare(a.name, b.name);
 | 
			
		||||
          if (ret === 0) {
 | 
			
		||||
            return ai - bi;
 | 
			
		||||
          } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -107,4 +113,6 @@ export function DirList(props: DirListProps) {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default DirList;
 | 
			
		||||
export default function DirListIsland(props: DirListProps){
 | 
			
		||||
  return <DirList {...props}/>
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										174
									
								
								src/natsort.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								src/natsort.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,174 @@
 | 
			
		|||
/**
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2016 W.Y.
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
export type OptionsType = {
 | 
			
		||||
    /*
 | 
			
		||||
    * Desc sorting.
 | 
			
		||||
    */
 | 
			
		||||
    desc?: boolean,
 | 
			
		||||
    /*
 | 
			
		||||
    * Case-Insensitive sorting.
 | 
			
		||||
    */
 | 
			
		||||
    insensitive?: boolean,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default function natsort(options: OptionsType = {}) {
 | 
			
		||||
 | 
			
		||||
    const ore = /^0/
 | 
			
		||||
    const sre = /\s+/g
 | 
			
		||||
    const tre = /^\s+|\s+$/g
 | 
			
		||||
    // unicode
 | 
			
		||||
    const ure = /[^\x00-\x80]/
 | 
			
		||||
    // hex
 | 
			
		||||
    const hre = /^0x[0-9a-f]+$/i
 | 
			
		||||
    // numeric
 | 
			
		||||
    const nre = /(0x[\da-fA-F]+|(^[\+\-]?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?(?=\D|\s|$))|\d+)/g
 | 
			
		||||
    // datetime
 | 
			
		||||
    const dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/ // tslint:disable-line
 | 
			
		||||
    const toLowerCase = String.prototype.toLocaleLowerCase || String.prototype.toLowerCase
 | 
			
		||||
 | 
			
		||||
    const GREATER = options.desc ? -1 : 1
 | 
			
		||||
    const SMALLER = -GREATER
 | 
			
		||||
    const normalize = options.insensitive
 | 
			
		||||
        ? (s: string | number) => toLowerCase.call(`${s}`).replace(tre, '')
 | 
			
		||||
        : (s: string | number) => (`${s}`).replace(tre, '')
 | 
			
		||||
 | 
			
		||||
    function tokenize(s: string): string[] {
 | 
			
		||||
        return s.replace(nre, '\0$1\0')
 | 
			
		||||
            .replace(/\0$/, '')
 | 
			
		||||
            .replace(/^\0/, '')
 | 
			
		||||
            .split('\0')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function parse(s: string, l: number) {
 | 
			
		||||
        // normalize spaces; find floats not starting with '0',
 | 
			
		||||
        // string or 0 if not defined (Clint Priest)
 | 
			
		||||
        return (!s.match(ore) || l === 1)
 | 
			
		||||
            && parseFloat(s)
 | 
			
		||||
            || s.replace(sre, ' ').replace(tre, '')
 | 
			
		||||
            || 0
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return function (
 | 
			
		||||
        a: string | number,
 | 
			
		||||
        b: string | number,
 | 
			
		||||
    ): number {
 | 
			
		||||
 | 
			
		||||
        // trim pre-post whitespace
 | 
			
		||||
        const aa = normalize(a)
 | 
			
		||||
        const bb = normalize(b)
 | 
			
		||||
 | 
			
		||||
        // return immediately if at least one of the values is empty.
 | 
			
		||||
        // empty string < any others
 | 
			
		||||
        if (!aa && !bb) {
 | 
			
		||||
            return 0
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!aa && bb) {
 | 
			
		||||
            return SMALLER
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (aa && !bb) {
 | 
			
		||||
            return GREATER
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // tokenize: split numeric strings and default strings
 | 
			
		||||
        const aArr = tokenize(aa)
 | 
			
		||||
        const bArr = tokenize(bb)
 | 
			
		||||
 | 
			
		||||
        // hex or date detection
 | 
			
		||||
        const aHex = aa.match(hre)
 | 
			
		||||
        const bHex = bb.match(hre)
 | 
			
		||||
        const av = (aHex && bHex) ? parseInt(aHex[0], 16) : (aArr.length !== 1 && Date.parse(aa))
 | 
			
		||||
        const bv = (aHex && bHex)
 | 
			
		||||
            ? parseInt(bHex[0], 16)
 | 
			
		||||
            : av && bb.match(dre) && Date.parse(bb) || null
 | 
			
		||||
 | 
			
		||||
        // try and sort Hex codes or Dates
 | 
			
		||||
        if (bv) {
 | 
			
		||||
            if (av === bv) {
 | 
			
		||||
                return 0
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (av < bv) {
 | 
			
		||||
                return SMALLER
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (av > bv) {
 | 
			
		||||
                return GREATER
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const al = aArr.length
 | 
			
		||||
        const bl = bArr.length
 | 
			
		||||
 | 
			
		||||
        // handle numeric strings and default strings
 | 
			
		||||
        for (let i = 0, l = Math.max(al, bl); i < l; i += 1) {
 | 
			
		||||
 | 
			
		||||
            const af = parse(aArr[i] || '', al)
 | 
			
		||||
            const bf = parse(bArr[i] || '', bl)
 | 
			
		||||
 | 
			
		||||
            // handle numeric vs string comparison.
 | 
			
		||||
            // numeric < string
 | 
			
		||||
            if (isNaN(af as number) !== isNaN(bf as number)) {
 | 
			
		||||
                return isNaN(af as number) ? GREATER : SMALLER
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // if unicode use locale comparison
 | 
			
		||||
            if (ure.test((af as string) + (bf as string)) && (af as string).localeCompare) {
 | 
			
		||||
                const comp = (af as string).localeCompare(bf as string)
 | 
			
		||||
 | 
			
		||||
                if (comp > 0) {
 | 
			
		||||
                    return GREATER
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (comp < 0) {
 | 
			
		||||
                    return SMALLER
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (i === l - 1) {
 | 
			
		||||
                    return 0
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (af < bf) {
 | 
			
		||||
                return SMALLER
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (af > bf) {
 | 
			
		||||
                return GREATER
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (`${af}` < `${bf}`) {
 | 
			
		||||
                return SMALLER
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (`${af}` > `${bf}`) {
 | 
			
		||||
                return GREATER
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return 0
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue