Repository: AdobeDocs/adp-devsite
Pull request #127: Next / Prev 
Author: login: BaskarMitrah
Created: 2025-03-26T09:45:48Z | Merged: 2025-03-26T15:56:44Z

Issues : https://jira.corp.adobe.com/browse/DEVSITE-1613

Previous : https://stage--adp-devsite--adobedocs.aem.page/express/add-ons/docs/guides/getting-started/
Test URL : https://baskar-redirect--adp-devsite--adobedocs.aem.page/express/add-ons/docs/guides/getting-started/


Diff:
diff --git a/hlx_statics/blocks/next-prev/next-prev.js b/hlx_statics/blocks/next-prev/next-prev.js
index 9deed606a..c55b0beff 100644
--- a/hlx_statics/blocks/next-prev/next-prev.js
+++ b/hlx_statics/blocks/next-prev/next-prev.js
@@ -11,7 +11,7 @@ export default async function decorate(block) {
   block.innerHTML = '';
   const extractMenuData = (element) => [...element]
     .flatMap(links => [...links.querySelectorAll('li a')])
-    .map(link => ({ title: link.getAttribute('title'), href: link.getAttribute('href') }))
+    .map(link => ({ title: link.getAttribute('title'), href: link.getAttribute('href') , dhref : link.getAttribute('dhref') }))
     .filter((value, index, array) => array.findIndex(t => t.href === value.href) === index);
 
   const sideNavContainer = document.querySelector('.side-nav-subpages-section');
@@ -21,7 +21,7 @@ export default async function decorate(block) {
     const menuData = extractMenuData(sideNavContainer.querySelectorAll('ul'));
     const currentPath = window?.location?.pathname;
 
-    const currentIndex = menuData.findIndex(menu => menu.href === currentPath);
+    const currentIndex = menuData.findIndex(menu => menu.href === currentPath || menu.dhref === currentPath);
     const pages = [menuData[currentIndex - 1], menuData[currentIndex + 1]];
 
     const createIconSvg = (direction) => {
diff --git a/hlx_statics/blocks/side-nav/side-nav.js b/hlx_statics/blocks/side-nav/side-nav.js
index d5dcc136c..2f0b5b97b 100644
--- a/hlx_statics/blocks/side-nav/side-nav.js
+++ b/hlx_statics/blocks/side-nav/side-nav.js
@@ -309,8 +309,9 @@ export default async function decorate(block) {
           }
 
           updateIcon(getAnchorTag, !isExpanded, Boolean(childUl));
+          console.log('getAnchorTag.href', getAnchorTag.href)
 
-          if (window.location.href === getAnchorTag.href) {
+          if (window.location.href === getAnchorTag.href || window.location.pathname ===  getAnchorTag.getAttribute('dhref')) {
             getAnchorTag.setAttribute("aria-current", "page");
             if (li.classList.contains("header") && li.classList.contains("is-expanded")) {
               // if the header is expanded, make sure it's not selected if there is already a child selected.
@@ -326,7 +327,7 @@ export default async function decorate(block) {
           }
         };
 
-        if (window.location.href === getAnchorTag.href) {
+        if (window.location.href === getAnchorTag.href || window.location.pathname ===  getAnchorTag.getAttribute('dhref') ) {
           li.setAttribute("aria-expanded", true);
           getAnchorTag.setAttribute("aria-current", "page");
           const header = li.closest(".header");
diff --git a/hlx_statics/scripts/lib-helix.js b/hlx_statics/scripts/lib-helix.js
index 57cb0b035..6617d9a63 100644
--- a/hlx_statics/scripts/lib-helix.js
+++ b/hlx_statics/scripts/lib-helix.js
@@ -123,6 +123,27 @@ export async function fetchSideNavHtml() {
   return fetchNavHtml('subPages:');
 }
 
+/**
+ * Retrieves the side nav from the config.
+ * @returns {string} The side nav HTML
+ */
+export async function fetchRedirectJson() {
+  let pathPrefix = getMetadata('pathprefix').replace(/^\/|\/$/g, '');
+  let redirectFile = `${window.location.origin}/${pathPrefix}/redirects.json`;
+  const redirectHTML = await fetch(redirectFile)
+    .then(response => {
+      if (!response.ok) {
+        throw new Error('Network response was not ok');
+      }
+      return response.json();
+    })
+    .then(data => data)
+    .catch(error => {
+      console.error('There was a problem with the fetch operation:', error);
+    });
+  return redirectHTML;
+}
+
 /**
  * Retrieves the nav with the specified name from the config.
  * @param {string} name The nav name
@@ -133,21 +154,30 @@ async function fetchNavHtml(name) {
   let navPath = `${window.location.origin}/${pathPrefix}/config`;
   const fragment = await loadFragment(navPath);
 
+  const redirectHTML = await fetchRedirectJson();
+
   let navItems;
   fragment.querySelectorAll("p").forEach((item) => {
-    if(item.innerText === name) {
+    if (item.innerText === name) {
       navItems = item.parentElement.querySelector('ul');
       // relace annoying p tags
       const navItemsChild = navItems.querySelectorAll('li');
       navItemsChild.forEach((liItems) => {
         let p = liItems.querySelector('p');
-        if(p) {
+        if (p) {
           p.replaceWith(p.firstChild);
         }
         let a = liItems.querySelector(':scope > a');
         if (a) {
           a = normalizePaths(a, pathPrefix);
         }
+        if (redirectHTML.data.length > 0) {
+          redirectHTML.data.forEach((redirect) => {
+            if (a.getAttribute('href') == redirect.Source) {
+              a.setAttribute('dhref', redirect.Destination);
+            }
+          });
+        }
         // if (!a.getAttribute('href').startsWith(pathPrefix)) {
         //   if (a.getAttribute('href').endsWith('index.md')) {
         //     a.href = `/${pathPrefix}/${a.getAttribute('href').replaceAll('index.md', '')}`
@@ -187,7 +217,7 @@ function normalizePaths(anchorElem, pathPrefix) {
   return anchorElem;
 }
 
-function cleanMarkdownExtension (pathName) {
+function cleanMarkdownExtension(pathName) {
   return pathName
     .replace('/src/pages/', '/')
     .replace('/index.md/', '')
@@ -197,8 +227,8 @@ function cleanMarkdownExtension (pathName) {
     .replace('.md', '');
 };
 
-function trailingSlashFix (pathName)  {
-  if (!pathName.endsWith('/')){
+function trailingSlashFix(pathName) {
+  if (!pathName.endsWith('/')) {
     return `${pathName}/`;
   }
   return pathName;
@@ -413,7 +443,7 @@ export function decorateSections(main) {
             }
           });
         } else {
-            section.dataset[toCamelCase(key)] = meta[key];
+          section.dataset[toCamelCase(key)] = meta[key];
         }
       });
       sectionMeta.parentNode.remove();


Reviews:
user: login: melissag-ensemble
body: Baskar described the issue on slack:

Actually, the issue is not with redirection but with the Next/Prev functionality.
For example, on this page:
https://stage--adp-devsite--adobedocs.aem.page/express/add-ons/docs/references/addonsdk/addonsdk-app
At the bottom, we see the Next and Prev links:
Next → Add-on UI SDK
Prev → currentUser
Currently, the Prev link shows overview, but what we actually need is:
Next → devflags
Prev → app
I identified this issue and fixed it accordingly.
For your reference:
https://developer.adobe.com/express/add-ons/docs/references/addonsdk/app-currentUser/
Stage:
https://stage--adp-devsite--adobedocs.aem.page/express/add-ons/docs/references/addonsdk/app-current-user
Updated :
https://baskar-redirect--adp-devsite--adobedocs.aem.page/express/add-ons/docs/references/addonsdk/app-current-user
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-26T15:40:23Z
user: login: melissag-ensemble
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-26T15:53:33Z
user: login: melissag-ensemble
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-26T15:56:30Z

Review comments:
diff_hunk: @@ -309,8 +309,9 @@ export default async function decorate(block) {
           }
 
           updateIcon(getAnchorTag, !isExpanded, Boolean(childUl));
+          console.log('getAnchorTag.href', getAnchorTag.href)
path: hlx_statics/blocks/side-nav/side-nav.js
user: login: melissag-ensemble
body: please remove
created_at: 2025-03-26T15:53:33Z
author_association: COLLABORATOR

PR comments:
user: login: aem-code-sync[bot]
created_at: 2025-03-26T09:45:51Z
body: <!-- aem-bot-dash -->
Hello, I'm the AEM Code Sync Bot and I will run some actions to deploy your branch and validate page speed.
In case there are problems, just click a checkbox below to rerun the respective action.

- [ ] <!-- action-psi --> Re-run PSI checks
- [ ] <!-- action-sync --> Re-sync branch

<details>
<summary>Commits</summary>
<!-- commit-history -->

* [d14161a](https://github.com/AdobeDocs/adp-devsite/commit/d14161aa109a3ddc21d37f3059941b50731b1f2c) :white_check_mark: (latest)
* [106cdc0](https://github.com/AdobeDocs/adp-devsite/commit/106cdc063bfba98b177645ed1bc6220949d09092) :white_check_mark:
* [085934a](https://github.com/AdobeDocs/adp-devsite/commit/085934a3478c6d1e5780dd87ad9ab43419417d1a) :white_check_mark:
* [a7be16c](https://github.com/AdobeDocs/adp-devsite/commit/a7be16cf7e9a2b19bc6fe132063d64dde61c1aae) :white_check_mark:
* [886ffe7](https://github.com/AdobeDocs/adp-devsite/commit/886ffe7f2ee064fbc37b6b4674928483febb9606) :white_check_mark:
* [eb6d84e](https://github.com/AdobeDocs/adp-devsite/commit/eb6d84e4e421caa538375b494d51b7c88bdd0459) :white_check_mark:
* [71f7307](https://github.com/AdobeDocs/adp-devsite/commit/71f7307c0c2e3ed8b8ddaebeb40691cad91d264b) :white_check_mark:
* [b4de3e5](https://github.com/AdobeDocs/adp-devsite/commit/b4de3e5303ee17a10bb6ed2795444c420c77dd56) :white_check_mark:
* [11f49da](https://github.com/AdobeDocs/adp-devsite/commit/11f49da31427b0f3958d5fa01db0027321a6eacc) :white_check_mark:
* [4822e05](https://github.com/AdobeDocs/adp-devsite/commit/4822e05dc12621fd88f65de710005f1b318887c2) :white_check_mark:
* [c0d7273](https://github.com/AdobeDocs/adp-devsite/commit/c0d727326578dc87e60e8e4801476249187402d8) :white_check_mark:
* [599d258](https://github.com/AdobeDocs/adp-devsite/commit/599d25890940899e1bc0cc61340d5bd9b7a21116) :white_check_mark:

<!-- commit-history-end -->
</details>
author_association: NONE
user: login: aem-code-sync[bot]
created_at: 2025-03-26T09:46:13Z
body: <!-- aem-bot-psi -->
| | Page | Scores | Audits | Google |
|-|------|--------|--------|--------|
| :iphone: | [/express/add-ons/docs/guides/getting-started/](https://baskar-redirect--adp-devsite--adobedocs.aem.page/express/add-ons/docs/guides/getting-started/) | [![PERFORMANCE](https://img.shields.io/badge/PERFORMANCE-73-orange?style=for-the-badge "Performance")](https://googlechrome.github.io/lighthouse/scorecalc/#device=mobile&version=12.4.0&SI=5060.532643547445&FCP=3084.8454528868515&LCP=4813.89230488544&TBT=61.60069955586914&CLS=0.03800238363462124 "See Calculator") ![A11Y](https://img.shields.io/badge/A11Y-85-orange?style=for-the-badge "Accessibility") ![SEO](https://img.shields.io/badge/SEO-61-orange?style=for-the-badge "SEO") ![BEST PRACTICES](https://img.shields.io/badge/BEST%20PRACTICES-96-green?style=for-the-badge "Best Practices") | ![SI](https://img.shields.io/badge/SI-5.1s-orange?style=for-the-badge "Speed Index") ![FCP](https://img.shields.io/badge/FCP-3.1s-red?style=for-the-badge "First Contentful Paint") ![LCP](https://img.shields.io/badge/LCP-4.8s-red?style=for-the-badge "Largest Contentful Paint") ![TBT](https://img.shields.io/badge/TBT-60ms-green?style=for-the-badge "Total Blocking Time") ![CLS](https://img.shields.io/badge/CLS-0.038-green?style=for-the-badge "Cumulative Layout Shift") | [![PSI](https://www.gstatic.com/images/icons/material/product/2x/pagespeed_16dp.png)](https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Fbaskar-redirect--adp-devsite--adobedocs.aem.page%2Fexpress%2Fadd-ons%2Fdocs%2Fguides%2Fgetting-started%2F "Run again in Google PSI") |
| :desktop_computer: | [/express/add-ons/docs/guides/getting-started/](https://baskar-redirect--adp-devsite--adobedocs.aem.page/express/add-ons/docs/guides/getting-started/) | [![PERFORMANCE](https://img.shields.io/badge/PERFORMANCE-99-green?style=for-the-badge "Performance")](https://googlechrome.github.io/lighthouse/scorecalc/#device=mobile&version=12.4.0&SI=509.81168981754655&FCP=285.49650221865323&LCP=914.0380927371814&TBT=0&CLS=0.01545952063603558 "See Calculator") ![A11Y](https://img.shields.io/badge/A11Y-93-green?style=for-the-badge "Accessibility") ![SEO](https://img.shields.io/badge/SEO-61-orange?style=for-the-badge "SEO") ![BEST PRACTICES](https://img.shields.io/badge/BEST%20PRACTICES-96-green?style=for-the-badge "Best Practices") | ![SI](https://img.shields.io/badge/SI-0.5s-green?style=for-the-badge "Speed Index") ![FCP](https://img.shields.io/badge/FCP-0.3s-green?style=for-the-badge "First Contentful Paint") ![LCP](https://img.shields.io/badge/LCP-0.9s-green?style=for-the-badge "Largest Contentful Paint") ![TBT](https://img.shields.io/badge/TBT-0ms-green?style=for-the-badge "Total Blocking Time") ![CLS](https://img.shields.io/badge/CLS-0.015-green?style=for-the-badge "Cumulative Layout Shift") | [![PSI](https://www.gstatic.com/images/icons/material/product/2x/pagespeed_16dp.png)](https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Fbaskar-redirect--adp-devsite--adobedocs.aem.page%2Fexpress%2Fadd-ons%2Fdocs%2Fguides%2Fgetting-started%2F "Run again in Google PSI") |

author_association: NONE