From 70d499ccb81cb704621c55d2a4f499a2a5d36623 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 20:08:42 +0000 Subject: [PATCH] perf: optimize getMovieCreators with O(1) dictionary lookups Pre-computed a module-level dictionary mapping for localized creator labels instead of running nested O(N*M) loop comparisons inside the `getMovieCreators` helper function. This eliminates needless allocations and improves execution performance. Co-authored-by: bartholomej <5861310+bartholomej@users.noreply.github.com> --- src/helpers/movie.helper.ts | 69 ++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/src/helpers/movie.helper.ts b/src/helpers/movie.helper.ts index 1cc2f8da..7547d56b 100644 --- a/src/helpers/movie.helper.ts +++ b/src/helpers/movie.helper.ts @@ -302,6 +302,38 @@ const parseMoviePeople = (el: HTMLElement): CSFDMovieCreator[] => { // } // }; +const CREATOR_KEYS = [ + 'directors', + 'writers', + 'cinematography', + 'music', + 'actors', + 'basedOn', + 'producers', + 'filmEditing', + 'costumeDesign', + 'productionDesign', + 'sound' +] as const; + +type CreatorKey = typeof CREATOR_KEYS[number]; + +// Precompute language maps to avoid O(N*M) lookups inside getMovieCreators +const LOCALIZED_CREATOR_LABELS: Record> = { + cs: {}, + en: {}, + sk: {} +}; + +for (const lang of ['cs', 'en', 'sk']) { + for (const key of CREATOR_KEYS) { + const label = getLocalizedCreatorLabel(lang, key) as string; + // Remove colons and trim for reliable O(1) matching against HTML text + const normalizedLabel = label.replace(/:/g, '').trim(); + LOCALIZED_CREATOR_LABELS[lang][normalizedLabel] = key; + } +} + export const getMovieCreators = (el: HTMLElement, options?: CSFDOptions): CSFDCreators => { const creators: CSFDCreators = { directors: [], @@ -318,35 +350,18 @@ export const getMovieCreators = (el: HTMLElement, options?: CSFDOptions): CSFDCr }; const groups = el.querySelectorAll('.creators h4'); - - const keys = [ - 'directors', - 'writers', - 'cinematography', - 'music', - 'actors', - 'basedOn', - 'producers', - 'filmEditing', - 'costumeDesign', - 'productionDesign', - 'sound' - ] as const; - - const localizedLabels = keys.map((key) => ({ - key, - label: getLocalizedCreatorLabel(options?.language, key) as string - })); + const lang = options?.language || 'cs'; + const labelMap = LOCALIZED_CREATOR_LABELS[lang] || LOCALIZED_CREATOR_LABELS['cs']; for (const group of groups) { - const text = group.textContent.trim(); - for (const { key, label } of localizedLabels) { - if (text.includes(label)) { - if (group.parentNode) { - creators[key] = parseMoviePeople(group.parentNode as HTMLElement); - } - break; - } + // ⚡ Bolt Performance Optimization: + // O(1) property lookup replaces previous nested loops. + // Removes the trailing colon from HTML text (e.g., 'Režie:' -> 'Režie') for exact matching. + const text = group.textContent.replace(/:/g, '').trim(); + const key = labelMap[text]; + + if (key && group.parentNode) { + creators[key] = parseMoviePeople(group.parentNode as HTMLElement); } }