|
1 | | -import { closestEntries, passesFilters as passes, queryTests as compileQuery, readState, scoreFields, searchFields, slugOf, stateQuery } from "./search.js"; |
| 1 | +import { closestEntries, passesFilters as passes, queryTests as compileQuery, readState, scoreFields, searchFields, slugOf, stateQuery, ENGINES, engineRank } from "./search.js"; |
2 | 2 | import { CARD_LIMIT, LIST_LIMIT, commercialLabel, entryCardHtml, escapeHtml, groupHeadingHtml, groupMoreHtml, PERSPECTIVE_LABELS } from "./cards.mjs"; |
3 | 3 | import { installViewToggles } from "./views.js"; |
4 | 4 |
|
@@ -29,6 +29,7 @@ import { installViewToggles } from "./views.js"; |
29 | 29 | perspective: "any", |
30 | 30 | license: "any", |
31 | 31 | format: "any", |
| 32 | + engine: "any", |
32 | 33 | sort: "name", |
33 | 34 | }; |
34 | 35 | const state = { ...DEFAULTS }; |
@@ -78,6 +79,7 @@ import { installViewToggles } from "./views.js"; |
78 | 79 | sort: Object.keys(SORTS), |
79 | 80 | perspective: ["any", ...Object.keys(PERSPECTIVE_LABELS)], |
80 | 81 | license: ["any", ...Object.keys(LICENSE_FAMILIES)], |
| 82 | + engine: ["any", ...Object.keys(ENGINES)], |
81 | 83 | format: ["any", ...Object.keys(FORMAT_GROUPS)], |
82 | 84 | }) |
83 | 85 | ); |
@@ -143,7 +145,7 @@ import { installViewToggles } from "./views.js"; |
143 | 145 | // Searching under the default sort: best match first, then by name. |
144 | 146 | list.sort((a, b) => score.get(b.id) - score.get(a.id) || SORTS.name(a, b)); |
145 | 147 | } else { |
146 | | - list.sort(SORTS[state.sort] || SORTS.name); |
| 148 | + list.sort(sorter()); |
147 | 149 | } |
148 | 150 | return { list, counts, total: pool.length, ranked }; |
149 | 151 | } |
@@ -179,6 +181,13 @@ import { installViewToggles } from "./views.js"; |
179 | 181 | a.name.localeCompare(b.name), |
180 | 182 | }; |
181 | 183 |
|
| 184 | + /** The chosen sort, with entries made for the chosen engine first. */ |
| 185 | + function sorter() { |
| 186 | + const by = SORTS[state.sort] || SORTS.name; |
| 187 | + if (state.engine === "any") return by; |
| 188 | + return (a, b) => engineRank(a, state.engine) - engineRank(b, state.engine) || by(a, b); |
| 189 | + } |
| 190 | + |
182 | 191 | /* ---------------------------------------------------------- rendering */ |
183 | 192 |
|
184 | 193 | /** A category's view on this page: the config default (cards or list). */ |
@@ -278,6 +287,7 @@ import { installViewToggles } from "./views.js"; |
278 | 287 | }); |
279 | 288 | if (state.license !== DEFAULTS.license) |
280 | 289 | chips.push({ key: "license", label: `licence: ${LICENSE_FAMILIES[state.license] || state.license}` }); |
| 290 | + if (state.engine !== DEFAULTS.engine) chips.push({ key: "engine", label: `engine: ${ENGINES[state.engine]?.label || state.engine}` }); |
281 | 291 | if (state.format !== DEFAULTS.format) |
282 | 292 | chips.push({ key: "format", label: `format: ${FORMAT_GROUPS[state.format]?.label || state.format}` }); |
283 | 293 | if (!state.active) chips.push({ key: "active", label: "hiding active" }); |
@@ -443,7 +453,7 @@ import { installViewToggles } from "./views.js"; |
443 | 453 | placedKey = key; |
444 | 454 | const shown = new Set(list.map((e) => e.id)); |
445 | 455 | const rest = data.entries.filter((e) => !shown.has(e.id)); |
446 | | - const all = ranked ? [...list, ...rest] : data.entries.slice().sort(SORTS[state.sort] || SORTS.name); |
| 456 | + const all = ranked ? [...list, ...rest] : data.entries.slice().sort(sorter()); |
447 | 457 | // Entries not rendered yet (the preview page) are simply not placed. |
448 | 458 | const node = (e) => cardNodes.get(e.id); |
449 | 459 | const order = [flatHeading]; |
@@ -670,6 +680,7 @@ import { installViewToggles } from "./views.js"; |
670 | 680 |
|
671 | 681 | const selects = [ |
672 | 682 | ["#license-family", "license", LICENSE_FAMILIES], |
| 683 | + ["#engine", "engine", Object.fromEntries(Object.entries(ENGINES).map(([k, e]) => [k, e.label]))], |
673 | 684 | ["#format-group", "format", Object.fromEntries(Object.entries(FORMAT_GROUPS).map(([k, g]) => [k, g.label]))], |
674 | 685 | ]; |
675 | 686 | for (const [sel, field, choices] of selects) { |
@@ -870,6 +881,7 @@ import { installViewToggles } from "./views.js"; |
870 | 881 | $("#sort").value = state.sort; |
871 | 882 | $("#perspective").value = state.perspective; |
872 | 883 | $("#license-family").value = state.license; |
| 884 | + $("#engine").value = state.engine; |
873 | 885 | $("#format-group").value = state.format; |
874 | 886 | } |
875 | 887 |
|
|
0 commit comments