/** * getSubscriptionList(elId = 'subscription-data') * - Safely reads a JSON array string from a data attribute `data-subscription-list` * (produced by Liquid and HTML-escaped), decodes it if needed, and returns the parsed array. * - Returns [] on any parse error. * * Example output: [{ position: 1, title: "Box A", url: "https://..." }, ...] */ function getSubscriptionList(elId = 'subscription-data') { try { const el = document.getElementById(elId); if (!el) return []; // Prefer raw attribute (avoids dataset normalization differences) let raw = el.getAttribute('data-subscription-list'); if (!raw) { // fallback to dataset (some frameworks normalize data attributes) raw = el.dataset && el.dataset.subscriptionList ? el.dataset.subscriptionList : null; } if (!raw) return []; // If the string looks like it contains HTML entities (e.g. "), convert them. // Create a temporary DOM node to let the browser unescape HTML entities reliably. // Most browsers return the unescaped string for getAttribute, but this is robust. if (raw.indexOf('&') !== -1) { const txt = document.createElement('textarea'); txt.innerHTML = raw; raw = txt.value; } // Trim and parse JSON const trimmed = raw.trim(); if (!trimmed || trimmed === '[]') return []; const parsed = JSON.parse(trimmed); // Basic validation: ensure array of objects with expected keys if (!Array.isArray(parsed)) return []; return parsed.filter(item => item && (item.title || item.url)); } catch (err) { // Fail gracefully console.warn('getSubscriptionList parse error', err); return []; } } /* Usage example: document.addEventListener('DOMContentLoaded', () => { const subs = getSubscriptionList(); if (subs.length) { // initialize carousel, build list, etc. console.log('Subscription items:', subs); } }); */