From 3adf33b567c53e79ce45a36031b29da719fb2377 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Mon, 21 Aug 2023 22:14:04 -0300 Subject: sugar: showAggregate: display top-level non-AggregateErrors w/ more detail --- src/util/sugar.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/util') diff --git a/src/util/sugar.js b/src/util/sugar.js index 487c093c..5b1f3193 100644 --- a/src/util/sugar.js +++ b/src/util/sugar.js @@ -574,7 +574,12 @@ export function showAggregate(topError, { } }; - const message = recursive(topError, {level: 0}); + const message = + (topError instanceof AggregateError + ? recursive(topError, {level: 0}) + : (showTraces + ? topError.stack + : topError.toString())); if (print) { console.error(message); -- cgit 1.3.0-6-gf8a5 From 98133431c801a823f3430b0e178c56350e12622c Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Mon, 21 Aug 2023 22:14:34 -0300 Subject: write: static-build: gently log failed content functions & continue --- src/util/cli.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/util') diff --git a/src/util/cli.js b/src/util/cli.js index f83c8061..e8c8c79f 100644 --- a/src/util/cli.js +++ b/src/util/cli.js @@ -334,7 +334,9 @@ export function progressCallAll(msgOrMsgFn, array) { export function fileIssue({ topMessage = `This shouldn't happen.`, } = {}) { - console.error(color.red(`${topMessage} Please let the HSMusic developers know:`)); + if (topMessage) { + console.error(color.red(`${topMessage} Please let the HSMusic developers know:`)); + } console.error(color.red(`- https://hsmusic.wiki/feedback/`)); console.error(color.red(`- https://github.com/hsmusic/hsmusic-wiki/issues/`)); } -- cgit 1.3.0-6-gf8a5 From 75691866ed68b9261dd920b79d4ab214df3f049b Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 22 Aug 2023 13:02:19 -0300 Subject: data: filter only requested deps, require requesting 'this' * Thing.composite.from() only provides the dependencies specified in each step and the base, and prevents '#'-prefixed keys from being specified on the main (composite) dependency list. * CacheableObject no longer provides a "reflection" dependency to every compute/transform function, and now requires the property 'this' to be specified instead of the constructor.instance symbol. (The static CacheableObject.instance, inherited by all subclasses, was also removed.) * Also minor improvements to sugar.js data processing utility functions. --- src/util/sugar.js | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'src/util') diff --git a/src/util/sugar.js b/src/util/sugar.js index 5b1f3193..1ba3f3ae 100644 --- a/src/util/sugar.js +++ b/src/util/sugar.js @@ -168,12 +168,24 @@ export function setIntersection(set1, set2) { return intersection; } -export function filterProperties(obj, properties) { - const set = new Set(properties); - return Object.fromEntries( - Object - .entries(obj) - .filter(([key]) => set.has(key))); +export function filterProperties(object, properties) { + if (typeof object !== 'object' || object === null) { + throw new TypeError(`Expected object to be an object, got ${object}`); + } + + if (!Array.isArray(properties)) { + throw new TypeError(`Expected properties to be an array, got ${properties}`); + } + + const filteredObject = {}; + + for (const property of properties) { + if (Object.hasOwn(object, property)) { + filteredObject[property] = object[property]; + } + } + + return filteredObject; } export function queue(array, max = 50) { -- cgit 1.3.0-6-gf8a5 From eb00f2993a1aaaba171ad6c918656552f80bb748 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Thu, 7 Sep 2023 12:38:34 -0300 Subject: data: import Thing.common utilities directly Also rename 'color' (from #cli) to 'colors'. --- src/util/cli.js | 2 +- src/util/sugar.js | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/util') diff --git a/src/util/cli.js b/src/util/cli.js index e8c8c79f..9f2b35ab 100644 --- a/src/util/cli.js +++ b/src/util/cli.js @@ -17,7 +17,7 @@ export const ENABLE_COLOR = const C = (n) => ENABLE_COLOR ? (text) => `\x1b[${n}m${text}\x1b[0m` : (text) => text; -export const color = { +export const colors = { bright: C('1'), dim: C('2'), normal: C('22'), diff --git a/src/util/sugar.js b/src/util/sugar.js index 1ba3f3ae..ebb7d61e 100644 --- a/src/util/sugar.js +++ b/src/util/sugar.js @@ -6,7 +6,7 @@ // It will likely only do exactly what I want it to, and only in the cases I // decided were relevant enough to 8other handling. -import {color} from './cli.js'; +import {colors} from './cli.js'; // Apparently JavaScript doesn't come with a function to split an array into // chunks! Weird. Anyway, this is an awesome place to use a generator, even @@ -566,10 +566,10 @@ export function showAggregate(topError, { .trim() .replace(/file:\/\/.*\.js/, (match) => pathToFileURL(match)) : '(no stack trace)'; - header += ` ${color.dim(tracePart)}`; + header += ` ${colors.dim(tracePart)}`; } - const bar = level % 2 === 0 ? '\u2502' : color.dim('\u254e'); - const head = level % 2 === 0 ? '\u257f' : color.dim('\u257f'); + const bar = level % 2 === 0 ? '\u2502' : colors.dim('\u254e'); + const head = level % 2 === 0 ? '\u257f' : colors.dim('\u257f'); if (error instanceof AggregateError) { return ( @@ -605,7 +605,7 @@ export function decorateErrorWithIndex(fn) { try { return fn(x, index, array); } catch (error) { - error.message = `(${color.yellow(`#${index + 1}`)}) ${error.message}`; + error.message = `(${colors.yellow(`#${index + 1}`)}) ${error.message}`; throw error; } }; -- cgit 1.3.0-6-gf8a5 From 19b6cbd1cde35399c0ecdee5459c5a4946e84299 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Fri, 8 Sep 2023 08:40:03 -0300 Subject: util: fix missing color -> colors rename in cli utils --- src/util/cli.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/util') diff --git a/src/util/cli.js b/src/util/cli.js index 9f2b35ab..4c08c085 100644 --- a/src/util/cli.js +++ b/src/util/cli.js @@ -335,8 +335,8 @@ export function fileIssue({ topMessage = `This shouldn't happen.`, } = {}) { if (topMessage) { - console.error(color.red(`${topMessage} Please let the HSMusic developers know:`)); + console.error(colors.red(`${topMessage} Please let the HSMusic developers know:`)); } - console.error(color.red(`- https://hsmusic.wiki/feedback/`)); - console.error(color.red(`- https://github.com/hsmusic/hsmusic-wiki/issues/`)); + console.error(colors.red(`- https://hsmusic.wiki/feedback/`)); + console.error(colors.red(`- https://github.com/hsmusic/hsmusic-wiki/issues/`)); } -- cgit 1.3.0-6-gf8a5 From 745322c71c2443a631533ad7ef651ea30ad87a7c Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Fri, 8 Sep 2023 08:45:30 -0300 Subject: util: remove unused getPagePathnameAcrossLanguages util --- src/util/urls.js | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'src/util') diff --git a/src/util/urls.js b/src/util/urls.js index d2b303e9..11b9b8b0 100644 --- a/src/util/urls.js +++ b/src/util/urls.js @@ -237,27 +237,6 @@ export function getPagePathname({ : to('localized.' + pagePath[0], ...pagePath.slice(1))); } -export function getPagePathnameAcrossLanguages({ - defaultLanguage, - languages, - pagePath, - urls, -}) { - return withEntries(languages, entries => entries - .filter(([key, language]) => key !== 'default' && !language.hidden) - .map(([_key, language]) => [ - language.code, - getPagePathname({ - baseDirectory: - (language === defaultLanguage - ? '' - : language.code), - pagePath, - urls, - }), - ])); -} - // Needed for the rare path arguments which themselves contains one or more // slashes, e.g. for listings, with arguments like 'albums/by-name'. export function getPageSubdirectoryPrefix({ -- cgit 1.3.0-6-gf8a5 From 21a270ca6efa561cad3e87048cf8deb8a166d55f Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Fri, 8 Sep 2023 08:51:20 -0300 Subject: fix miscellaneous eslint errors --- src/util/html.js | 2 +- src/util/replacer.js | 1 - src/util/wiki-data.js | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src/util') diff --git a/src/util/html.js b/src/util/html.js index a311bbba..b1668558 100644 --- a/src/util/html.js +++ b/src/util/html.js @@ -242,7 +242,7 @@ export class Tag { this.selfClosing && !(value === null || value === undefined || - !Boolean(value) || + !value || Array.isArray(value) && value.filter(Boolean).length === 0) ) { throw new Error(`Tag <${this.tagName}> is self-closing but got content`); diff --git a/src/util/replacer.js b/src/util/replacer.js index c5289cc5..647d1f0e 100644 --- a/src/util/replacer.js +++ b/src/util/replacer.js @@ -5,7 +5,6 @@ // function, which converts nodes parsed here into actual HTML, links, etc // for embedding in a wiki webpage. -import {logError, logWarn} from '#cli'; import * as html from '#html'; import {escapeRegex} from '#sugar'; diff --git a/src/util/wiki-data.js b/src/util/wiki-data.js index ad2f82fb..0eab2204 100644 --- a/src/util/wiki-data.js +++ b/src/util/wiki-data.js @@ -1,6 +1,6 @@ // Utility functions for interacting with wiki data. -import {accumulateSum, empty, stitchArrays, unique} from './sugar.js'; +import {accumulateSum, empty, unique} from './sugar.js'; // Generic value operations -- cgit 1.3.0-6-gf8a5 From c4f6c41a248ba9ef4f802cc03c20757d417540e4 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Sat, 9 Sep 2023 21:08:06 -0300 Subject: data: WIP cached composition nonsense --- src/util/wiki-data.js | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'src/util') diff --git a/src/util/wiki-data.js b/src/util/wiki-data.js index 0eab2204..ac652b27 100644 --- a/src/util/wiki-data.js +++ b/src/util/wiki-data.js @@ -874,3 +874,71 @@ export function filterItemsForCarousel(items) { .filter(item => item.artTags.every(tag => !tag.isContentWarning)) .slice(0, maxCarouselLayoutItems + 1); } + +// Ridiculous caching support nonsense + +export class TupleMap { + static maxNestedTupleLength = 25; + + #store = [undefined, null, null, null]; + + #lifetime(value) { + if (Array.isArray(value) && value.length <= TupleMap.maxNestedTupleLength) { + return 'tuple'; + } else if ( + typeof value === 'object' && value !== null || + typeof value === 'function' + ) { + return 'weak'; + } else { + return 'strong'; + } + } + + #getSubstoreShallow(value, store) { + const lifetime = this.#lifetime(value); + const mapIndex = {weak: 1, strong: 2, tuple: 3}[lifetime]; + + let map = store[mapIndex]; + if (map === null) { + map = store[mapIndex] = + (lifetime === 'weak' ? new WeakMap() + : lifetime === 'strong' ? new Map() + : lifetime === 'tuple' ? new TupleMap() + : null); + } + + if (map.has(value)) { + return map.get(value); + } else { + const substore = [undefined, null, null, null]; + map.set(value, substore); + return substore; + } + } + + #getSubstoreDeep(tuple, store = this.#store) { + if (tuple.length === 0) { + return store; + } else { + const [first, ...rest] = tuple; + return this.#getSubstoreDeep(rest, this.#getSubstoreShallow(first, store)); + } + } + + get(tuple) { + const store = this.#getSubstoreDeep(tuple); + return store[0]; + } + + has(tuple) { + const store = this.#getSubstoreDeep(tuple); + return store[0] !== undefined; + } + + set(tuple, value) { + const store = this.#getSubstoreDeep(tuple); + store[0] = value; + return value; + } +} -- cgit 1.3.0-6-gf8a5 From d878ab29f20c0727acafb4b1150d4e31d69c55c0 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Mon, 11 Sep 2023 10:09:48 -0300 Subject: data, html, infra: supporting changes for sanitizing content --- src/util/html.js | 57 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 16 deletions(-) (limited to 'src/util') diff --git a/src/util/html.js b/src/util/html.js index a311bbba..f0c7bfdf 100644 --- a/src/util/html.js +++ b/src/util/html.js @@ -806,24 +806,43 @@ export class Template { } // Null is always an acceptable slot value. - if (value !== null) { - if ('validate' in description) { - description.validate({ - ...commonValidators, - ...validators, - })(value); - } + if (value === null) { + return true; + } + + if ('validate' in description) { + description.validate({ + ...commonValidators, + ...validators, + })(value); + } - if ('type' in description) { - const {type} = description; - if (type === 'html') { - if (!isHTML(value)) { + if ('type' in description) { + switch (description.type) { + case 'html': { + if (!isHTML(value)) throw new TypeError(`Slot expects html (tag, template or blank), got ${typeof value}`); - } - } else { - if (typeof value !== type) { - throw new TypeError(`Slot expects ${type}, got ${typeof value}`); - } + + return true; + } + + case 'string': { + // Tags and templates are valid in string arguments - they'll be + // stringified when exposed to the description's .content() function. + if (isTag(value) || isTemplate(value)) + return true; + + if (typeof value !== 'string') + throw new TypeError(`Slot expects string, got ${typeof value}`); + + return true; + } + + default: { + if (typeof value !== description.type) + throw new TypeError(`Slot expects ${description.type}, got ${typeof value}`); + + return true; } } } @@ -847,6 +866,12 @@ export class Template { return providedValue; } + if (description.type === 'string') { + if (isTag(providedValue) || isTemplate(providedValue)) { + return providedValue.toString(); + } + } + if (providedValue !== null) { return providedValue; } -- cgit 1.3.0-6-gf8a5 From 8d674012710d673b773e13b0cf0be9abba6ccc00 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Sat, 23 Sep 2023 22:13:35 -0300 Subject: util: showAggregate: show error causes --- src/util/sugar.js | 49 +++++++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 18 deletions(-) (limited to 'src/util') diff --git a/src/util/sugar.js b/src/util/sugar.js index ebb7d61e..14fb250e 100644 --- a/src/util/sugar.js +++ b/src/util/sugar.js @@ -544,15 +544,17 @@ export function showAggregate(topError, { print = true, } = {}) { const recursive = (error, {level}) => { - let header = showTraces + let headerPart = showTraces ? `[${error.constructor.name || 'unnamed'}] ${ error.message || '(no message)' }` : error instanceof AggregateError ? `[${error.message || '(no message)'}]` : error.message || '(no message)'; + if (showTraces) { const stackLines = error.stack?.split('\n'); + const stackLine = stackLines?.find( (line) => line.trim().startsWith('at') && @@ -560,30 +562,41 @@ export function showAggregate(topError, { !line.includes('node:') && !line.includes('') ); + const tracePart = stackLine ? '- ' + stackLine .trim() .replace(/file:\/\/.*\.js/, (match) => pathToFileURL(match)) : '(no stack trace)'; - header += ` ${colors.dim(tracePart)}`; - } - const bar = level % 2 === 0 ? '\u2502' : colors.dim('\u254e'); - const head = level % 2 === 0 ? '\u257f' : colors.dim('\u257f'); - - if (error instanceof AggregateError) { - return ( - header + - '\n' + - error.errors - .map((error) => recursive(error, {level: level + 1})) - .flatMap((str) => str.split('\n')) - .map((line, i) => i === 0 ? ` ${head} ${line}` : ` ${bar} ${line}`) - .join('\n') - ); - } else { - return header; + + headerPart += ` ${colors.dim(tracePart)}`; } + + const head1 = level % 2 === 0 ? '\u21aa' : colors.dim('\u21aa'); + const bar1 = ' '; + + const causePart = + (error.cause + ? recursive(error.cause, {level: level + 1}) + .split('\n') + .map((line, i) => i === 0 ? ` ${head1} ${line}` : ` ${bar1} ${line}`) + .join('\n') + : ''); + + const head2 = level % 2 === 0 ? '\u257f' : colors.dim('\u257f'); + const bar2 = level % 2 === 0 ? '\u2502' : colors.dim('\u254e'); + + const aggregatePart = + (error instanceof AggregateError + ? error.errors + .map(error => recursive(error, {level: level + 1})) + .flatMap(str => str.split('\n')) + .map((line, i) => i === 0 ? ` ${head2} ${line}` : ` ${bar2} ${line}`) + .join('\n') + : ''); + + return [headerPart, causePart, aggregatePart].filter(Boolean).join('\n'); }; const message = -- cgit 1.3.0-6-gf8a5 From b5cfc2a793f22da60606a4dd7387fcf3d3163843 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Mon, 25 Sep 2023 14:23:23 -0300 Subject: data: misc. improvements for input validation & infrastructure --- src/util/sugar.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/util') diff --git a/src/util/sugar.js b/src/util/sugar.js index 14fb250e..24d409fb 100644 --- a/src/util/sugar.js +++ b/src/util/sugar.js @@ -599,12 +599,7 @@ export function showAggregate(topError, { return [headerPart, causePart, aggregatePart].filter(Boolean).join('\n'); }; - const message = - (topError instanceof AggregateError - ? recursive(topError, {level: 0}) - : (showTraces - ? topError.stack - : topError.toString())); + const message = recursive(topError, {level: 0}); if (print) { console.error(message); -- cgit 1.3.0-6-gf8a5 From 518647f8b80ffda6d502b1a75656da7f2ae4b9d3 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Thu, 28 Sep 2023 14:00:18 -0300 Subject: data: templateCompositeFrom: improve error message consistency --- src/util/sugar.js | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/util') diff --git a/src/util/sugar.js b/src/util/sugar.js index 24d409fb..ef6ab18c 100644 --- a/src/util/sugar.js +++ b/src/util/sugar.js @@ -230,6 +230,16 @@ export function escapeRegex(string) { return string.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); } +// Gets the "look" of some arbitrary value. It's like typeof, but smarter. +// Don't use this for actually validating types - it's only suitable for +// inclusion in error messages. +export function typeAppearance(value) { + if (value === null) return 'null'; + if (value === undefined) return 'undefined'; + if (Array.isArray(value)) return 'array'; + return typeof value; +} + // Binds default values for arguments in a {key: value} type function argument // (typically the second argument, but may be overridden by providing a // [bindOpts.bindIndex] argument). Typically useful for preparing a function for -- cgit 1.3.0-6-gf8a5 From 411c053dc4b314b2bc0d58d3899fd796ad0054c2 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Thu, 28 Sep 2023 14:11:02 -0300 Subject: data, util: use typeAppearance in more places --- src/util/html.js | 4 ++-- src/util/replacer.js | 4 ++-- src/util/sugar.js | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/util') diff --git a/src/util/html.js b/src/util/html.js index c7395fbf..282a52da 100644 --- a/src/util/html.js +++ b/src/util/html.js @@ -2,7 +2,7 @@ import {inspect} from 'node:util'; -import {empty} from '#sugar'; +import {empty, typeAppearance} from '#sugar'; import * as commonValidators from '#validators'; // COMPREHENSIVE! @@ -633,7 +633,7 @@ export class Template { static validateDescription(description) { if (typeof description !== 'object') { - throw new TypeError(`Expected object, got ${typeof description}`); + throw new TypeError(`Expected object, got ${typeAppearance(description)}`); } if (description === null) { diff --git a/src/util/replacer.js b/src/util/replacer.js index 647d1f0e..095ee060 100644 --- a/src/util/replacer.js +++ b/src/util/replacer.js @@ -6,7 +6,7 @@ // for embedding in a wiki webpage. import * as html from '#html'; -import {escapeRegex} from '#sugar'; +import {escapeRegex, typeAppearance} from '#sugar'; // Syntax literals. const tagBeginning = '[['; @@ -407,7 +407,7 @@ export function postprocessHeadings(inputNodes) { export function parseInput(input) { if (typeof input !== 'string') { - throw new TypeError(`Expected input to be string, got ${input}`); + throw new TypeError(`Expected input to be string, got ${typeAppearance(input)}`); } try { diff --git a/src/util/sugar.js b/src/util/sugar.js index ef6ab18c..29fcf848 100644 --- a/src/util/sugar.js +++ b/src/util/sugar.js @@ -82,7 +82,7 @@ export function stitchArrays(keyToArray) { for (const [key, value] of Object.entries(keyToArray)) { if (value === null) continue; if (Array.isArray(value)) continue; - errors.push(new TypeError(`(${key}) Expected array or null, got ${value}`)); + errors.push(new TypeError(`(${key}) Expected array or null, got ${typeAppearance(value)}`)); } if (!empty(errors)) { @@ -170,11 +170,11 @@ export function setIntersection(set1, set2) { export function filterProperties(object, properties) { if (typeof object !== 'object' || object === null) { - throw new TypeError(`Expected object to be an object, got ${object}`); + throw new TypeError(`Expected object to be an object, got ${typeAppearance(object)}`); } if (!Array.isArray(properties)) { - throw new TypeError(`Expected properties to be an array, got ${properties}`); + throw new TypeError(`Expected properties to be an array, got ${typeAppearance(properties)}`); } const filteredObject = {}; -- cgit 1.3.0-6-gf8a5 From 13b25a8d48d142b60d5c351aad4ad1bf80104320 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Sat, 30 Sep 2023 08:29:13 -0300 Subject: util, test: WIP decorate error with index symbol --- src/util/sugar.js | 1 + 1 file changed, 1 insertion(+) (limited to 'src/util') diff --git a/src/util/sugar.js b/src/util/sugar.js index 29fcf848..0522b59e 100644 --- a/src/util/sugar.js +++ b/src/util/sugar.js @@ -624,6 +624,7 @@ export function decorateErrorWithIndex(fn) { return fn(x, index, array); } catch (error) { error.message = `(${colors.yellow(`#${index + 1}`)}) ${error.message}`; + error[Symbol.for('hsmusic.sugar.index')] = 1; throw error; } }; -- cgit 1.3.0-6-gf8a5 From 6eaa070e5c036ba8cd45f79c16dc2732b40ea480 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Sat, 30 Sep 2023 09:14:29 -0300 Subject: data, util: hsmusic.sugar.index -> hsmusic.decorate.indexInSourceArray --- src/util/sugar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/util') diff --git a/src/util/sugar.js b/src/util/sugar.js index 0522b59e..2e724bae 100644 --- a/src/util/sugar.js +++ b/src/util/sugar.js @@ -624,7 +624,7 @@ export function decorateErrorWithIndex(fn) { return fn(x, index, array); } catch (error) { error.message = `(${colors.yellow(`#${index + 1}`)}) ${error.message}`; - error[Symbol.for('hsmusic.sugar.index')] = 1; + error[Symbol.for('hsmusic.decorate.indexInSourceArray')] = index; throw error; } }; -- cgit 1.3.0-6-gf8a5 From e842ce93e6405334b6ef475ec1db41e051cfd2b5 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Wed, 11 Oct 2023 14:49:43 -0300 Subject: data: use flash act directory for better determinism --- src/util/wiki-data.js | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'src/util') diff --git a/src/util/wiki-data.js b/src/util/wiki-data.js index ac652b27..0790ae91 100644 --- a/src/util/wiki-data.js +++ b/src/util/wiki-data.js @@ -610,20 +610,9 @@ export function sortFlashesChronologically(data, { latestFirst = false, getDate, } = {}) { - // Flash acts don't actually have any identifying properties because they - // don't have dedicated pages (yet), so don't have a directory. Make up a - // fake key identifying them so flashes can be grouped together. - const flashActs = new Set(data.map(flash => flash.act)); - const flashActIdentifiers = new Map(); - - let counter = 0; - for (const act of flashActs) { - flashActIdentifiers.set(act, ++counter); - } - // Group flashes by act... - data.sort((a, b) => { - return flashActIdentifiers.get(a.act) - flashActIdentifiers.get(b.act); + sortByDirectory(data, { + getDirectory: flash => flash.act.directory, }); // Sort flashes by position in act... -- cgit 1.3.0-6-gf8a5 From ea1b8196ba240d2cc4c64a9079947028cb536bf8 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Wed, 18 Oct 2023 14:53:38 -0300 Subject: sugar: filterProperties: preserve original order if specified --- src/util/sugar.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'src/util') diff --git a/src/util/sugar.js b/src/util/sugar.js index 2e724bae..3e39e98f 100644 --- a/src/util/sugar.js +++ b/src/util/sugar.js @@ -168,7 +168,9 @@ export function setIntersection(set1, set2) { return intersection; } -export function filterProperties(object, properties) { +export function filterProperties(object, properties, { + preserveOriginalOrder = false, +} = {}) { if (typeof object !== 'object' || object === null) { throw new TypeError(`Expected object to be an object, got ${typeAppearance(object)}`); } @@ -179,9 +181,17 @@ export function filterProperties(object, properties) { const filteredObject = {}; - for (const property of properties) { - if (Object.hasOwn(object, property)) { - filteredObject[property] = object[property]; + if (preserveOriginalOrder) { + for (const property of Object.keys(object)) { + if (properties.includes(property)) { + filteredObject[property] = object[property]; + } + } + } else { + for (const property of properties) { + if (Object.hasOwn(object, property)) { + filteredObject[property] = object[property]; + } } } -- cgit 1.3.0-6-gf8a5