From 58d8a5b532785c4302fa3131691d18622243ee61 Mon Sep 17 00:00:00 2001 From: fkakatie Date: Fri, 10 Jul 2026 13:42:49 -0600 Subject: [PATCH 1/2] docs: update jsdoc for loadCopy to account for widgets --- scripts/scripts.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/scripts.js b/scripts/scripts.js index 1559628..163f8ba 100644 --- a/scripts/scripts.js +++ b/scripts/scripts.js @@ -121,8 +121,8 @@ export function getLocale() { } /** - * Fetches localized UI strings from a block's companion JSON file. - * @param {string} scriptUrl - The block module's `import.meta.url` + * Fetches localized UI strings from a folders's companion JSON file. + * @param {string} scriptUrl - The module's `import.meta.url` * @returns {Promise} */ export async function loadCopy(scriptUrl) { From cc7ab012b202ca39cfd98bfc8241b225f056f425 Mon Sep 17 00:00:00 2001 From: fkakatie Date: Fri, 10 Jul 2026 13:43:33 -0600 Subject: [PATCH 2/2] feat: import loadCopy instead of rewriting across the project --- blocks/carousel/carousel.js | 18 ++------------ widgets/plp/plp.js | 18 ++------------ widgets/press-releases/press-releases.js | 28 ++++------------------ widgets/press-releases/press-releases.json | 1 - widgets/search/search.js | 28 +++------------------- 5 files changed, 11 insertions(+), 82 deletions(-) diff --git a/blocks/carousel/carousel.js b/blocks/carousel/carousel.js index 1ebb7b6..bf634fa 100644 --- a/blocks/carousel/carousel.js +++ b/blocks/carousel/carousel.js @@ -1,5 +1,5 @@ // eslint-disable-next-line import/no-cycle -import { buildVideoAutoBlocks, getLocale } from '../../scripts/scripts.js'; +import { buildVideoAutoBlocks, loadCopy } from '../../scripts/scripts.js'; import { decorateBlock, loadBlock } from '../../scripts/aem.js'; const CAROUSEL_VARIANTS = ['slides', 'promo']; @@ -11,20 +11,6 @@ function resolveVariant(block) { return 'promo'; } -async function loadCopy(lang) { - const scriptPath = new URL(import.meta.url).pathname; - const jsonPath = scriptPath.replace(/\.js$/, '.json'); - const url = `${window.hlx?.codeBasePath || ''}${jsonPath}`; - try { - const resp = await fetch(url); - if (!resp.ok) return {}; - const data = await resp.json(); - return data[lang] || data.en || {}; - } catch { - return {}; - } -} - function updateNavigation(block, slideIndex) { const slides = block.querySelectorAll('.carousel-slide'); const prev = block.querySelector('.slide-prev'); @@ -318,7 +304,7 @@ export default async function decorate(block) { const isSingleSlide = rows.length < 2; const isSlides = variant === 'slides'; - const copy = await loadCopy(getLocale()); + const copy = await loadCopy(import.meta.url); block.dataset.slideOf = copy.of || 'of'; block.setAttribute('role', 'region'); diff --git a/widgets/plp/plp.js b/widgets/plp/plp.js index 32c999a..edf29f3 100644 --- a/widgets/plp/plp.js +++ b/widgets/plp/plp.js @@ -1,7 +1,7 @@ import { createOptimizedPicture, decorateBlock, loadBlock, } from '../../scripts/aem.js'; -import { normalizeIndexImageUrl, getLocale } from '../../scripts/scripts.js'; +import { normalizeIndexImageUrl, getLocale, loadCopy } from '../../scripts/scripts.js'; const FACETS = [ { key: 'region', copyKey: 'region' }, @@ -12,20 +12,6 @@ const FACETS = [ { key: 'traction-system', copyKey: 'tractionSystem' }, ]; -async function loadWidgetCopy(lang) { - const scriptPath = new URL(import.meta.url).pathname; - const jsonPath = scriptPath.replace(/\.js$/, '.json'); - const url = `${window.hlx?.codeBasePath || ''}${jsonPath}`; - try { - const resp = await fetch(url); - if (!resp.ok) return {}; - const data = await resp.json(); - return data[lang] || data.en || {}; - } catch { - return {}; - } -} - function isDirectChild(itemPath, parentPath) { const normalized = parentPath.endsWith('/') ? parentPath.slice(0, -1) : parentPath; if (!itemPath.startsWith(`${normalized}/`)) return false; @@ -151,7 +137,7 @@ async function renderCards(container, items) { export default async function decorate(widget) { const lang = getLocale(); - const [allItems, copy] = await Promise.all([loadIndex(lang), loadWidgetCopy(lang)]); + const [allItems, copy] = await Promise.all([loadIndex(lang), loadCopy(import.meta.url)]); const parentPath = window.location.pathname; const children = allItems .filter((item) => isDirectChild(item.path || '', parentPath)) diff --git a/widgets/press-releases/press-releases.js b/widgets/press-releases/press-releases.js index 57774c9..7feeec3 100644 --- a/widgets/press-releases/press-releases.js +++ b/widgets/press-releases/press-releases.js @@ -1,25 +1,6 @@ -import { getLocale } from '../../scripts/scripts.js'; +import { getLocale, loadCopy } from '../../scripts/scripts.js'; -/** - * Load widget config from the widget's local JSON (same name as the script). - * @param {string} lang - Language key (e.g. en) - * @returns {Promise<{ copy: Object, defaultPageSize: number }>} - */ -async function loadWidgetConfig(lang) { - const scriptPath = new URL(import.meta.url).pathname; - const jsonPath = scriptPath.replace(/\.js$/, '.json'); - const url = `${window.hlx?.codeBasePath || ''}${jsonPath}`; - try { - const resp = await fetch(url); - if (!resp.ok) return { copy: {}, defaultPageSize: 12 }; - const data = await resp.json(); - const key = data[lang] ? lang : 'en'; - const defaultPageSize = parseInt(data.defaultPageSize, 10) || 12; - return { copy: data[key] || {}, defaultPageSize }; - } catch (_) { - return { copy: {}, defaultPageSize: 12 }; - } -} +const DEFAULT_PAGE_SIZE = 12; /** * Normalize a press release row from the query index. @@ -225,11 +206,10 @@ export default async function decorate(widget) { if (widget.dataset.pressReleasesInitialized === 'true') return; widget.dataset.pressReleasesInitialized = 'true'; - const lang = getLocale(); - const { copy, defaultPageSize } = await loadWidgetConfig(lang); + const copy = await loadCopy(import.meta.url); hydrateCopy(widget, copy); - const pageSize = parseInt(widget.dataset.pageSize, 10) || defaultPageSize; + const pageSize = parseInt(widget.dataset.pageSize, 10) || DEFAULT_PAGE_SIZE; buildPressReleasesListing(widget, copy, pageSize); } diff --git a/widgets/press-releases/press-releases.json b/widgets/press-releases/press-releases.json index af13228..dffb66b 100644 --- a/widgets/press-releases/press-releases.json +++ b/widgets/press-releases/press-releases.json @@ -1,5 +1,4 @@ { - "defaultPageSize": 12, "en": { "learnMore": "Learn More >", "loadMore": "Load More", diff --git a/widgets/search/search.js b/widgets/search/search.js index 75eb2ec..bf69538 100644 --- a/widgets/search/search.js +++ b/widgets/search/search.js @@ -1,25 +1,5 @@ import { createOptimizedPicture, loadCSS } from '../../scripts/aem.js'; -import { normalizeIndexImageUrl, getLocale } from '../../scripts/scripts.js'; - -/** - * Load widget copy from the widget's local JSON (same name as the script). - * @param {string} lang - Language key (e.g. en) - * @returns {Promise} Copy for that language (flat key-value) - */ -async function loadWidgetCopy(lang) { - const scriptPath = new URL(import.meta.url).pathname; - const jsonPath = scriptPath.replace(/\.js$/, '.json'); - const url = `${window.hlx?.codeBasePath || ''}${jsonPath}`; - try { - const resp = await fetch(url); - if (!resp.ok) return {}; - const data = await resp.json(); - const key = data[lang] ? lang : 'en'; - return data[key] || {}; - } catch (_) { - return {}; - } -} +import { normalizeIndexImageUrl, getLocale, loadCopy } from '../../scripts/scripts.js'; /** * Normalize a single item from the query index. @@ -687,8 +667,7 @@ export async function attachSearchSuggestions(input, opts = {}) { await loadCSS(`${window.hlx?.codeBasePath || ''}/widgets/search/suggestions.css`); - const lang = (document.documentElement.lang || 'en').split('-')[0]; - const copy = await loadWidgetCopy(lang); + const copy = await loadCopy(import.meta.url); const overlay = document.createElement('div'); overlay.id = 'search-suggestions'; @@ -851,8 +830,7 @@ export async function initHeaderSearch(input, opts = {}) { * @param {HTMLElement} widget - Widget container element */ export default async function decorate(widget) { - const lang = (document.documentElement.lang || 'en').split('-')[0]; - const copy = await loadWidgetCopy(lang); + const copy = await loadCopy(import.meta.url); hydrateCopy(widget, copy); searchResultsContainer = widget;