From 78da05da1c0949f8fb3b79cae513dc4f729d7219 Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Fri, 5 Jan 2024 16:04:51 +0100 Subject: [PATCH 01/54] Improve theme excel format --- styles/styles.css | 1 + 1 file changed, 1 insertion(+) diff --git a/styles/styles.css b/styles/styles.css index dd6e5f33..143da461 100644 --- a/styles/styles.css +++ b/styles/styles.css @@ -52,6 +52,7 @@ main div > div { background-color: var(--scope-background, #fff); color: var(--scope-color, #000); margin: var(--scope-margin, 0 auto); + padding: var(--scope-padding, 0); } a { From 058774e73de6c4ea7262f51038525bd995542fe3 Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Mon, 8 Jan 2024 10:10:08 +0100 Subject: [PATCH 02/54] #theme --- blocks/button/button.css | 8 +++-- blocks/card/card.css | 40 ++++++++++++++++++++----- blocks/card/card.js | 32 ++++++++++---------- blocks/icon/icon.css | 7 +++-- blocks/navigation/navigation.css | 12 ++++++++ blocks/theme/theme.js | 4 ++- styles/styles.css | 51 +++++++++++++++----------------- 7 files changed, 98 insertions(+), 56 deletions(-) diff --git a/blocks/button/button.css b/blocks/button/button.css index 7358e7cb..e3a5c958 100644 --- a/blocks/button/button.css +++ b/blocks/button/button.css @@ -1,8 +1,12 @@ raqn-button { width: 100%; display: grid; + align-content: center; + justify-content: center; + align-items: center; + justify-items: var(--scope-justify, start); - & > div { + & > * { background-color: var(--scope-accent-background, #000); color: var(--scope-accent-color, #fff); text-transform: none; @@ -19,7 +23,7 @@ raqn-button { } raqn-button a { - color: currentcolor; + color: var(--scope-accent-color, currentcolor); padding: 10px 20px; text-decoration: none; } diff --git a/blocks/card/card.css b/blocks/card/card.css index db0d2da7..2f239bea 100644 --- a/blocks/card/card.css +++ b/blocks/card/card.css @@ -1,10 +1,36 @@ raqn-card { - background-color: var(--scope-background, red); - display: grid; - grid-template-columns: var(--card-columns, 1fr); - gap: var(--scope-gap, 20px); + background-color: var(--scope-background, red); + display: grid; + position: relative; + grid-template-columns: var(--card-columns, 1fr); + gap: var(--scope-gap, 20px); + padding: var(--scope-padding, 20px 0); +} +raqn-card a { + font-size: var(--raqn-font-size-3, 1.2em); + font-weight: bold; +} +raqn-card:not(.inner-background) > div { + background-color: var(--scope-background, #fff); + color: var(--scope-color, #000); } - raqn-card > picture { - grid-column: span var(--card-columns, 1fr); -} \ No newline at end of file + grid-column: span var(--card-columns, 1fr); +} +raqn-card > div { + position: relative; +} + +raqn-card > div div:last-child > a { + position: absolute; + inset-inline-start: 0; + inset-block-start: 0; + width: 100%; + height: 100%; + cursor: pointer; + text-indent: -10000px; +} +raqn-card raqn-icon { + width: 100%; + display: flex; +} diff --git a/blocks/card/card.js b/blocks/card/card.js index cd9b1026..9c69b120 100644 --- a/blocks/card/card.js +++ b/blocks/card/card.js @@ -3,17 +3,32 @@ import { eagerImage } from '../../scripts/libs.js'; export default class Card extends ComponentBase { static get observedAttributes() { - return ['columns', 'ratio', 'eager']; + return ['columns', 'ratio', 'eager', 'background', 'button']; } connected() { + if (this.getAttribute('button') === 'true') { + Array.from(this.querySelectorAll('a')).forEach((a) => + this.convertLink(a), + ); + } this.eager = parseInt(this.getAttribute('eager') || 0, 10); + this.ratio = this.getAttribute('ratio') || '4/3'; + this.style.setProperty('--card-ratio', this.ratio); + this.classList.add('inner'); this.setupColumns(this.getAttribute('columns')); if (this.eager) { eagerImage(this, this.eager); } } + convertLink(a) { + const button = document.createElement('raqn-button'); + const content = a.outerHTML; + button.innerHTML = content; + a.replaceWith(button); + } + setupColumns(columns) { if (!columns) { return; @@ -24,19 +39,4 @@ export default class Card extends ComponentBase { .join(' '); this.style.setProperty('--card-columns', this.area); } - - attributeChangedCallback(name, oldValue, newValue) { - if (oldValue !== newValue) { - switch (name) { - case 'columns': - this.setupColumns(newValue); - break; - case 'ratio': - this.style.setProperty('--card-ratio', newValue); - break; - default: - break; - } - } - } } diff --git a/blocks/icon/icon.css b/blocks/icon/icon.css index bd707aa0..e4ac4b87 100644 --- a/blocks/icon/icon.css +++ b/blocks/icon/icon.css @@ -2,9 +2,10 @@ raqn-icon { display: inline-flex; font-size: 1em; line-height: 1em; + text-align: center; min-width: var(--scope-icon-size, 1em); min-height: var(--scope-icon-size, 1em); - text-align: center; + justify-content: var(--scope-icon-align, start); text-transform: none; vertical-align: middle; -webkit-font-smoothing: antialiased; @@ -13,8 +14,8 @@ raqn-icon { raqn-icon svg { display: inline-block; - max-height: 100%; - max-width: 100%; + max-width: var(--scope-icon-size, 1em); + max-height: var(--scope-icon-size, 1em); fill: currentcolor; overflow: hidden; vertical-align: middle; diff --git a/blocks/navigation/navigation.css b/blocks/navigation/navigation.css index 26f5ed24..a92c9715 100644 --- a/blocks/navigation/navigation.css +++ b/blocks/navigation/navigation.css @@ -78,6 +78,7 @@ raqn-navigation { &:not([compact='true']) > nav { a { line-height: var(--scope-icon-size, 24px); + /* font-size: inherit; */ } ul { @@ -136,5 +137,16 @@ raqn-navigation { opacity: 1; } } + + .level-2, + .level-2 > ul { + display: inline-flex; + flex-direction: column; + } + + .level-2 > ul { + list-style: none; + padding: 0; + } } } diff --git a/blocks/theme/theme.js b/blocks/theme/theme.js index c7ad257a..55f77bf6 100644 --- a/blocks/theme/theme.js +++ b/blocks/theme/theme.js @@ -7,7 +7,8 @@ export default class Theme extends ComponentBase { constructor() { super(); this.external = '/theme.json'; - this.toTags = ['font-size', 'font-weight', 'font-family']; + this.skip = ['tag', 'font-face']; + this.toTags = ['font-size', 'font-weight', 'font-family', 'line-height']; this.fontFace = ''; this.atomic = ''; } @@ -85,6 +86,7 @@ export default class Theme extends ComponentBase { .join('\n\n'); this.variables = k(t) + .filter((key) => !this.skip.includes(key)) .map((key) => { const rows = k(t[key]); return rows.map((row) => this.renderVariables(key, row, t)).join(''); diff --git a/styles/styles.css b/styles/styles.css index 143da461..6e9522f9 100644 --- a/styles/styles.css +++ b/styles/styles.css @@ -39,27 +39,38 @@ main > * { } .full-width { - --scope-outer-gap: calc((var(--scope-max-width) - 100vw) / 2); - + --scope-outer-gap: calc((var(--raqn-max-width-default) - 100vw) / 2); + --scope-inner-gap: calc((100vw - var(--scope-max-width)) / 2); display: grid; width: 100vw; margin-inline-start: var(--scope-outer-gap); - padding-inline: calc(-1 * var(--scope-outer-gap)); + padding-inline: var(--scope-inner-gap); box-sizing: border-box; } -main div > div { +main > div > div { background-color: var(--scope-background, #fff); color: var(--scope-color, #000); - margin: var(--scope-margin, 0 auto); padding: var(--scope-padding, 0); } +main > div > div > div { + max-width: var(--scope-max-width, 100%); + margin: var(--scope-margin, 0 auto); +} + a { display: inline-flex; line-height: 1em; text-align: center; align-items: center; + color: var(--scope-link-color, inherit); + text-decoration: none; + font-size: var(--scope-font-size, 1.2em); + + &:hover { + color: var(--scope-link-color-hover, inherit); + } } .raqn-grid { @@ -83,26 +94,12 @@ img { pointer-events: none; } -@keyframes placeholder { - 0% { - background-color: var(--scope-background, #fff); - } - - 50% { - background-color: var(--scope-color, #999); - } - - 100% { - background-color: var(--scope-background, #fff); - } -} - -@keyframes fade-in { - 0% { - opacity: 0; - } - - 100% { - opacity: 1; - } +p, +h1, +h2, +h3, +h4, +h5, +h6 { + margin: var(--scope-margin, 1em 0); } From 05c52e9edbd4d0a6f9fc438270d3eb38a1e12732 Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Mon, 8 Jan 2024 16:52:41 +0100 Subject: [PATCH 03/54] Comparition --- head.html | 3 --- 1 file changed, 3 deletions(-) diff --git a/head.html b/head.html index 68292790..6f07eff5 100644 --- a/head.html +++ b/head.html @@ -1,8 +1,5 @@ - - - Date: Mon, 8 Jan 2024 16:57:43 +0100 Subject: [PATCH 04/54] Comparition --- scripts/init.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/init.js b/scripts/init.js index ebc9b3d9..c657d51d 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -23,7 +23,7 @@ function lcpPriority() { const eagerImages = document.querySelector('meta[name="lcp"]'); if (eagerImages) { const length = parseInt(eagerImages.getAttribute('content'), 10); - eagerImage(document, length); + eagerImage(document.body, length); } const lcp = document.querySelector('meta[name="lcp"]'); From f2394004bbe6d88460728d113e2c8fa1818a449a Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Mon, 8 Jan 2024 16:59:14 +0100 Subject: [PATCH 05/54] Comparition --- blocks/card/card.js | 2 +- blocks/header/header.js | 2 +- scripts/init.js | 13 ++++++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/blocks/card/card.js b/blocks/card/card.js index 9c69b120..519bfb35 100644 --- a/blocks/card/card.js +++ b/blocks/card/card.js @@ -1,5 +1,5 @@ import ComponentBase from '../../scripts/component-base.js'; -import { eagerImage } from '../../scripts/libs.js'; +import { eagerImage } from '../../scripts/init.js'; export default class Card extends ComponentBase { static get observedAttributes() { diff --git a/blocks/header/header.js b/blocks/header/header.js index 5d373996..12cd96bd 100644 --- a/blocks/header/header.js +++ b/blocks/header/header.js @@ -1,5 +1,5 @@ import ComponentBase from '../../scripts/component-base.js'; -import { eagerImage } from '../../scripts/libs.js'; +import { eagerImage } from '../../scripts/init.js'; export default class Header extends ComponentBase { external = '/header.plain.html'; diff --git a/scripts/init.js b/scripts/init.js index c657d51d..22e2530c 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -1,5 +1,16 @@ import ComponentLoader from './component-loader.js'; -import { config, debounce, eagerImage, getBreakPoint } from './libs.js'; +import { config, debounce, getBreakPoint } from './libs.js'; + +export const eagerImage = (block, length = 1) => { + const imgs = Array.from(block.querySelectorAll('img')).slice(0, length); + imgs.forEach((img) => { + const width = img.getAttribute('width'); + const height = img.getAttribute('height'); + const ratio = Math.floor((width / height) * 100) / 100; + img.style.aspectRatio = ratio; + img.setAttribute('loading', 'eager'); + }); +}; export function retriveDataFrom(blocks) { return blocks.map((block) => { From 45e79ea93aa9fb3812cf02244f6372ca9c45bb00 Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Mon, 8 Jan 2024 17:02:53 +0100 Subject: [PATCH 06/54] Comparition --- scripts/init.js | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/scripts/init.js b/scripts/init.js index 22e2530c..57c82ea4 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -3,12 +3,13 @@ import { config, debounce, getBreakPoint } from './libs.js'; export const eagerImage = (block, length = 1) => { const imgs = Array.from(block.querySelectorAll('img')).slice(0, length); - imgs.forEach((img) => { + return imgs.map((img) => { const width = img.getAttribute('width'); const height = img.getAttribute('height'); const ratio = Math.floor((width / height) * 100) / 100; img.style.aspectRatio = ratio; img.setAttribute('loading', 'eager'); + return img; }); }; @@ -31,27 +32,31 @@ export function retriveDataFrom(blocks) { } function lcpPriority() { - const eagerImages = document.querySelector('meta[name="lcp"]'); - if (eagerImages) { - const length = parseInt(eagerImages.getAttribute('content'), 10); - eagerImage(document.body, length); - } + if (!window.raqnLCP) { + const eagerImages = document.querySelector('meta[name="lcp"]'); + if (eagerImages) { + const length = parseInt(eagerImages.getAttribute('content'), 10); + eagerImage(document.body, length); + } - const lcp = document.querySelector('meta[name="lcp"]'); - if (!lcp) { - return window.raqnLCP || []; + const lcp = document.querySelector('meta[name="lcp"]'); + if (!lcp) { + return window.raqnLCP || []; + } + window.raqnLCP = + window.raqnLCP || + lcp + .getAttribute('content') + .split(',') + .map((name) => ({ name })); } - window.raqnLCP = - window.raqnLCP || - lcp - .getAttribute('content') - .split(',') - .map((name) => ({ name })); return window.raqnLCP; } export async function init(node = document) { let blocks = Array.from(node.querySelectorAll('[class]:not([class^=style]')); + const imgs = lcpPriority(); + console.log(imgs); if (node === document) { const header = node.querySelector('header'); @@ -90,5 +95,4 @@ export async function init(node = document) { } // mechanism of retrieving lang to be used in the app document.documentElement.lang = document.documentElement.lang || 'en'; -lcpPriority(); init(); From a2a2830d61051eb07e337c3047d585d3e0e85ca6 Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Mon, 8 Jan 2024 17:04:09 +0100 Subject: [PATCH 07/54] Comparition --- scripts/init.js | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/scripts/init.js b/scripts/init.js index 57c82ea4..360d910e 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -32,31 +32,27 @@ export function retriveDataFrom(blocks) { } function lcpPriority() { - if (!window.raqnLCP) { - const eagerImages = document.querySelector('meta[name="lcp"]'); - if (eagerImages) { - const length = parseInt(eagerImages.getAttribute('content'), 10); - eagerImage(document.body, length); - } + const eagerImages = document.querySelector('meta[name="lcp"]'); + if (eagerImages) { + const length = parseInt(eagerImages.getAttribute('content'), 10); + eagerImage(document.body, length); + } - const lcp = document.querySelector('meta[name="lcp"]'); - if (!lcp) { - return window.raqnLCP || []; - } - window.raqnLCP = - window.raqnLCP || - lcp - .getAttribute('content') - .split(',') - .map((name) => ({ name })); + const lcp = document.querySelector('meta[name="lcp"]'); + if (!lcp) { + return window.raqnLCP || []; } + window.raqnLCP = + window.raqnLCP || + lcp + .getAttribute('content') + .split(',') + .map((name) => ({ name })); return window.raqnLCP; } export async function init(node = document) { let blocks = Array.from(node.querySelectorAll('[class]:not([class^=style]')); - const imgs = lcpPriority(); - console.log(imgs); if (node === document) { const header = node.querySelector('header'); @@ -95,4 +91,5 @@ export async function init(node = document) { } // mechanism of retrieving lang to be used in the app document.documentElement.lang = document.documentElement.lang || 'en'; +lcpPriority(); init(); From 6651fab8566bdac0b952693b26fea8358ae9801c Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Mon, 8 Jan 2024 17:13:34 +0100 Subject: [PATCH 08/54] Comparition --- scripts/init.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/init.js b/scripts/init.js index 360d910e..14775163 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -3,13 +3,13 @@ import { config, debounce, getBreakPoint } from './libs.js'; export const eagerImage = (block, length = 1) => { const imgs = Array.from(block.querySelectorAll('img')).slice(0, length); - return imgs.map((img) => { + console.log('eager', imgs, length); + imgs.forEach((img) => { const width = img.getAttribute('width'); const height = img.getAttribute('height'); const ratio = Math.floor((width / height) * 100) / 100; img.style.aspectRatio = ratio; img.setAttribute('loading', 'eager'); - return img; }); }; @@ -32,7 +32,7 @@ export function retriveDataFrom(blocks) { } function lcpPriority() { - const eagerImages = document.querySelector('meta[name="lcp"]'); + const eagerImages = document.querySelector('meta[name="eager"]'); if (eagerImages) { const length = parseInt(eagerImages.getAttribute('content'), 10); eagerImage(document.body, length); From 58aa66c59f3171d155166750cd4e1c6c5078ec06 Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Mon, 8 Jan 2024 20:09:35 +0100 Subject: [PATCH 09/54] Comparition --- scripts/init.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/init.js b/scripts/init.js index 14775163..4fee8acc 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -76,7 +76,7 @@ export async function init(node = document) { Promise.all( rest.map(({ name, el }) => setTimeout(() => start({ name, el }))), ); - }); + }, 100); // reload on breakpoint change window.raqnBreakpoint = getBreakPoint(); window.addEventListener( From 404d314cedf7c5dc6742ed8276f573aa07d96ab1 Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 10:17:26 +0100 Subject: [PATCH 10/54] await --- scripts/init.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/init.js b/scripts/init.js index 4fee8acc..fd2e36d2 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -68,15 +68,15 @@ export async function init(node = document) { const loader = new ComponentLoader(name, el); return loader.decorate(); }; - Promise.all([ + await Promise.all([ ...lcp.map(({ name, el }) => start({ name, el })), ...prio.map(({ name, el }) => start({ name, el })), ]); - setTimeout(() => { - Promise.all( - rest.map(({ name, el }) => setTimeout(() => start({ name, el }))), - ); - }, 100); + + await Promise.all( + rest.map(({ name, el }) => setTimeout(() => start({ name, el }))), + ); + // reload on breakpoint change window.raqnBreakpoint = getBreakPoint(); window.addEventListener( From 84ae1119b8aadcb92c3006bac5daf38915f166aa Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 10:18:36 +0100 Subject: [PATCH 11/54] await --- scripts/init.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/scripts/init.js b/scripts/init.js index fd2e36d2..50d6826c 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -62,19 +62,14 @@ export async function init(node = document) { const data = retriveDataFrom(blocks); const lcp = window.raqnLCP; - const prio = data.slice(0, 2); - const rest = data.slice(2); const start = ({ name, el }) => { const loader = new ComponentLoader(name, el); return loader.decorate(); }; - await Promise.all([ - ...lcp.map(({ name, el }) => start({ name, el })), - ...prio.map(({ name, el }) => start({ name, el })), - ]); + await Promise.all([...lcp.map(({ name, el }) => start({ name, el }))]); await Promise.all( - rest.map(({ name, el }) => setTimeout(() => start({ name, el }))), + data.map(({ name, el }) => setTimeout(() => start({ name, el }))), ); // reload on breakpoint change From 62b73674d1c8f30a25cabbaecd32786620856b7a Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 10:21:42 +0100 Subject: [PATCH 12/54] await --- scripts/init.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/init.js b/scripts/init.js index 50d6826c..fb398f3e 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -66,9 +66,10 @@ export async function init(node = document) { const loader = new ComponentLoader(name, el); return loader.decorate(); }; - await Promise.all([...lcp.map(({ name, el }) => start({ name, el }))]); - await Promise.all( + Promise.all([...lcp.map(({ name, el }) => start({ name, el }))]); + + window.addEventListener('load', () => data.map(({ name, el }) => setTimeout(() => start({ name, el }))), ); From bb09e58f9acb02cfbbb9d3096360f13660cfedcd Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 10:27:13 +0100 Subject: [PATCH 13/54] #414986 > using on load --- head.html | 1 + 1 file changed, 1 insertion(+) diff --git a/head.html b/head.html index 6f07eff5..a475a5e1 100644 --- a/head.html +++ b/head.html @@ -6,6 +6,7 @@ as="fetch" crossorigin="anonymous" /> + From 4f8f3ace36aba0d79392ed5d78202b87cfb5a4fc Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 10:42:20 +0100 Subject: [PATCH 14/54] #414986 > using on load --- scripts/init.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/init.js b/scripts/init.js index fb398f3e..febacaaf 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -1,6 +1,8 @@ import ComponentLoader from './component-loader.js'; import { config, debounce, getBreakPoint } from './libs.js'; +export let loaded = false; + export const eagerImage = (block, length = 1) => { const imgs = Array.from(block.querySelectorAll('img')).slice(0, length); console.log('eager', imgs, length); @@ -69,9 +71,10 @@ export async function init(node = document) { Promise.all([...lcp.map(({ name, el }) => start({ name, el }))]); - window.addEventListener('load', () => - data.map(({ name, el }) => setTimeout(() => start({ name, el }))), - ); + window.addEventListener('load', () => { + loaded = true; + return data.map(({ name, el }) => setTimeout(() => start({ name, el }))); + }); // reload on breakpoint change window.raqnBreakpoint = getBreakPoint(); From d19e0f5702248a2f01ca28a126f6e7fbb665df82 Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 10:42:46 +0100 Subject: [PATCH 15/54] #414986 > using on load --- scripts/init.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/init.js b/scripts/init.js index febacaaf..f1388028 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -71,10 +71,14 @@ export async function init(node = document) { Promise.all([...lcp.map(({ name, el }) => start({ name, el }))]); - window.addEventListener('load', () => { - loaded = true; - return data.map(({ name, el }) => setTimeout(() => start({ name, el }))); - }); + if (!loaded) { + window.addEventListener('load', () => { + loaded = true; + return data.map(({ name, el }) => setTimeout(() => start({ name, el }))); + }); + } else { + data.map(({ name, el }) => setTimeout(() => start({ name, el }))); + } // reload on breakpoint change window.raqnBreakpoint = getBreakPoint(); From 9354d46044247a1f65b04cdec02af0ad44bceee9 Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 10:44:04 +0100 Subject: [PATCH 16/54] #414986 > using on load --- scripts/init.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/init.js b/scripts/init.js index f1388028..75d001fa 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -64,20 +64,22 @@ export async function init(node = document) { const data = retriveDataFrom(blocks); const lcp = window.raqnLCP; + const priority = data.filter(({ name }) => lcp.includes(name)); + const rest = data.filter(({ name }) => !lcp.includes(name)); const start = ({ name, el }) => { const loader = new ComponentLoader(name, el); return loader.decorate(); }; - Promise.all([...lcp.map(({ name, el }) => start({ name, el }))]); + Promise.all([...lcp.map(({ name, el }) => start({ name, el })), ...priority]); if (!loaded) { window.addEventListener('load', () => { loaded = true; - return data.map(({ name, el }) => setTimeout(() => start({ name, el }))); + return rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); }); } else { - data.map(({ name, el }) => setTimeout(() => start({ name, el }))); + rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); } // reload on breakpoint change From 6212bf17ecc4470fc7e7fb945cdda096b956806e Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 10:50:29 +0100 Subject: [PATCH 17/54] #414986 > using on load --- scripts/init.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/init.js b/scripts/init.js index 75d001fa..eaa9481c 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -71,7 +71,10 @@ export async function init(node = document) { return loader.decorate(); }; - Promise.all([...lcp.map(({ name, el }) => start({ name, el })), ...priority]); + await Promise.all([ + ...lcp.map(({ name, el }) => start({ name, el })), + ...priority, + ]); if (!loaded) { window.addEventListener('load', () => { @@ -79,7 +82,7 @@ export async function init(node = document) { return rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); }); } else { - rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); + await rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); } // reload on breakpoint change From 08a995093d01717e53109541b30ceb299fa27bc6 Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 10:51:25 +0100 Subject: [PATCH 18/54] #414986 > using on load --- scripts/init.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/init.js b/scripts/init.js index eaa9481c..e7c1a617 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -73,7 +73,7 @@ export async function init(node = document) { await Promise.all([ ...lcp.map(({ name, el }) => start({ name, el })), - ...priority, + ...priority.map(({ name, el }) => start({ name, el })), ]); if (!loaded) { @@ -82,7 +82,7 @@ export async function init(node = document) { return rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); }); } else { - await rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); + rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); } // reload on breakpoint change From 0f1c5b7339f77c7eae029870f7557545d817b3e5 Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 10:52:07 +0100 Subject: [PATCH 19/54] #414986 > using on load --- scripts/init.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/init.js b/scripts/init.js index e7c1a617..0b56747a 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -76,14 +76,14 @@ export async function init(node = document) { ...priority.map(({ name, el }) => start({ name, el })), ]); - if (!loaded) { - window.addEventListener('load', () => { - loaded = true; - return rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); - }); - } else { - rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); - } + // if (!loaded) { + // window.addEventListener('load', () => { + // loaded = true; + // return rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); + // }); + // } else { + rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); + // } // reload on breakpoint change window.raqnBreakpoint = getBreakPoint(); From d0fd0c5b974489d4d5767d9d48e6b61f16ee7efb Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 10:55:52 +0100 Subject: [PATCH 20/54] #414986 > using on load --- scripts/init.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/init.js b/scripts/init.js index 0b56747a..7ba05fed 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -71,7 +71,7 @@ export async function init(node = document) { return loader.decorate(); }; - await Promise.all([ + Promise.all([ ...lcp.map(({ name, el }) => start({ name, el })), ...priority.map(({ name, el }) => start({ name, el })), ]); From d4ccf4f182c7251aedfc0165e4e493f0cc901fc9 Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 11:11:26 +0100 Subject: [PATCH 21/54] #414986 > await and on load --- scripts/init.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/init.js b/scripts/init.js index 7ba05fed..e7c1a617 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -71,19 +71,19 @@ export async function init(node = document) { return loader.decorate(); }; - Promise.all([ + await Promise.all([ ...lcp.map(({ name, el }) => start({ name, el })), ...priority.map(({ name, el }) => start({ name, el })), ]); - // if (!loaded) { - // window.addEventListener('load', () => { - // loaded = true; - // return rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); - // }); - // } else { - rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); - // } + if (!loaded) { + window.addEventListener('load', () => { + loaded = true; + return rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); + }); + } else { + rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); + } // reload on breakpoint change window.raqnBreakpoint = getBreakPoint(); From 8ccea5ba4f8eaecbfa3fb5e168500fcf0f7161c7 Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 11:12:49 +0100 Subject: [PATCH 22/54] #414986 > await and on load --- scripts/init.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/scripts/init.js b/scripts/init.js index e7c1a617..c3c829c5 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -71,17 +71,19 @@ export async function init(node = document) { return loader.decorate(); }; + window.addEventListener('load', () => { + if (!loaded) { + loaded = true; + rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); + } + }); + await Promise.all([ ...lcp.map(({ name, el }) => start({ name, el })), ...priority.map(({ name, el }) => start({ name, el })), ]); - if (!loaded) { - window.addEventListener('load', () => { - loaded = true; - return rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); - }); - } else { + if (loaded) { rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); } From 057c6f16ed4edddbd9f2fceffdd5c703b7cb55a0 Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 12:18:03 +0100 Subject: [PATCH 23/54] #414986 > regular loading --- docs/edge/client.md | 68 +++++++++++++++++++++++++++++++++++++++++---- scripts/init.js | 8 +++--- 2 files changed, 67 insertions(+), 9 deletions(-) diff --git a/docs/edge/client.md b/docs/edge/client.md index b2d3fbd2..a031a6d9 100644 --- a/docs/edge/client.md +++ b/docs/edge/client.md @@ -1,15 +1,73 @@ -# Everything else as client side javascript +# Everything as client side javascript + +As mentioned and for what is rendered at serverside. + +Things that can be done without javascript: + +1. Style basic html set on the page. +2. Predefine sizes on LCP (althout even the header is not available SSR) +3. Set the scripts to and things to preload + +Most features depends on javascript to transform dom and hidratate it. + +1. load and priorize resorces that are not in head.html +2. inicially hide body +3. parse dom +4. compile rendering blocking styles and javascripts +5. Load header.plain.html +6. load other non eager components + +The only server side injection available is by head.html. Requirements - Clientside Hidratation dom transformation "decoration" - Manual focus on FCP and LCP -- blocking resources before render +- queue and blocking each resources before loading and render next Boiler plate approach -1. Performance +1. Performance by avoiding visible rendering before loading required 2. Decoration by feature -3. Manualy defining priority +3. Manualy defining priority of required 4. Eager and defered -5. Semantical content used as component functional content (metadata) +5. Semantical content used as component functional content (metadata) among others + +## Defining blocks and features + +### Default script behavior - Non block features + +1. Setup SampleRun +2. Eager loading + 1. decorateTemplateAndTheme (Required once, add classes to body) + 2. Load external header, add css variables using metadata (required to avoid CLS and must be defined used styles.css) + 3. decorateMain (Required once, but need to run always that a new dom is loaded or added) includes: + 1. decorate buttons, icons, blocks, Section, Images, grid. + 4. if desktop loads fonts +3. Lazy and delayed 4. Load blocks (by order of apearance) 5. Load footer and decorate it manually 6. Load fonts 7. Load lazy styles 8. Observe for delayed etcs + +### Block features + +A example of a block + +```javascript +export default async function decorate(block) { + // add feature to a element (block) + // Eg add events transform it etcs +} +``` + +Here is some examples: +(Example HEADER)[https://github.com/adobe/aem-boilerplate/blob/main/blocks/header/header.js] + +Advances: +1 - Simple to add events etcs +2 - Functional approch good for testing +3 - usign modules allow importing from other libraries + +Disavantages +1 - Blocks need to be executed manually in every element +2 - Any new dom needs be decorated manually +3 - Limited reusability of a "component" +4 - Too opniated, easy allows bad code +5 - no clear life cicle of a block diff --git a/scripts/init.js b/scripts/init.js index c3c829c5..cd4a6888 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -78,14 +78,14 @@ export async function init(node = document) { } }); - await Promise.all([ + // start with lcp and priority + Promise.all([ ...lcp.map(({ name, el }) => start({ name, el })), ...priority.map(({ name, el }) => start({ name, el })), ]); - if (loaded) { - rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); - } + // timeout for the rest to proper prioritize in case of stalled loading + rest.map(({ name, el }) => setTimeout(() => start({ name, el })), 10); // reload on breakpoint change window.raqnBreakpoint = getBreakPoint(); From 95443f164ccfda26ac587dff832dfb8e18a1ea2f Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 12:18:17 +0100 Subject: [PATCH 24/54] #414986 > regular loading --- scripts/init.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/scripts/init.js b/scripts/init.js index cd4a6888..d9163ae1 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -71,13 +71,6 @@ export async function init(node = document) { return loader.decorate(); }; - window.addEventListener('load', () => { - if (!loaded) { - loaded = true; - rest.map(({ name, el }) => setTimeout(() => start({ name, el }))); - } - }); - // start with lcp and priority Promise.all([ ...lcp.map(({ name, el }) => start({ name, el })), From 282e29ba9d8a29ca1cb201e1a90f7a070991313d Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 12:52:05 +0100 Subject: [PATCH 25/54] #414986 > regular loading --- docs/edge/client.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/edge/client.md b/docs/edge/client.md index a031a6d9..68e0b76b 100644 --- a/docs/edge/client.md +++ b/docs/edge/client.md @@ -61,7 +61,7 @@ Here is some examples: (Example HEADER)[https://github.com/adobe/aem-boilerplate/blob/main/blocks/header/header.js] Advances: -1 - Simple to add events etcs +1 - Simple 2 - Functional approch good for testing 3 - usign modules allow importing from other libraries @@ -69,5 +69,6 @@ Disavantages 1 - Blocks need to be executed manually in every element 2 - Any new dom needs be decorated manually 3 - Limited reusability of a "component" -4 - Too opniated, easy allows bad code -5 - no clear life cicle of a block +4 - Too opniated allows to free style coding / no code best practices enforcing +5 - No clear life cicle of a block +6 - Uses semantical data as parameters and passing options From 8031bdf663a09b7f6d6b7fbf1c4ecf20d0239700 Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 12:54:18 +0100 Subject: [PATCH 26/54] #414986 > regular loading --- head.html | 1 - 1 file changed, 1 deletion(-) diff --git a/head.html b/head.html index a475a5e1..6f07eff5 100644 --- a/head.html +++ b/head.html @@ -6,7 +6,6 @@ as="fetch" crossorigin="anonymous" /> - From 786698a7c748adbadbed69932c466ab9520e0617 Mon Sep 17 00:00:00 2001 From: Felipe Simoes Date: Tue, 9 Jan 2024 16:24:06 +0100 Subject: [PATCH 27/54] #414986 > docs --- blocks/navigation/navigation.js | 2 +- scripts/component-base.js | 14 +- scripts/component-loader.js | 14 - scripts/init.js | 25 +- scripts/lib-franklin.js | 825 -------------------------------- scripts/scripts.js | 162 ------- 6 files changed, 9 insertions(+), 1033 deletions(-) delete mode 100644 scripts/lib-franklin.js delete mode 100644 scripts/scripts.js diff --git a/blocks/navigation/navigation.js b/blocks/navigation/navigation.js index 210e2651..25e93704 100644 --- a/blocks/navigation/navigation.js +++ b/blocks/navigation/navigation.js @@ -17,7 +17,7 @@ export default class Navigation extends Column { return button; } - render() { + ready() { this.list = this.querySelector('ul'); this.nav = document.createElement('nav'); this.nav.append(this.list); diff --git a/scripts/component-base.js b/scripts/component-base.js index 31e73567..bab81dc0 100644 --- a/scripts/component-base.js +++ b/scripts/component-base.js @@ -1,16 +1,6 @@ import { init } from './init.js'; export default class ComponentBase extends HTMLElement { - static get breakpoints() { - return { - S: 0, - M: 768, - L: 1024, - XL: 1280, - XXL: 1920, - }; - } - constructor() { super(); this.external = false; @@ -23,7 +13,7 @@ export default class ComponentBase extends HTMLElement { await this.load(this.external); } this.connected(); - this.render(); + this.ready(); } async load(block) { @@ -45,5 +35,5 @@ export default class ComponentBase extends HTMLElement { connected() {} - render() {} + ready() {} } diff --git a/scripts/component-loader.js b/scripts/component-loader.js index 22c40390..4f69659c 100644 --- a/scripts/component-loader.js +++ b/scripts/component-loader.js @@ -12,10 +12,6 @@ export default class ComponentLoader { } } - /** - * Loads a CSS file. - * @param {string} href URL to the CSS file - */ async loadCSS(href) { return new Promise((resolve, reject) => { if (!document.querySelector(`head > link[href="${href}"]`)) { @@ -31,9 +27,6 @@ export default class ComponentLoader { }); } - /** - * Parse extra params from classList - */ setParams() { const mediaParams = {}; this.params = { @@ -66,13 +59,6 @@ export default class ComponentLoader { }; } - /** - * Set the configuration for the given block, and also passes - * the config through all custom patching helpers added to the project. - * - * @param {Element} block The block element - * @returns {Object} The block config (blockName, cssPath and jsPath) - */ setBlockPaths() { this.cssPath = `/blocks/${this.blockName}/${this.blockName}.css`; this.jsPath = `/blocks/${this.blockName}/${this.blockName}.js`; diff --git a/scripts/init.js b/scripts/init.js index d9163ae1..23cba9bc 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -1,21 +1,7 @@ import ComponentLoader from './component-loader.js'; -import { config, debounce, getBreakPoint } from './libs.js'; +import { config, debounce, eagerImage, getBreakPoint } from './libs.js'; -export let loaded = false; - -export const eagerImage = (block, length = 1) => { - const imgs = Array.from(block.querySelectorAll('img')).slice(0, length); - console.log('eager', imgs, length); - imgs.forEach((img) => { - const width = img.getAttribute('width'); - const height = img.getAttribute('height'); - const ratio = Math.floor((width / height) * 100) / 100; - img.style.aspectRatio = ratio; - img.setAttribute('loading', 'eager'); - }); -}; - -export function retriveDataFrom(blocks) { +export function getInfos(blocks) { return blocks.map((block) => { let el = block; const tagName = el.tagName.toLowerCase(); @@ -23,6 +9,7 @@ export function retriveDataFrom(blocks) { if (!config.elementBlocks.includes(tagName)) { [name] = Array.from(el.classList); } else { + // allow original way of defining blocks el = document.createElement('div'); block.append(el); } @@ -62,7 +49,7 @@ export async function init(node = document) { blocks = [header, ...blocks, footer]; } - const data = retriveDataFrom(blocks); + const data = getInfos(blocks); const lcp = window.raqnLCP; const priority = data.filter(({ name }) => lcp.includes(name)); const rest = data.filter(({ name }) => !lcp.includes(name)); @@ -80,12 +67,12 @@ export async function init(node = document) { // timeout for the rest to proper prioritize in case of stalled loading rest.map(({ name, el }) => setTimeout(() => start({ name, el })), 10); - // reload on breakpoint change + // reload on breakpoint change to reset params and variables window.raqnBreakpoint = getBreakPoint(); window.addEventListener( 'resize', debounce(() => { - // only on width changes + // only on width / breakpoint changes if (window.raqnBreakpoint !== getBreakPoint()) { window.location.reload(); } diff --git a/scripts/lib-franklin.js b/scripts/lib-franklin.js deleted file mode 100644 index d365f1bd..00000000 --- a/scripts/lib-franklin.js +++ /dev/null @@ -1,825 +0,0 @@ -/* - * Copyright 2022 Adobe. All rights reserved. - * This file is licensed to you under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - * OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - */ - -/** - * log RUM if part of the sample. - * @param {string} checkpoint identifies the checkpoint in funnel - * @param {Object} data additional data for RUM sample - */ -export function sampleRUM(checkpoint, data = {}) { - sampleRUM.defer = sampleRUM.defer || []; - const defer = (fnname) => { - sampleRUM[fnname] = sampleRUM[fnname] - || ((...args) => sampleRUM.defer.push({ fnname, args })); - }; - sampleRUM.drain = sampleRUM.drain - || ((dfnname, fn) => { - sampleRUM[dfnname] = fn; - sampleRUM.defer - .filter(({ fnname }) => dfnname === fnname) - .forEach(({ fnname, args }) => sampleRUM[fnname](...args)); - }); - sampleRUM.always = sampleRUM.always || []; - sampleRUM.always.on = (chkpnt, fn) => { - sampleRUM.always[chkpnt] = fn; - }; - sampleRUM.on = (chkpnt, fn) => { - sampleRUM.cases[chkpnt] = fn; - }; - defer('observe'); - defer('cwv'); - try { - window.hlx = window.hlx || {}; - if (!window.hlx.rum) { - const usp = new URLSearchParams(window.location.search); - const weight = usp.get('rum') === 'on' ? 1 : 100; // with parameter, weight is 1. Defaults to 100. - // eslint-disable-next-line no-bitwise - const hashCode = (s) => s.split('').reduce((a, b) => ((a << 5) - a + b.charCodeAt(0)) | 0, 0); - const id = `${hashCode( - window.location.href, - )}-${new Date().getTime()}-${Math.random().toString(16).substr(2, 14)}`; - const random = Math.random(); - const isSelected = random * weight < 1; - const urlSanitizers = { - full: () => window.location.href, - origin: () => window.location.origin, - path: () => window.location.href.replace(/\?.*$/, ''), - }; - // eslint-disable-next-line object-curly-newline, max-len - window.hlx.rum = { - weight, - id, - random, - isSelected, - sampleRUM, - sanitizeURL: urlSanitizers[window.hlx.RUM_MASK_URL || 'path'], - }; - } - const { weight, id } = window.hlx.rum; - if (window.hlx && window.hlx.rum && window.hlx.rum.isSelected) { - const sendPing = (pdata = data) => { - // eslint-disable-next-line object-curly-newline, max-len, no-use-before-define - const body = JSON.stringify({ - weight, - id, - referer: window.hlx.rum.sanitizeURL(), - checkpoint, - ...data, - }); - const url = `https://rum.hlx.page/.rum/${weight}`; - // eslint-disable-next-line no-unused-expressions - navigator.sendBeacon(url, body); - // eslint-disable-next-line no-console - console.debug(`ping:${checkpoint}`, pdata); - }; - sampleRUM.cases = sampleRUM.cases || { - cwv: () => sampleRUM.cwv(data) || true, - lazy: () => { - // use classic script to avoid CORS issues - const script = document.createElement('script'); - script.src = 'https://rum.hlx.page/.rum/@adobe/helix-rum-enhancer@^1/src/index.js'; - document.head.appendChild(script); - return true; - }, - }; - sendPing(data); - if (sampleRUM.cases[checkpoint]) { - sampleRUM.cases[checkpoint](); - } - } - if (sampleRUM.always[checkpoint]) { - sampleRUM.always[checkpoint](data); - } - } catch (error) { - // something went wrong - } -} - -/** - * Loads a CSS file. - * @param {string} href URL to the CSS file - */ -export async function loadCSS(href) { - return new Promise((resolve, reject) => { - if (!document.querySelector(`head > link[href="${href}"]`)) { - const link = document.createElement('link'); - link.rel = 'stylesheet'; - link.href = href; - link.onload = resolve; - link.onerror = reject; - document.head.append(link); - } else { - resolve(); - } - }); -} - -/** - * Loads a non module JS file. - * @param {string} src URL to the JS file - * @param {Object} attrs additional optional attributes - */ - -export async function loadScript(src, attrs) { - return new Promise((resolve, reject) => { - if (!document.querySelector(`head > script[src="${src}"]`)) { - const script = document.createElement('script'); - script.src = src; - if (attrs) { - // eslint-disable-next-line no-restricted-syntax, guard-for-in - for (const attr in attrs) { - script.setAttribute(attr, attrs[attr]); - } - } - script.onload = resolve; - script.onerror = reject; - document.head.append(script); - } else { - resolve(); - } - }); -} - -/** - * Retrieves the content of metadata tags. - * @param {string} name The metadata name (or property) - * @returns {string} The metadata value(s) - */ -export function getMetadata(name) { - const attr = name && name.includes(':') ? 'property' : 'name'; - const meta = [...document.head.querySelectorAll(`meta[${attr}="${name}"]`)] - .map((m) => m.content) - .join(', '); - return meta || ''; -} - -/** - * Sanitizes a string for use as class name. - * @param {string} name The unsanitized string - * @returns {string} The class name - */ -export function toClassName(name) { - return typeof name === 'string' - ? name - .toLowerCase() - .replace(/[^0-9a-z]/gi, '-') - .replace(/-+/g, '-') - .replace(/^-|-$/g, '') - : ''; -} - -/** - * Sanitizes a string for use as a js property name. - * @param {string} name The unsanitized string - * @returns {string} The camelCased name - */ -export function toCamelCase(name) { - return toClassName(name).replace(/-([a-z])/g, (g) => g[1].toUpperCase()); -} - -const ICONS_CACHE = {}; -/** - * Replace icons with inline SVG and prefix with codeBasePath. - * @param {Element} [element] Element containing icons - */ -export async function decorateIcons(element) { - // Prepare the inline sprite - let svgSprite = document.getElementById('franklin-svg-sprite'); - if (!svgSprite) { - const div = document.createElement('div'); - div.innerHTML = ''; - svgSprite = div.firstElementChild; - document.body.append(div.firstElementChild); - } - - // Download all new icons - const icons = [...element.querySelectorAll('span.icon')]; - await Promise.all( - icons.map(async (span) => { - const iconName = Array.from(span.classList) - .find((c) => c.startsWith('icon-')) - .substring(5); - if (!ICONS_CACHE[iconName]) { - ICONS_CACHE[iconName] = true; - try { - const response = await fetch( - `${window.hlx.iconsPath}/${iconName}.svg`, - ); - if (!response.ok) { - ICONS_CACHE[iconName] = false; - return; - } - // Styled icons don't play nice with the sprite approach because of shadow dom isolation - // and same for internal references - const svg = await response.text(); - if (svg.match(/(