|
| 1 | +import { DockerRegistryUIError } from './error.js'; |
| 2 | +import { isDigit } from './utils.js'; |
| 3 | + |
| 4 | +const TAGLIST_ORDER_REGEX = /(alpha-(asc|desc);num-(asc|desc))|(num-(asc|desc);alpha-(asc|desc))/; |
| 5 | + |
| 6 | +export const taglistOrderVariants = (taglistOrder) => { |
| 7 | + switch (taglistOrder) { |
| 8 | + case 'desc': |
| 9 | + return 'alpha-desc;num-desc'; |
| 10 | + case 'asc': |
| 11 | + return 'num-asc;alpha-asc'; |
| 12 | + case 'alpha-desc': |
| 13 | + case 'alpha-asc': |
| 14 | + case 'num-desc': |
| 15 | + case 'num-asc': |
| 16 | + return `${taglistOrder};${taglistOrder.startsWith('num') ? 'alpha' : 'num'}-asc`; |
| 17 | + default: |
| 18 | + if (!taglistOrder) { |
| 19 | + return 'alpha-asc;num-desc'; |
| 20 | + } else if (TAGLIST_ORDER_REGEX.test(taglistOrder)) { |
| 21 | + return taglistOrder; |
| 22 | + } |
| 23 | + throw new DockerRegistryUIError(`The taglist order \`${taglistOrder}\` is not recognized.`); |
| 24 | + } |
| 25 | +}; |
| 26 | + |
| 27 | +export const taglistOrderParser = (taglistOrder) => { |
| 28 | + const orders = taglistOrderVariants(taglistOrder) |
| 29 | + .split(';') |
| 30 | + .filter((e) => e) |
| 31 | + .map((e) => e.split('-').filter((e) => e)) |
| 32 | + .reduce((acc, e, idx) => { |
| 33 | + if (e.length > 1) { |
| 34 | + acc[e[0] + 'Asc'] = e[1] === 'asc'; |
| 35 | + } |
| 36 | + if (idx === 0) { |
| 37 | + acc.numFirst = e[0] === 'num'; |
| 38 | + } |
| 39 | + return acc; |
| 40 | + }, {}); |
| 41 | + |
| 42 | + return orders; |
| 43 | +}; |
| 44 | + |
| 45 | +export const tagReduce = (acc, e) => { |
| 46 | + if (acc.length > 0 && isDigit(acc[acc.length - 1].charAt(0)) == isDigit(e)) { |
| 47 | + acc[acc.length - 1] += e; |
| 48 | + } else { |
| 49 | + acc.push(e); |
| 50 | + } |
| 51 | + return acc; |
| 52 | +}; |
| 53 | + |
| 54 | +export const splitTagToArray = (tag) => |
| 55 | + tag |
| 56 | + .split('') |
| 57 | + .reduce(tagReduce, []) |
| 58 | + .map((e) => (isDigit(e.charAt(0)) ? parseInt(e) : e)); |
| 59 | + |
| 60 | +const applyOrder = (order, e1, e2) => { |
| 61 | + if (e1 === e2) { |
| 62 | + return 0; |
| 63 | + } |
| 64 | + const numFirst = order.numFirst ? 1 : -1; |
| 65 | + if (typeof e1 === 'number') { |
| 66 | + const factor = order.numAsc ? 1 : -1; |
| 67 | + return typeof e2 === 'number' ? (e1 - e2) * factor : -1 * numFirst; |
| 68 | + } else if (typeof e2 === 'number') { |
| 69 | + return 1 * numFirst; |
| 70 | + } else { |
| 71 | + const factor = order.alphaAsc ? 1 : -1; |
| 72 | + return e1.localeCompare(e2) * factor; |
| 73 | + } |
| 74 | +}; |
| 75 | + |
| 76 | +export const getTagComparator = (order) => { |
| 77 | + return (e1, e2) => { |
| 78 | + const tag1 = splitTagToArray(e1.tag || e1); |
| 79 | + const tag2 = splitTagToArray(e2.tag || e2); |
| 80 | + |
| 81 | + for (var i = 0; i < tag1.length && i < tag2.length; i++) { |
| 82 | + const compare = applyOrder(order, tag1[i], tag2[i]); |
| 83 | + if (compare != 0) { |
| 84 | + return compare; |
| 85 | + } |
| 86 | + } |
| 87 | + return (e1.tag || e1).length - (e2.tag || e2).length; |
| 88 | + }; |
| 89 | +}; |
0 commit comments