Skip to content

Commit cb23d46

Browse files
committed
Add experimentation plugin and metadata helpers
Enable experimentation support: update ESLint ignores to include plugins/, add a sidekick plugin config (tools/sidekick/config.json) and a small sidekick script (scripts/sidekick.js) to toggle the external DA experiment module. Add getAllMetadata helper (scripts/shared.js) to collect scoped metadata, introduce AUDIENCES and an experimentation context in scripts/scripts.js, and dynamically load the plugin's eager/lazy entry points when experimentation metadata or sidekick is present. Also wire sidekick import/sidekick-ready handling and adjust DA preview/experiment import logic.
1 parent 0785c0a commit cb23d46

File tree

5 files changed

+100
-3
lines changed

5 files changed

+100
-3
lines changed

eslint.config.cjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const js = require('@eslint/js');
22
const globals = require('globals');
33

44
module.exports = [
5-
{ ignores: ['helix-importer-ui/**', 'tools/**', '.skills/**', '**/*.min.js', '.eslintrc.js', 'eslint.config.cjs'] },
5+
{ ignores: ['helix-importer-ui/**', 'tools/**', '.skills/**', '**/*.min.js', '.eslintrc.js', 'eslint.config.cjs', 'plugins/**'] },
66
js.configs.recommended,
77
{
88
languageOptions: {

scripts/scripts.js

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,31 @@ import {
1212
loadSection,
1313
sampleRUM,
1414
loadCSS,
15+
loadScript,
1516
getMetadata,
17+
toCamelCase,
18+
toClassName,
1619
} from './aem.js';
20+
import { getAllMetadata } from './shared.js';
1721
import dynamicBlocks from '../blocks/dynamic/index.js';
1822

23+
const AUDIENCES = {
24+
mobile: () => window.innerWidth < 600,
25+
desktop: () => window.innerWidth >= 600,
26+
};
27+
28+
function getExperimentationContext() {
29+
return {
30+
getAllMetadata, getMetadata, loadCSS, loadScript, sampleRUM, toCamelCase, toClassName,
31+
};
32+
}
33+
34+
function isExperimentationEnabled() {
35+
return getMetadata('experiment')
36+
|| Object.keys(getAllMetadata('campaign')).length
37+
|| Object.keys(getAllMetadata('audience')).length;
38+
}
39+
1940
const THEME_STORAGE_KEY = 'diyfire-theme';
2041

2142
function applyTheme(theme) {
@@ -172,6 +193,10 @@ async function loadEager(doc) {
172193
const main = doc.querySelector('main');
173194
if (main) {
174195
if (window.isErrorPage) loadErrorPage(main);
196+
if (isExperimentationEnabled()) {
197+
const { loadEager: runEager } = await import('../plugins/experimentation/src/index.js');
198+
await runEager(document, { audiences: AUDIENCES }, getExperimentationContext());
199+
}
175200
decorateMain(main);
176201
document.body.classList.add('appear');
177202
await loadSection(main.querySelector('.section'), async (s) => {
@@ -229,6 +254,11 @@ async function loadLazy(doc) {
229254
loadCSS(`${window.hlx.codeBasePath}/styles/lazy-styles.css`);
230255
loadFonts();
231256

257+
if (isExperimentationEnabled()) {
258+
const { loadLazy: runLazy } = await import('../plugins/experimentation/src/index.js');
259+
await runLazy(document, { audiences: AUDIENCES }, getExperimentationContext());
260+
}
261+
232262
const loadQuickEdit = async (...args) => {
233263
const { default: initQuickEdit } = await import('../tools/quick-edit/quick-edit.js');
234264
initQuickEdit(...args);
@@ -279,10 +309,23 @@ if (!window.hlx?.suppressLoadPage) {
279309
loadPage();
280310

281311
(async function loadDa() {
282-
if (!new URL(window.location.href).searchParams.get('dapreview')) return;
283-
import('https://da.live/scripts/dapreview.js').then(({ default: daPreview }) => daPreview(loadPage));
312+
const { searchParams } = new URL(window.location.href);
313+
if (searchParams.get('dapreview')) {
314+
import('https://da.live/scripts/dapreview.js').then(({ default: daPreview }) => daPreview(loadPage));
315+
}
316+
if (searchParams.get('daexperiment')) {
317+
import('https://da.live/nx/public/plugins/exp/exp.js');
318+
}
284319
}());
285320

321+
if (document.querySelector('aem-sidekick')) {
322+
import('./sidekick.js');
323+
} else {
324+
document.addEventListener('sidekick-ready', () => {
325+
import('./sidekick.js');
326+
}, { once: true });
327+
}
328+
286329
window.addEventListener('aem-theme-change', (e) => {
287330
applyTheme(e.detail?.theme);
288331
});

scripts/shared.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,25 @@ export function createChart(canvas, config) {
260260
return chart;
261261
}
262262

263+
/**
264+
* Returns all metadata properties matching a given scope/prefix.
265+
* Looks for `<meta property="{scope}:…">` and `<meta name="{scope}-…">`.
266+
* @param {string} scope The metadata prefix (e.g. 'campaign', 'audience')
267+
* @param {Document} [doc=document] Document to query
268+
* @returns {Record<string, string>} Key-value pairs of matching metadata (keys in camelCase)
269+
*/
270+
export function getAllMetadata(scope, doc = document) {
271+
const result = {};
272+
const meta = [...doc.head.querySelectorAll(`meta[property^="${scope}:"], meta[name^="${scope}-"]`)];
273+
meta.forEach((m) => {
274+
const key = m.getAttribute('property')
275+
? m.getAttribute('property').replace(`${scope}:`, '')
276+
: m.getAttribute('name').replace(`${scope}-`, '');
277+
result[key.replace(/[-:]([a-z])/g, (g) => g[1].toUpperCase())] = m.content;
278+
});
279+
return result;
280+
}
281+
263282
/**
264283
* Check if the current page is in the Universal Editor.
265284
* @returns {boolean}

scripts/sidekick.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
let defined;
2+
3+
function toggleExp() {
4+
if (defined) {
5+
defined.remove();
6+
defined = undefined;
7+
return;
8+
}
9+
import('https://da.live/nx/public/plugins/exp/exp.js').then((mod) => {
10+
defined = mod;
11+
});
12+
}
13+
14+
const sk = document.querySelector('aem-sidekick');
15+
if (sk) {
16+
sk.addEventListener('custom:experimentation', toggleExp);
17+
} else {
18+
document.addEventListener('sidekick-ready', () => {
19+
document.querySelector('aem-sidekick')
20+
.addEventListener('custom:experimentation', toggleExp);
21+
}, { once: true });
22+
}

tools/sidekick/config.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"project": "DIYFire",
3+
"plugins": [
4+
{
5+
"id": "experimentation",
6+
"titleI18n": {
7+
"en": "Experimentation"
8+
},
9+
"environments": ["dev", "preview"],
10+
"event": "experimentation"
11+
}
12+
]
13+
}

0 commit comments

Comments
 (0)