chunk-049-seo-ui.js

I’ll build this as a strong SEO UI chunk for RX Theme: schema helpers, TOC, FAQ accordion, reading progress, breadcrumbs enhancement, copy-link buttons, lazy UI behaviors, and safe WordPress-friendly front-end code.

Yes friend — for this file:

/assets/static-js/static-chunks-js/chunk-049-seo-ui.js

Use it for SEO user-interface features, not heavy backend SEO. This file should improve user experience, engagement, structured-content interaction, readability, internal navigation, and article signals.

Copy this full code into:

rx-theme/assets/static-js/static-chunks-js/chunk-049-seo-ui.js
/*!
 * RX Theme - SEO UI Chunk
 * File: /assets/static-js/static-chunks-js/chunk-049-seo-ui.js
 * Purpose: Advanced SEO-friendly UI enhancement for article pages, medical content, blog posts, docs, FAQs, TOC, breadcrumbs, reading progress, share tools, and UX signals.
 * Author: RxHarun
 */

(function () {
  'use strict';

  /**
   * ==========================================================
   * RX SEO UI CONFIG
   * ==========================================================
   */

  const RX_SEO_UI = {
    selectors: {
      article: '.rx-article, article, .entry-content, .post-content, .rx-content',
      contentArea: '.entry-content, .post-content, .rx-content, article',
      headings: 'h2, h3',
      tocContainer: '[data-rx-toc], .rx-toc',
      faqContainer: '.rx-faq, [data-rx-faq]',
      faqItem: '.rx-faq-item, .faq-item',
      faqQuestion: '.rx-faq-question, .faq-question',
      faqAnswer: '.rx-faq-answer, .faq-answer',
      breadcrumb: '.rx-breadcrumb, .breadcrumbs, nav[aria-label="breadcrumb"]',
      shareBox: '.rx-share-box, [data-rx-share]',
      copyLinkButton: '[data-rx-copy-link]',
      printButton: '[data-rx-print]',
      backToTop: '[data-rx-back-to-top], .rx-back-to-top',
      readingProgress: '[data-rx-reading-progress], .rx-reading-progress',
      estimatedReadTime: '[data-rx-read-time], .rx-read-time',
      updatedDate: '[data-rx-updated-date], .rx-updated-date',
      searchInput: '[data-rx-content-search]',
      glossaryTerm: '[data-rx-glossary-term]',
      externalLinks: 'a[href^="http"]',
      internalLinks: 'a[href^="/"], a[href*="' + window.location.hostname + '"]',
      tables: '.entry-content table, .post-content table, article table',
      images: '.entry-content img, .post-content img, article img',
      videos: 'iframe[src*="youtube"], iframe[src*="vimeo"], video',
      accordions: '[data-rx-accordion]',
      jumpLinks: 'a[href^="#"]'
    },

    classes: {
      active: 'is-active',
      open: 'is-open',
      hidden: 'is-hidden',
      visible: 'is-visible',
      current: 'is-current',
      copied: 'is-copied',
      enhanced: 'rx-enhanced',
      tableWrap: 'rx-table-wrap',
      imageWrap: 'rx-image-wrap',
      externalLink: 'rx-external-link',
      internalLink: 'rx-internal-link',
      tocList: 'rx-toc-list',
      tocItem: 'rx-toc-item',
      tocLink: 'rx-toc-link',
      tocLevel2: 'rx-toc-level-2',
      tocLevel3: 'rx-toc-level-3',
      progressBar: 'rx-progress-bar'
    },

    options: {
      minHeadingsForToc: 3,
      wordsPerMinute: 220,
      scrollOffset: 90,
      debounceDelay: 120,
      throttleDelay: 80,
      autoGenerateToc: true,
      autoHeadingIds: true,
      smoothScroll: true,
      enableFaqAccordion: true,
      enableProgressBar: true,
      enableReadTime: true,
      enableExternalLinkSafety: true,
      enableTableWrap: true,
      enableImageEnhance: true,
      enableVideoLazyFrame: true,
      enableCopyButtons: true,
      enableContentSearch: true,
      enableBackToTop: true,
      enablePrint: true,
      enableTocSpy: true,
      enableSchemaHints: true
    }
  };

  /**
   * ==========================================================
   * SMALL HELPERS
   * ==========================================================
   */

  const RX = {
    qs(selector, parent = document) {
      return parent.querySelector(selector);
    },

    qsa(selector, parent = document) {
      return Array.prototype.slice.call(parent.querySelectorAll(selector));
    },

    hasClass(el, className) {
      return el && el.classList.contains(className);
    },

    addClass(el, className) {
      if (el) el.classList.add(className);
    },

    removeClass(el, className) {
      if (el) el.classList.remove(className);
    },

    toggleClass(el, className, force) {
      if (el) el.classList.toggle(className, force);
    },

    attr(el, name, value) {
      if (!el) return null;
      if (typeof value === 'undefined') return el.getAttribute(name);
      el.setAttribute(name, value);
      return value;
    },

    create(tag, className, text) {
      const el = document.createElement(tag);
      if (className) el.className = className;
      if (text) el.textContent = text;
      return el;
    },

    slugify(text) {
      return String(text || '')
        .toLowerCase()
        .trim()
        .replace(/&/g, ' and ')
        .replace(/[^\w\s-]/g, '')
        .replace(/\s+/g, '-')
        .replace(/-+/g, '-')
        .replace(/^-|-$/g, '');
    },

    uniqueId(base) {
      let id = base || 'rx-section';
      let i = 2;

      while (document.getElementById(id)) {
        id = base + '-' + i;
        i++;
      }

      return id;
    },

    getText(el) {
      return el ? el.textContent.replace(/\s+/g, ' ').trim() : '';
    },

    isVisible(el) {
      if (!el) return false;
      const style = window.getComputedStyle(el);
      return style.display !== 'none' && style.visibility !== 'hidden' && el.offsetParent !== null;
    },

    debounce(fn, wait) {
      let timer = null;

      return function () {
        const context = this;
        const args = arguments;

        clearTimeout(timer);
        timer = setTimeout(function () {
          fn.apply(context, args);
        }, wait);
      };
    },

    throttle(fn, wait) {
      let last = 0;
      let timer = null;

      return function () {
        const now = Date.now();
        const remaining = wait - (now - last);
        const context = this;
        const args = arguments;

        if (remaining <= 0) {
          clearTimeout(timer);
          timer = null;
          last = now;
          fn.apply(context, args);
        } else if (!timer) {
          timer = setTimeout(function () {
            last = Date.now();
            timer = null;
            fn.apply(context, args);
          }, remaining);
        }
      };
    },

    copyText(text) {
      if (navigator.clipboard && window.isSecureContext) {
        return navigator.clipboard.writeText(text);
      }

      return new Promise(function (resolve, reject) {
        const textarea = document.createElement('textarea');
        textarea.value = text;
        textarea.style.position = 'fixed';
        textarea.style.left = '-9999px';
        textarea.style.top = '-9999px';
        document.body.appendChild(textarea);
        textarea.focus();
        textarea.select();

        try {
          document.execCommand('copy');
          document.body.removeChild(textarea);
          resolve();
        } catch (error) {
          document.body.removeChild(textarea);
          reject(error);
        }
      });
    },

    safeUrl(url) {
      try {
        return new URL(url, window.location.origin);
      } catch (error) {
        return null;
      }
    },

    prefersReducedMotion() {
      return window.matchMedia &&
        window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    }
  };

  /**
   * ==========================================================
   * MAIN SEO UI MODULE
   * ==========================================================
   */

  const RxSeoUI = {
    article: null,
    headings: [],
    tocLinks: [],
    progressBar: null,

    init() {
      this.article = RX.qs(RX_SEO_UI.selectors.article);

      if (!this.article) {
        return;
      }

      RX.addClass(document.documentElement, 'rx-seo-ui-ready');

      this.prepareHeadings();
      this.buildTableOfContents();
      this.setupTocScrollSpy();
      this.setupSmoothJumpLinks();
      this.setupReadingProgress();
      this.setupEstimatedReadTime();
      this.setupFaqAccordion();
      this.setupBreadcrumbEnhancement();
      this.setupShareTools();
      this.setupCopyLinkButtons();
      this.setupBackToTop();
      this.setupPrintButtons();
      this.setupContentSearch();
      this.enhanceExternalLinks();
      this.enhanceInternalLinks();
      this.wrapTables();
      this.enhanceImages();
      this.enhanceVideos();
      this.setupAccordionBlocks();
      this.setupGlossaryTerms();
      this.setupSchemaHints();
      this.setupKeyboardUX();
      this.observeContentChanges();

      window.dispatchEvent(
        new CustomEvent('rxSeoUiReady', {
          detail: {
            article: this.article,
            headings: this.headings.length
          }
        })
      );
    },

    /**
     * ======================================================
     * HEADING ID + ARTICLE OUTLINE
     * ======================================================
     */

    prepareHeadings() {
      if (!RX_SEO_UI.options.autoHeadingIds) {
        return;
      }

      const headings = RX.qsa(RX_SEO_UI.selectors.headings, this.article)
        .filter(function (heading) {
          return RX.getText(heading).length > 0;
        });

      headings.forEach(function (heading) {
        if (!heading.id) {
          const base = RX.slugify(RX.getText(heading)) || 'rx-heading';
          heading.id = RX.uniqueId(base);
        }

        heading.setAttribute('tabindex', '-1');
        heading.classList.add('rx-seo-heading');
      });

      this.headings = headings;
    },

    /**
     * ======================================================
     * AUTO TABLE OF CONTENTS
     * ======================================================
     */

    buildTableOfContents() {
      if (!RX_SEO_UI.options.autoGenerateToc) {
        return;
      }

      const tocContainer = RX.qs(RX_SEO_UI.selectors.tocContainer);

      if (!tocContainer || this.headings.length < RX_SEO_UI.options.minHeadingsForToc) {
        return;
      }

      if (RX.hasClass(tocContainer, RX_SEO_UI.classes.enhanced)) {
        return;
      }

      const nav = RX.create('nav', 'rx-toc-nav');
      nav.setAttribute('aria-label', 'Article table of contents');

      const title = tocContainer.getAttribute('data-rx-toc-title') || 'Table of Contents';
      const titleEl = RX.create('div', 'rx-toc-title', title);

      const list = RX.create('ol', RX_SEO_UI.classes.tocList);

      this.headings.forEach(function (heading) {
        const level = heading.tagName.toLowerCase() === 'h3' ? 3 : 2;
        const item = RX.create(
          'li',
          RX_SEO_UI.classes.tocItem + ' ' + (level === 3 ? RX_SEO_UI.classes.tocLevel3 : RX_SEO_UI.classes.tocLevel2)
        );

        const link = RX.create('a', RX_SEO_UI.classes.tocLink, RX.getText(heading));
        link.href = '#' + heading.id;
        link.setAttribute('data-rx-target', heading.id);

        item.appendChild(link);
        list.appendChild(item);
      });

      nav.appendChild(titleEl);
      nav.appendChild(list);

      tocContainer.innerHTML = '';
      tocContainer.appendChild(nav);
      RX.addClass(tocContainer, RX_SEO_UI.classes.enhanced);

      this.tocLinks = RX.qsa('.' + RX_SEO_UI.classes.tocLink, tocContainer);
    },

    setupTocScrollSpy() {
      if (!RX_SEO_UI.options.enableTocSpy || !this.headings.length || !this.tocLinks.length) {
        return;
      }

      const updateActiveToc = RX.throttle(() => {
        let currentId = null;
        const offset = RX_SEO_UI.options.scrollOffset + 20;

        for (let i = 0; i < this.headings.length; i++) {
          const heading = this.headings[i];
          const rect = heading.getBoundingClientRect();

          if (rect.top <= offset) {
            currentId = heading.id;
          }
        }

        this.tocLinks.forEach(function (link) {
          const isCurrent = link.getAttribute('data-rx-target') === currentId;
          RX.toggleClass(link, RX_SEO_UI.classes.current, isCurrent);

          if (isCurrent) {
            link.setAttribute('aria-current', 'true');
          } else {
            link.removeAttribute('aria-current');
          }
        });
      }, RX_SEO_UI.options.throttleDelay);

      window.addEventListener('scroll', updateActiveToc, { passive: true });
      window.addEventListener('resize', updateActiveToc, { passive: true });
      updateActiveToc();
    },

    /**
     * ======================================================
     * SMOOTH SCROLL FOR JUMP LINKS
     * ======================================================
     */

    setupSmoothJumpLinks() {
      if (!RX_SEO_UI.options.smoothScroll) {
        return;
      }

      const links = RX.qsa(RX_SEO_UI.selectors.jumpLinks);

      links.forEach(function (link) {
        if (RX.hasClass(link, 'rx-smooth-ready')) {
          return;
        }

        RX.addClass(link, 'rx-smooth-ready');

        link.addEventListener('click', function (event) {
          const hash = link.getAttribute('href');

          if (!hash || hash === '#') {
            return;
          }

          const targetId = decodeURIComponent(hash.slice(1));
          const target = document.getElementById(targetId);

          if (!target) {
            return;
          }

          event.preventDefault();

          const top = target.getBoundingClientRect().top + window.pageYOffset - RX_SEO_UI.options.scrollOffset;

          window.scrollTo({
            top: top,
            behavior: RX.prefersReducedMotion() ? 'auto' : 'smooth'
          });

          target.focus({ preventScroll: true });

          if (history.pushState) {
            history.pushState(null, '', '#' + target.id);
          }
        });
      });
    },

    /**
     * ======================================================
     * READING PROGRESS
     * ======================================================
     */

    setupReadingProgress() {
      if (!RX_SEO_UI.options.enableProgressBar) {
        return;
      }

      let progress = RX.qs(RX_SEO_UI.selectors.readingProgress);

      if (!progress) {
        progress = RX.create('div', 'rx-reading-progress');
        progress.setAttribute('data-rx-reading-progress', '');
        progress.innerHTML = '<span class="' + RX_SEO_UI.classes.progressBar + '" aria-hidden="true"></span>';
        document.body.appendChild(progress);
      }

      this.progressBar = RX.qs('.' + RX_SEO_UI.classes.progressBar, progress) || progress;

      const updateProgress = RX.throttle(() => {
        const articleRect = this.article.getBoundingClientRect();
        const articleTop = articleRect.top + window.pageYOffset;
        const articleHeight = Math.max(this.article.offsetHeight - window.innerHeight, 1);
        const scrolled = window.pageYOffset - articleTop;
        const percentage = Math.max(0, Math.min(100, (scrolled / articleHeight) * 100));

        this.progressBar.style.width = percentage + '%';
        progress.setAttribute('aria-valuenow', Math.round(percentage));
      }, RX_SEO_UI.options.throttleDelay);

      progress.setAttribute('role', 'progressbar');
      progress.setAttribute('aria-label', 'Reading progress');
      progress.setAttribute('aria-valuemin', '0');
      progress.setAttribute('aria-valuemax', '100');

      window.addEventListener('scroll', updateProgress, { passive: true });
      window.addEventListener('resize', updateProgress, { passive: true });
      updateProgress();
    },

    /**
     * ======================================================
     * ESTIMATED READING TIME
     * ======================================================
     */

    setupEstimatedReadTime() {
      if (!RX_SEO_UI.options.enableReadTime) {
        return;
      }

      const readTimeEl = RX.qs(RX_SEO_UI.selectors.estimatedReadTime);

      if (!readTimeEl) {
        return;
      }

      const text = RX.getText(this.article);
      const words = text.split(/\s+/).filter(Boolean).length;
      const minutes = Math.max(1, Math.ceil(words / RX_SEO_UI.options.wordsPerMinute));

      readTimeEl.textContent = minutes + ' min read';
      readTimeEl.setAttribute('aria-label', 'Estimated reading time: ' + minutes + ' minutes');
      RX.addClass(readTimeEl, RX_SEO_UI.classes.enhanced);
    },

    /**
     * ======================================================
     * FAQ ACCORDION
     * ======================================================
     */

    setupFaqAccordion() {
      if (!RX_SEO_UI.options.enableFaqAccordion) {
        return;
      }

      const faqContainers = RX.qsa(RX_SEO_UI.selectors.faqContainer);

      faqContainers.forEach(function (container, containerIndex) {
        if (RX.hasClass(container, RX_SEO_UI.classes.enhanced)) {
          return;
        }

        const items = RX.qsa(RX_SEO_UI.selectors.faqItem, container);

        items.forEach(function (item, index) {
          const question = RX.qs(RX_SEO_UI.selectors.faqQuestion, item);
          const answer = RX.qs(RX_SEO_UI.selectors.faqAnswer, item);

          if (!question || !answer) {
            return;
          }

          const qId = question.id || 'rx-faq-q-' + containerIndex + '-' + index;
          const aId = answer.id || 'rx-faq-a-' + containerIndex + '-' + index;

          question.id = qId;
          answer.id = aId;

          question.setAttribute('role', 'button');
          question.setAttribute('tabindex', '0');
          question.setAttribute('aria-controls', aId);
          question.setAttribute('aria-expanded', RX.hasClass(item, RX_SEO_UI.classes.open) ? 'true' : 'false');

          answer.setAttribute('role', 'region');
          answer.setAttribute('aria-labelledby', qId);

          if (!RX.hasClass(item, RX_SEO_UI.classes.open)) {
            answer.hidden = true;
          }

          const toggle = function () {
            const isOpen = RX.hasClass(item, RX_SEO_UI.classes.open);

            RX.toggleClass(item, RX_SEO_UI.classes.open, !isOpen);
            question.setAttribute('aria-expanded', !isOpen ? 'true' : 'false');
            answer.hidden = isOpen;
          };

          question.addEventListener('click', toggle);

          question.addEventListener('keydown', function (event) {
            if (event.key === 'Enter' || event.key === ' ') {
              event.preventDefault();
              toggle();
            }
          });
        });

        RX.addClass(container, RX_SEO_UI.classes.enhanced);
      });
    },

    /**
     * ======================================================
     * BREADCRUMB ENHANCEMENT
     * ======================================================
     */

    setupBreadcrumbEnhancement() {
      const breadcrumbs = RX.qsa(RX_SEO_UI.selectors.breadcrumb);

      breadcrumbs.forEach(function (nav) {
        if (RX.hasClass(nav, RX_SEO_UI.classes.enhanced)) {
          return;
        }

        nav.setAttribute('aria-label', nav.getAttribute('aria-label') || 'Breadcrumb');

        const links = RX.qsa('a', nav);
        const last = links[links.length - 1];

        links.forEach(function (link) {
          link.classList.add('rx-breadcrumb-link');
        });

        if (last && last.href === window.location.href) {
          last.setAttribute('aria-current', 'page');
        }

        RX.addClass(nav, RX_SEO_UI.classes.enhanced);
      });
    },

    /**
     * ======================================================
     * SHARE TOOLS
     * ======================================================
     */

    setupShareTools() {
      const shareBoxes = RX.qsa(RX_SEO_UI.selectors.shareBox);

      shareBoxes.forEach(function (box) {
        if (RX.hasClass(box, RX_SEO_UI.classes.enhanced)) {
          return;
        }

        const title = document.title;
        const url = window.location.href;

        const nativeBtn = RX.qs('[data-rx-native-share]', box);

        if (nativeBtn && navigator.share) {
          nativeBtn.hidden = false;

          nativeBtn.addEventListener('click', function () {
            navigator.share({
              title: title,
              url: url
            }).catch(function () {
              // User cancelled share. No action needed.
            });
          });
        }

        const shareLinks = RX.qsa('[data-rx-share-platform]', box);

        shareLinks.forEach(function (link) {
          const platform = link.getAttribute('data-rx-share-platform');
          const encodedUrl = encodeURIComponent(url);
          const encodedTitle = encodeURIComponent(title);
          let href = '';

          if (platform === 'facebook') {
            href = 'https://www.facebook.com/sharer/sharer.php?u=' + encodedUrl;
          } else if (platform === 'twitter' || platform === 'x') {
            href = 'https://twitter.com/intent/tweet?url=' + encodedUrl + '&text=' + encodedTitle;
          } else if (platform === 'linkedin') {
            href = 'https://www.linkedin.com/sharing/share-offsite/?url=' + encodedUrl;
          } else if (platform === 'whatsapp') {
            href = 'https://api.whatsapp.com/send?text=' + encodedTitle + '%20' + encodedUrl;
          } else if (platform === 'telegram') {
            href = 'https://t.me/share/url?url=' + encodedUrl + '&text=' + encodedTitle;
          } else if (platform === 'email') {
            href = 'mailto:?subject=' + encodedTitle + '&body=' + encodedUrl;
          }

          if (href) {
            link.href = href;
            link.target = platform === 'email' ? '_self' : '_blank';
            link.rel = platform === 'email' ? '' : 'noopener noreferrer';
          }
        });

        RX.addClass(box, RX_SEO_UI.classes.enhanced);
      });
    },

    /**
     * ======================================================
     * COPY CURRENT LINK / COPY SECTION LINK
     * ======================================================
     */

    setupCopyLinkButtons() {
      if (!RX_SEO_UI.options.enableCopyButtons) {
        return;
      }

      const buttons = RX.qsa(RX_SEO_UI.selectors.copyLinkButton);

      buttons.forEach(function (button) {
        if (RX.hasClass(button, RX_SEO_UI.classes.enhanced)) {
          return;
        }

        const originalText = button.textContent;

        button.addEventListener('click', function () {
          const targetSelector = button.getAttribute('data-rx-copy-link');
          let textToCopy = window.location.href;

          if (targetSelector && targetSelector !== 'current') {
            const target = document.querySelector(targetSelector);

            if (target && target.id) {
              textToCopy = window.location.origin + window.location.pathname + '#' + target.id;
            }
          }

          RX.copyText(textToCopy)
            .then(function () {
              RX.addClass(button, RX_SEO_UI.classes.copied);
              button.textContent = button.getAttribute('data-rx-copied-text') || 'Copied';

              setTimeout(function () {
                RX.removeClass(button, RX_SEO_UI.classes.copied);
                button.textContent = originalText;
              }, 1600);
            })
            .catch(function () {
              button.textContent = 'Copy failed';

              setTimeout(function () {
                button.textContent = originalText;
              }, 1600);
            });
        });

        RX.addClass(button, RX_SEO_UI.classes.enhanced);
      });

      this.addHeadingCopyLinks();
    },

    addHeadingCopyLinks() {
      this.headings.forEach(function (heading) {
        if (RX.qs('.rx-heading-copy', heading)) {
          return;
        }

        const btn = RX.create('button', 'rx-heading-copy', '#');
        btn.type = 'button';
        btn.setAttribute('aria-label', 'Copy link to this section');

        btn.addEventListener('click', function () {
          const link = window.location.origin + window.location.pathname + '#' + heading.id;

          RX.copyText(link).then(function () {
            RX.addClass(btn, RX_SEO_UI.classes.copied);
            btn.textContent = '✓';

            setTimeout(function () {
              RX.removeClass(btn, RX_SEO_UI.classes.copied);
              btn.textContent = '#';
            }, 1400);
          });
        });

        heading.appendChild(btn);
      });
    },

    /**
     * ======================================================
     * BACK TO TOP
     * ======================================================
     */

    setupBackToTop() {
      if (!RX_SEO_UI.options.enableBackToTop) {
        return;
      }

      let button = RX.qs(RX_SEO_UI.selectors.backToTop);

      if (!button) {
        button = RX.create('button', 'rx-back-to-top', '↑');
        button.type = 'button';
        button.setAttribute('aria-label', 'Back to top');
        button.setAttribute('data-rx-back-to-top', '');
        document.body.appendChild(button);
      }

      const toggleButton = RX.throttle(function () {
        RX.toggleClass(button, RX_SEO_UI.classes.visible, window.pageYOffset > 600);
      }, RX_SEO_UI.options.throttleDelay);

      button.addEventListener('click', function () {
        window.scrollTo({
          top: 0,
          behavior: RX.prefersReducedMotion() ? 'auto' : 'smooth'
        });
      });

      window.addEventListener('scroll', toggleButton, { passive: true });
      toggleButton();
    },

    /**
     * ======================================================
     * PRINT
     * ======================================================
     */

    setupPrintButtons() {
      if (!RX_SEO_UI.options.enablePrint) {
        return;
      }

      const printButtons = RX.qsa(RX_SEO_UI.selectors.printButton);

      printButtons.forEach(function (button) {
        if (RX.hasClass(button, RX_SEO_UI.classes.enhanced)) {
          return;
        }

        button.addEventListener('click', function () {
          window.print();
        });

        RX.addClass(button, RX_SEO_UI.classes.enhanced);
      });
    },

    /**
     * ======================================================
     * CONTENT SEARCH INSIDE ARTICLE
     * ======================================================
     */

    setupContentSearch() {
      if (!RX_SEO_UI.options.enableContentSearch) {
        return;
      }

      const input = RX.qs(RX_SEO_UI.selectors.searchInput);

      if (!input) {
        return;
      }

      const searchableBlocks = RX.qsa('p, li, h2, h3, h4, blockquote', this.article);

      const clearMarks = function () {
        RX.qsa('mark.rx-search-mark').forEach(function (mark) {
          const parent = mark.parentNode;
          parent.replaceChild(document.createTextNode(mark.textContent), mark);
          parent.normalize();
        });
      };

      const markText = function (node, query) {
        const text = node.textContent;
        const index = text.toLowerCase().indexOf(query.toLowerCase());

        if (index === -1 || !query) {
          return false;
        }

        const before = document.createTextNode(text.slice(0, index));
        const mark = RX.create('mark', 'rx-search-mark', text.slice(index, index + query.length));
        const after = document.createTextNode(text.slice(index + query.length));

        node.textContent = '';
        node.appendChild(before);
        node.appendChild(mark);
        node.appendChild(after);

        return true;
      };

      const runSearch = RX.debounce(function () {
        const query = input.value.trim();

        clearMarks();

        searchableBlocks.forEach(function (block) {
          RX.removeClass(block, 'rx-search-hit');
        });

        if (query.length < 2) {
          return;
        }

        let firstHit = null;

        searchableBlocks.forEach(function (block) {
          if (block.children.length > 0 && !/^(H2|H3|H4|P|LI|BLOCKQUOTE)$/.test(block.tagName)) {
            return;
          }

          const found = markText(block, query);

          if (found) {
            RX.addClass(block, 'rx-search-hit');
            if (!firstHit) {
              firstHit = block;
            }
          }
        });

        if (firstHit) {
          firstHit.scrollIntoView({
            behavior: RX.prefersReducedMotion() ? 'auto' : 'smooth',
            block: 'center'
          });
        }
      }, 220);

      input.addEventListener('input', runSearch);
    },

    /**
     * ======================================================
     * EXTERNAL LINK SEO + SECURITY ENHANCEMENT
     * ======================================================
     */

    enhanceExternalLinks() {
      if (!RX_SEO_UI.options.enableExternalLinkSafety) {
        return;
      }

      const links = RX.qsa(RX_SEO_UI.selectors.externalLinks, this.article);

      links.forEach(function (link) {
        const url = RX.safeUrl(link.href);

        if (!url || url.hostname === window.location.hostname) {
          return;
        }

        RX.addClass(link, RX_SEO_UI.classes.externalLink);

        if (!link.target) {
          link.target = '_blank';
        }

        const relParts = new Set((link.rel || '').split(/\s+/).filter(Boolean));
        relParts.add('noopener');
        relParts.add('noreferrer');

        if (link.getAttribute('data-rx-sponsored') === 'true') {
          relParts.add('sponsored');
        }

        if (link.getAttribute('data-rx-ugc') === 'true') {
          relParts.add('ugc');
        }

        link.rel = Array.from(relParts).join(' ');

        if (!link.getAttribute('aria-label')) {
          link.setAttribute('aria-label', RX.getText(link) + ' opens in a new tab');
        }
      });
    },

    enhanceInternalLinks() {
      const links = RX.qsa(RX_SEO_UI.selectors.internalLinks, this.article);

      links.forEach(function (link) {
        const url = RX.safeUrl(link.href);

        if (!url) {
          return;
        }

        if (url.hostname === window.location.hostname) {
          RX.addClass(link, RX_SEO_UI.classes.internalLink);
        }
      });
    },

    /**
     * ======================================================
     * RESPONSIVE TABLE WRAPPER
     * ======================================================
     */

    wrapTables() {
      if (!RX_SEO_UI.options.enableTableWrap) {
        return;
      }

      const tables = RX.qsa(RX_SEO_UI.selectors.tables);

      tables.forEach(function (table) {
        if (table.parentElement && RX.hasClass(table.parentElement, RX_SEO_UI.classes.tableWrap)) {
          return;
        }

        const wrapper = RX.create('div', RX_SEO_UI.classes.tableWrap);
        wrapper.setAttribute('role', 'region');
        wrapper.setAttribute('aria-label', 'Scrollable table');
        wrapper.setAttribute('tabindex', '0');

        table.parentNode.insertBefore(wrapper, table);
        wrapper.appendChild(table);

        RX.addClass(table, RX_SEO_UI.classes.enhanced);
      });
    },

    /**
     * ======================================================
     * IMAGE ENHANCEMENT
     * ======================================================
     */

    enhanceImages() {
      if (!RX_SEO_UI.options.enableImageEnhance) {
        return;
      }

      const images = RX.qsa(RX_SEO_UI.selectors.images);

      images.forEach(function (img) {
        if (!img.hasAttribute('loading')) {
          img.setAttribute('loading', 'lazy');
        }

        if (!img.hasAttribute('decoding')) {
          img.setAttribute('decoding', 'async');
        }

        if (!img.alt || img.alt.trim() === '') {
          img.setAttribute('alt', '');
        }

        RX.addClass(img, RX_SEO_UI.classes.enhanced);

        if (
          img.parentElement &&
          img.parentElement.tagName !== 'FIGURE' &&
          !RX.hasClass(img.parentElement, RX_SEO_UI.classes.imageWrap)
        ) {
          const wrapper = RX.create('span', RX_SEO_UI.classes.imageWrap);
          img.parentNode.insertBefore(wrapper, img);
          wrapper.appendChild(img);
        }
      });
    },

    /**
     * ======================================================
     * VIDEO / IFRAME ENHANCEMENT
     * ======================================================
     */

    enhanceVideos() {
      if (!RX_SEO_UI.options.enableVideoLazyFrame) {
        return;
      }

      const videos = RX.qsa(RX_SEO_UI.selectors.videos, this.article);

      videos.forEach(function (video) {
        if (video.tagName.toLowerCase() === 'iframe') {
          if (!video.hasAttribute('loading')) {
            video.setAttribute('loading', 'lazy');
          }

          if (!video.hasAttribute('title')) {
            video.setAttribute('title', 'Embedded video');
          }

          if (!video.parentElement.classList.contains('rx-video-wrap')) {
            const wrapper = RX.create('div', 'rx-video-wrap');
            video.parentNode.insertBefore(wrapper, video);
            wrapper.appendChild(video);
          }
        }

        if (video.tagName.toLowerCase() === 'video') {
          video.setAttribute('preload', video.getAttribute('preload') || 'metadata');
        }

        RX.addClass(video, RX_SEO_UI.classes.enhanced);
      });
    },

    /**
     * ======================================================
     * GENERIC ACCORDION
     * ======================================================
     */

    setupAccordionBlocks() {
      const accordions = RX.qsa(RX_SEO_UI.selectors.accordions);

      accordions.forEach(function (accordion, accordionIndex) {
        if (RX.hasClass(accordion, RX_SEO_UI.classes.enhanced)) {
          return;
        }

        const triggers = RX.qsa('[data-rx-accordion-trigger]', accordion);

        triggers.forEach(function (trigger, index) {
          const panelSelector = trigger.getAttribute('data-rx-accordion-trigger');
          const panel = panelSelector
            ? RX.qs(panelSelector, accordion)
            : trigger.nextElementSibling;

          if (!panel) {
            return;
          }

          const triggerId = trigger.id || 'rx-accordion-trigger-' + accordionIndex + '-' + index;
          const panelId = panel.id || 'rx-accordion-panel-' + accordionIndex + '-' + index;

          trigger.id = triggerId;
          panel.id = panelId;

          trigger.setAttribute('role', 'button');
          trigger.setAttribute('tabindex', '0');
          trigger.setAttribute('aria-controls', panelId);
          trigger.setAttribute('aria-expanded', RX.hasClass(panel, RX_SEO_UI.classes.open) ? 'true' : 'false');

          panel.setAttribute('role', 'region');
          panel.setAttribute('aria-labelledby', triggerId);

          if (!RX.hasClass(panel, RX_SEO_UI.classes.open)) {
            panel.hidden = true;
          }

          const togglePanel = function () {
            const isOpen = trigger.getAttribute('aria-expanded') === 'true';

            trigger.setAttribute('aria-expanded', isOpen ? 'false' : 'true');
            panel.hidden = isOpen;
            RX.toggleClass(panel, RX_SEO_UI.classes.open, !isOpen);
          };

          trigger.addEventListener('click', togglePanel);

          trigger.addEventListener('keydown', function (event) {
            if (event.key === 'Enter' || event.key === ' ') {
              event.preventDefault();
              togglePanel();
            }
          });
        });

        RX.addClass(accordion, RX_SEO_UI.classes.enhanced);
      });
    },

    /**
     * ======================================================
     * GLOSSARY TERMS
     * ======================================================
     */

    setupGlossaryTerms() {
      const terms = RX.qsa(RX_SEO_UI.selectors.glossaryTerm, this.article);

      terms.forEach(function (term, index) {
        if (RX.hasClass(term, RX_SEO_UI.classes.enhanced)) {
          return;
        }

        const definition = term.getAttribute('data-rx-definition');

        if (!definition) {
          return;
        }

        const tooltipId = 'rx-glossary-tooltip-' + index;
        const tooltip = RX.create('span', 'rx-glossary-tooltip', definition);
        tooltip.id = tooltipId;
        tooltip.setAttribute('role', 'tooltip');
        tooltip.hidden = true;

        term.setAttribute('tabindex', '0');
        term.setAttribute('aria-describedby', tooltipId);
        term.appendChild(tooltip);

        const show = function () {
          tooltip.hidden = false;
          RX.addClass(term, RX_SEO_UI.classes.open);
        };

        const hide = function () {
          tooltip.hidden = true;
          RX.removeClass(term, RX_SEO_UI.classes.open);
        };

        term.addEventListener('mouseenter', show);
        term.addEventListener('focus', show);
        term.addEventListener('mouseleave', hide);
        term.addEventListener('blur', hide);

        RX.addClass(term, RX_SEO_UI.classes.enhanced);
      });
    },

    /**
     * ======================================================
     * LIGHT SCHEMA HINTS
     * This does not replace PHP schema.
     * It only adds data attributes/classes for front-end consistency.
     * Real JSON-LD should be generated from WordPress/PHP.
     * ======================================================
     */

    setupSchemaHints() {
      if (!RX_SEO_UI.options.enableSchemaHints) {
        return;
      }

      const faqContainers = RX.qsa(RX_SEO_UI.selectors.faqContainer);

      faqContainers.forEach(function (container) {
        container.setAttribute('data-schema-hint', 'FAQPage');
      });

      const breadcrumbs = RX.qsa(RX_SEO_UI.selectors.breadcrumb);

      breadcrumbs.forEach(function (breadcrumb) {
        breadcrumb.setAttribute('data-schema-hint', 'BreadcrumbList');
      });

      if (this.article) {
        this.article.setAttribute('data-schema-hint', 'Article');
      }
    },

    /**
     * ======================================================
     * KEYBOARD UX
     * ======================================================
     */

    setupKeyboardUX() {
      document.addEventListener('keydown', function (event) {
        if (event.key === 'Escape') {
          RX.qsa('.rx-glossary-tooltip').forEach(function (tooltip) {
            tooltip.hidden = true;
          });

          RX.qsa('.rx-glossary-term, [data-rx-glossary-term]').forEach(function (term) {
            RX.removeClass(term, RX_SEO_UI.classes.open);
          });
        }
      });
    },

    /**
     * ======================================================
     * CONTENT MUTATION OBSERVER
     * Useful when article content is loaded later by AJAX.
     * ======================================================
     */

    observeContentChanges() {
      if (!window.MutationObserver || !this.article) {
        return;
      }

      const observer = new MutationObserver(
        RX.debounce(() => {
          this.prepareHeadings();
          this.setupSmoothJumpLinks();
          this.enhanceExternalLinks();
          this.enhanceInternalLinks();
          this.wrapTables();
          this.enhanceImages();
          this.enhanceVideos();
          this.setupFaqAccordion();
          this.setupAccordionBlocks();
          this.setupGlossaryTerms();
        }, 300)
      );

      observer.observe(this.article, {
        childList: true,
        subtree: true
      });
    }
  };

  /**
   * ==========================================================
   * SAFE DOM READY
   * ==========================================================
   */

  function domReady(callback) {
    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', callback);
    } else {
      callback();
    }
  }

  domReady(function () {
    RxSeoUI.init();
  });

  /**
   * ==========================================================
   * GLOBAL SAFE EXPORT
   * ==========================================================
   */

  window.RxSeoUI = RxSeoUI;
})();

Add this CSS also in your SEO/UI CSS file, for example:

/assets/css/components/seo-ui.css
.rx-reading-progress {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 99999;
  width: 100%;
  height: 3px;
  background: transparent;
  pointer-events: none;
}

.rx-progress-bar {
  display: block;
  width: 0;
  height: 100%;
  background: currentColor;
  transition: width 0.1s linear;
}

.rx-toc {
  border: 1px solid currentColor;
  border-radius: 12px;
  padding: 16px;
  margin: 24px 0;
}

.rx-toc-title {
  font-weight: 700;
  margin-bottom: 10px;
}

.rx-toc-list {
  margin: 0;
  padding-left: 20px;
}

.rx-toc-item {
  margin: 6px 0;
}

.rx-toc-level-3 {
  margin-left: 18px;
  font-size: 0.95em;
}

.rx-toc-link {
  text-decoration: none;
}

.rx-toc-link.is-current {
  font-weight: 700;
  text-decoration: underline;
}

.rx-heading-copy {
  margin-left: 8px;
  border: 0;
  background: transparent;
  cursor: pointer;
  font-size: 0.8em;
  opacity: 0.45;
}

.rx-heading-copy:hover,
.rx-heading-copy:focus,
.rx-heading-copy.is-copied {
  opacity: 1;
}

.rx-table-wrap {
  overflow-x: auto;
  max-width: 100%;
  margin: 20px 0;
}

.rx-table-wrap table {
  width: 100%;
  min-width: 620px;
}

.rx-image-wrap {
  display: inline-block;
  max-width: 100%;
}

.rx-image-wrap img {
  max-width: 100%;
  height: auto;
}

.rx-video-wrap {
  position: relative;
  overflow: hidden;
  width: 100%;
  aspect-ratio: 16 / 9;
  margin: 24px 0;
}

.rx-video-wrap iframe,
.rx-video-wrap video {
  width: 100%;
  height: 100%;
  border: 0;
}

.rx-faq-question,
[data-rx-accordion-trigger] {
  cursor: pointer;
}

.rx-faq-answer[hidden],
[data-rx-accordion] [hidden] {
  display: none;
}

.rx-back-to-top {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 9999;
  width: 44px;
  height: 44px;
  border-radius: 999px;
  border: 1px solid currentColor;
  opacity: 0;
  visibility: hidden;
  cursor: pointer;
  transition: opacity 0.2s ease, visibility 0.2s ease, transform 0.2s ease;
}

.rx-back-to-top.is-visible {
  opacity: 1;
  visibility: visible;
}

.rx-search-mark {
  padding: 0 2px;
}

.rx-glossary-term,
[data-rx-glossary-term] {
  position: relative;
  cursor: help;
  border-bottom: 1px dotted currentColor;
}

.rx-glossary-tooltip {
  position: absolute;
  left: 0;
  bottom: 100%;
  z-index: 20;
  width: max-content;
  max-width: 260px;
  padding: 8px 10px;
  border-radius: 8px;
  background: #111;
  color: #fff;
  font-size: 13px;
  line-height: 1.4;
}

.rx-external-link::after {
  content: "↗";
  margin-left: 3px;
  font-size: 0.8em;
}

@media print {
  .rx-reading-progress,
  .rx-back-to-top,
  .rx-heading-copy,
  .rx-share-box,
  [data-rx-share] {
    display: none !important;
  }

  .rx-table-wrap {
    overflow: visible;
  }
}

Example HTML usage inside your WordPress template:

<div class="rx-read-time" data-rx-read-time></div>

<div class="rx-toc" data-rx-toc data-rx-toc-title="Article Contents"></div>

<article class="rx-article entry-content">
  <h2>What is High Blood Pressure?</h2>
  <p>Content here...</p>

  <h2>Symptoms</h2>
  <p>Content here...</p>

  <h2>FAQs</h2>
  <div class="rx-faq" data-rx-faq>
    <div class="rx-faq-item">
      <div class="rx-faq-question">Is high blood pressure dangerous?</div>
      <div class="rx-faq-answer">
        <p>Yes, untreated high blood pressure can increase health risks.</p>
      </div>
    </div>
  </div>
</article>

<button data-rx-copy-link="current">Copy link</button>
<button data-rx-print>Print</button>

Best loading style in WordPress:

wp_enqueue_script(
    'rx-chunk-049-seo-ui',
    get_template_directory_uri() . '/assets/static-js/static-chunks-js/chunk-049-seo-ui.js',
    array(),
    wp_get_theme()->get('Version'),
    true
);

For advanced performance, load it only on single posts/pages:

if ( is_single() || is_page() ) {
    wp_enqueue_script(
        'rx-chunk-049-seo-ui',
        get_template_directory_uri() . '/assets/static-js/static-chunks-js/chunk-049-seo-ui.js',
        array(),
        wp_get_theme()->get('Version'),
        true
    );
}

My best advice: keep this file for front-end SEO UI, and keep real SEO schema, meta title, canonical, Open Graph, Twitter cards, and JSON-LD inside PHP files like:

/inc/seo/schema.php
/inc/seo/meta-tags.php
/inc/seo/open-graph.php
/inc/seo/breadcrumb-schema.php

Leave a Reply

Your email address will not be published. Required fields are marked *