From 6e05a00ef8b168c8adf2d2644c3bd5672b421477 Mon Sep 17 00:00:00 2001 From: rusmeenkhan1 Date: Wed, 13 May 2026 15:02:06 +0530 Subject: [PATCH 1/2] moved decorateButtons to scripts.js --- blocks/hero-heritage-cc/hero-heritage-cc.js | 4 +- blocks/modal/modal.js | 3 +- scripts/aem.js | 67 ------------------ scripts/editor-support.js | 2 +- scripts/scripts.js | 76 ++++++++++++++++++++- 5 files changed, 78 insertions(+), 74 deletions(-) diff --git a/blocks/hero-heritage-cc/hero-heritage-cc.js b/blocks/hero-heritage-cc/hero-heritage-cc.js index 054e0b1..3643bf8 100644 --- a/blocks/hero-heritage-cc/hero-heritage-cc.js +++ b/blocks/hero-heritage-cc/hero-heritage-cc.js @@ -1,5 +1,5 @@ -import { decorateButtons, pickPicturePreloadUrl } from '../../scripts/aem.js'; -import { loadFragment } from '../../scripts/scripts.js'; +import { pickPicturePreloadUrl } from '../../scripts/aem.js'; +import { decorateButtons, loadFragment } from '../../scripts/scripts.js'; /* eslint-disable secure-coding/no-hardcoded-credentials -- CSS classes/style props only */ diff --git a/blocks/modal/modal.js b/blocks/modal/modal.js index 77310ea..dfdb9f2 100644 --- a/blocks/modal/modal.js +++ b/blocks/modal/modal.js @@ -1,7 +1,7 @@ import { buildBlock, decorateBlock, loadBlock, loadCSS, } from '../../scripts/aem.js'; -import { loadFragment, DOMPURIFY } from '../../scripts/scripts.js'; +import { loadFragment, DOMPURIFY, decorateButtons } from '../../scripts/scripts.js'; /* This is not a traditional block, so there is no decorate function. @@ -417,6 +417,7 @@ export async function createModal(contentNodes, options = {}) { const block = buildBlock('modal', ''); document.querySelector('main').append(block); decorateBlock(block); + decorateButtons(block); await loadBlock(block); // close on click outside the dialog diff --git a/scripts/aem.js b/scripts/aem.js index 71deade..8060710 100644 --- a/scripts/aem.js +++ b/scripts/aem.js @@ -462,70 +462,6 @@ function wrapTextNodes(block) { }); } -/** - * Decorates paragraphs containing a single link as buttons. - * @param {Element} element container element - */ -function decorateButtons(element) { - element.querySelectorAll('a').forEach((a) => { - a.title = a.title || a.textContent; - const shouldSkip = a.href === a.textContent && a.textContent.trim().length > 0 - && !a.closest('.button-container') && !a.classList.contains('button'); - if (!shouldSkip) { - const up = a.parentElement; - const twoup = a.parentElement.parentElement; - const threeup = a.parentElement.parentElement.parentElement; - const child = a.querySelector(':scope > *:first-child'); - if (!a.querySelector('img')) { - if (up.childNodes.length === 1 && (up.tagName === 'P' || up.tagName === 'DIV')) { - a.className = 'button'; // default - up.classList.add('button-container'); - } - if ( - up.childNodes.length === 1 - && up.tagName === 'STRONG' - && twoup.childNodes.length === 1 - && twoup.tagName === 'P' - ) { - a.className = 'button primary'; - twoup.classList.add('button-container'); - } - if ( - up.childNodes.length === 1 - && up.tagName === 'EM' - && twoup.childNodes.length === 1 - && twoup.tagName === 'P' - ) { - a.className = 'button secondary'; - twoup.classList.add('button-container'); - } - if ( - up.childNodes.length === 1 - && up.tagName === 'STRONG' - && twoup.childNodes.length === 1 - && (twoup.tagName === 'EM' || child?.tagName === 'EM') - && threeup.childNodes.length === 1 - && threeup.tagName === 'P' - ) { - a.className = 'button tertiary'; - threeup.classList.add('button-container'); - } - if ( - up.childNodes.length === 1 - && up.tagName === 'EM' - && twoup.childNodes.length === 1 - && twoup.tagName === 'STRONG' - && threeup.childNodes.length === 1 - && threeup.tagName === 'P' - ) { - a.className = 'button tertiary'; - threeup.classList.add('button-container'); - } - } - } - }); -} - /** * Add for icon, prefixed with codeBasePath and optional prefix. * @param {Element} [span] span element with icon classes @@ -705,8 +641,6 @@ function decorateBlock(block) { blockWrapper.classList.add(`${shortBlockName}-wrapper`); const section = block.closest('.section'); if (section) section.classList.add(`${shortBlockName}-container`); - // eslint-disable-next-line no-use-before-define - decorateButtons(block); } } @@ -812,7 +746,6 @@ export { createOptimizedPicture, decorateBlock, decorateBlocks, - decorateButtons, decorateIcons, decorateTemplateAndTheme, fetchPlaceholders, diff --git a/scripts/editor-support.js b/scripts/editor-support.js index 26962e1..60645f7 100644 --- a/scripts/editor-support.js +++ b/scripts/editor-support.js @@ -1,7 +1,6 @@ import { decorateBlock, decorateBlocks, - decorateButtons, decorateIcons, loadBlock, loadSections, @@ -13,6 +12,7 @@ import { decorateRichtext } from './editor-support-rte.js'; import { decorateSections, decorateMain, + decorateButtons, loadFragment, moveAllAttributes, } from './scripts.js'; diff --git a/scripts/scripts.js b/scripts/scripts.js index 84c5a11..7727061 100644 --- a/scripts/scripts.js +++ b/scripts/scripts.js @@ -3,7 +3,6 @@ import { loadFooter, buildBlock, decorateBlock, - decorateButtons, decorateIcons, decorateBlocks, decorateTemplateAndTheme, @@ -22,6 +21,70 @@ import { export { DOMPURIFY }; +/** + * Decorates paragraphs containing a single link as buttons. + * @param {Element} element container element + */ +export function decorateButtons(element) { + element.querySelectorAll('a').forEach((a) => { + a.title = a.title || a.textContent; + const shouldSkip = a.href === a.textContent && a.textContent.trim().length > 0 + && !a.closest('.button-container') && !a.classList.contains('button'); + if (!shouldSkip) { + const up = a.parentElement; + const twoup = a.parentElement.parentElement; + const threeup = a.parentElement.parentElement.parentElement; + const child = a.querySelector(':scope > *:first-child'); + if (!a.querySelector('img')) { + if (up.childNodes.length === 1 && (up.tagName === 'P' || up.tagName === 'DIV')) { + a.className = 'button'; // default + up.classList.add('button-container'); + } + if ( + up.childNodes.length === 1 + && up.tagName === 'STRONG' + && twoup.childNodes.length === 1 + && twoup.tagName === 'P' + ) { + a.className = 'button primary'; + twoup.classList.add('button-container'); + } + if ( + up.childNodes.length === 1 + && up.tagName === 'EM' + && twoup.childNodes.length === 1 + && twoup.tagName === 'P' + ) { + a.className = 'button secondary'; + twoup.classList.add('button-container'); + } + if ( + up.childNodes.length === 1 + && up.tagName === 'STRONG' + && twoup.childNodes.length === 1 + && (twoup.tagName === 'EM' || child?.tagName === 'EM') + && threeup.childNodes.length === 1 + && threeup.tagName === 'P' + ) { + a.className = 'button tertiary'; + threeup.classList.add('button-container'); + } + if ( + up.childNodes.length === 1 + && up.tagName === 'EM' + && twoup.childNodes.length === 1 + && twoup.tagName === 'STRONG' + && threeup.childNodes.length === 1 + && threeup.tagName === 'P' + ) { + a.className = 'button tertiary'; + threeup.classList.add('button-container'); + } + } + } + }); +} + // Max collection size before iteration to prevent DoS from excessive loops (CWE-400) const MAX_ITERATION_LIMIT = 500; @@ -473,6 +536,7 @@ export function buildEmbedBlocks(main) { const embedBlock = buildBlock('embed', a.cloneNode(true)); a.replaceWith(embedBlock); decorateBlock(embedBlock); + decorateButtons(embedBlock); } }); } @@ -1025,6 +1089,7 @@ export function buildMultiSection(main) { appendMultiSectionBlock(section, items, blockClass, true); // Decorate blocks inside nested sections so they get .block and are loaded by loadSection decorateBlocks(section); + section.querySelectorAll('div.block').forEach((block) => decorateButtons(block)); }); } @@ -1073,6 +1138,7 @@ export function decorateMain(main) { buildAutoBlocks(main); initEntranceAnimationObserver(main); decorateBlocks(main); + main.querySelectorAll('div.block').forEach((block) => decorateButtons(block)); decorateButtonGroups(main); buildEmbedBlocks(main); decorateLinkedPictures(main); @@ -1764,7 +1830,9 @@ async function loadLazy(doc) { const main = doc.querySelector('main'); // Load header first so nav-wrapper is available for category navbar - await loadHeader(doc.querySelector('header')); + const headerEl = doc.querySelector('header'); + await loadHeader(headerEl); + if (headerEl) decorateButtons(headerEl); // Load get app banner fragment and append to header await loadGetAppBannerFragment(); @@ -1788,7 +1856,9 @@ async function loadLazy(doc) { const element = hash ? doc.getElementById(hash.substring(1)) : false; if (hash && element) element.scrollIntoView(); - loadFooter(doc.querySelector('footer')); + const footerEl = doc.querySelector('footer'); + loadFooter(footerEl); + if (footerEl) decorateButtons(footerEl); // Rewrite relative links to prod origin (avoid ww2 links) doc.querySelectorAll('a[href]').forEach((a) => { From cac95ed43f805df7c3f389beb6a5920e53f38530 Mon Sep 17 00:00:00 2001 From: rusmeenkhan1 Date: Fri, 15 May 2026 12:51:05 +0530 Subject: [PATCH 2/2] fixed linting issue --- scripts/scripts.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/scripts.js b/scripts/scripts.js index 7727061..a1ebe38 100644 --- a/scripts/scripts.js +++ b/scripts/scripts.js @@ -25,6 +25,8 @@ export { DOMPURIFY }; * Decorates paragraphs containing a single link as buttons. * @param {Element} element container element */ + +/* eslint-disable sonarjs/cognitive-complexity */ export function decorateButtons(element) { element.querySelectorAll('a').forEach((a) => { a.title = a.title || a.textContent;