@adobe/helix-rum-enhancer 2.31.0-beta.2 → 2.31.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,28 @@
1
+ # [2.31.0-beta.4](https://github.com/adobe/helix-rum-enhancer/compare/v2.31.0-beta.3...v2.31.0-beta.4) (2025-01-16)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * plugin path resolution ([f464652](https://github.com/adobe/helix-rum-enhancer/commit/f464652df5bef5f42e0b32c1f10bebef013dd1b0))
7
+
8
+ # [2.31.0-beta.3](https://github.com/adobe/helix-rum-enhancer/compare/v2.31.0-beta.2...v2.31.0-beta.3) (2025-01-16)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * bugs and failing tests ([5c9adbc](https://github.com/adobe/helix-rum-enhancer/commit/5c9adbc2502203495a05d4fd2be6e05cc11102df))
14
+ * cross-browser compatibility ([1c21afd](https://github.com/adobe/helix-rum-enhancer/commit/1c21afd8cd982d4c33feba863d2251311f36e153))
15
+ * set proper url base for plugins ([9726dc8](https://github.com/adobe/helix-rum-enhancer/commit/9726dc8f98bd71936c8a8f430cae73b6a8f5d63f))
16
+ * use proper fully qualified URLs for plugin path to avoid CORS ([c73eb31](https://github.com/adobe/helix-rum-enhancer/commit/c73eb31461115529922b82c3a8b678f21052b918))
17
+
18
+
19
+ ### Features
20
+
21
+ * allow external extension via window.RUM_PLUGINS ([4613b00](https://github.com/adobe/helix-rum-enhancer/commit/4613b004c617f4d503355b5c43008149df9101ef))
22
+ * inline web-vitals.js ([7d89e9f](https://github.com/adobe/helix-rum-enhancer/commit/7d89e9f664686d3a475ce829d7fb4f68f29ed71b))
23
+ * introduce minimal plugin system to offset non-essenial logic ([8642557](https://github.com/adobe/helix-rum-enhancer/commit/8642557beaef5161d1d4d51d2b04ce06bf7dbeb7))
24
+ * introduce minimal plugin system to offset non-essenial logic ([6066f0b](https://github.com/adobe/helix-rum-enhancer/commit/6066f0bd56393a10391e190b9a338f9a65b772b0))
25
+
1
26
  # [2.31.0-beta.2](https://github.com/adobe/helix-rum-enhancer/compare/v2.31.0-beta.1...v2.31.0-beta.2) (2025-01-16)
2
27
 
3
28
 
package/modules/index.js CHANGED
@@ -14,26 +14,66 @@
14
14
  import { KNOWN_PROPERTIES, DEFAULT_TRACKING_EVENTS } from './defaults.js';
15
15
  import { urlSanitizers } from './utils.js';
16
16
  import { targetSelector, sourceSelector } from './dom.js';
17
- import {
18
- addAdsParametersTracking,
19
- addCookieConsentTracking,
20
- addEmailParameterTracking,
21
- addUTMParametersTracking,
22
- } from './martech.js';
23
17
  import { fflags } from './fflags.js';
24
18
 
25
19
  const { sampleRUM, queue, isSelected } = (window.hlx && window.hlx.rum) ? window.hlx.rum
26
20
  /* c8 ignore next */ : {};
27
21
 
28
- // blocks mutation observer
29
- // eslint-disable-next-line no-use-before-define, max-len
30
- const blocksMO = window.MutationObserver ? new MutationObserver(blocksMCB)
31
- /* c8 ignore next */ : {};
22
+ const createMO = (cb) => (window.MutationObserver ? new MutationObserver(cb)
23
+ /* c8 ignore next */ : {});
32
24
 
33
- // media mutation observer
34
- // eslint-disable-next-line no-use-before-define, max-len
35
- const mediaMO = window.MutationObserver ? new MutationObserver(mediaMCB)
36
- /* c8 ignore next */ : {};
25
+ // blocks & media mutation observer
26
+ // eslint-disable-next-line no-use-before-define
27
+ const [blocksMO, mediaMO] = [blocksMCB, mediaMCB].map(createMO);
28
+
29
+ // Check for the presence of a given cookie
30
+ const hasCookieKey = (key) => () => document.cookie.split(';').some((c) => c.trim().startsWith(`${key}=`));
31
+
32
+ const pluginBasePath = new URL(document.currentScript.src).href.replace(/index(\.map)?\.js/, 'plugins');
33
+
34
+ const PLUGINS = {
35
+ cwv: `${pluginBasePath}/cwv.js`,
36
+ // Interactive elements
37
+ form: { url: `${pluginBasePath}/form.js`, condition: () => document.querySelector('form'), isBlockDependent: true },
38
+ video: { url: `${pluginBasePath}/video.js`, condition: () => document.querySelector('video'), isBlockDependent: true },
39
+ // Martech
40
+ martech: { url: `${pluginBasePath}/martech.js`, condition: ({ urlParameters }) => urlParameters.size > 0 },
41
+ onetrust: { url: `${pluginBasePath}/onetrust.js`, condition: () => (document.querySelector('#onetrust-consent-sdk') || hasCookieKey('OptanonAlertBoxClosed')), isBlockDependent: true },
42
+ };
43
+
44
+ const PLUGIN_PARAMETERS = {
45
+ context: document.body,
46
+ fflags,
47
+ sampleRUM,
48
+ sourceSelector,
49
+ targetSelector,
50
+ };
51
+
52
+ const pluginCache = new Map();
53
+
54
+ function loadPlugin(key, params) {
55
+ const plugin = PLUGINS[key];
56
+ const usp = new URLSearchParams(window.location.search);
57
+ if (!pluginCache.has(key) && plugin.condition && !plugin.condition({ urlParameters: usp })) {
58
+ return null;
59
+ }
60
+ if (!pluginCache.has(key)) {
61
+ try {
62
+ pluginCache.set(key, import(`${plugin.url || plugin}`));
63
+ } catch (e) {
64
+ return null;
65
+ }
66
+ }
67
+ const pluginLoadPromise = pluginCache.get(key);
68
+ return pluginLoadPromise
69
+ .then((p) => (p.default && p.default(params)) || (typeof p === 'function' && p(params)));
70
+ }
71
+
72
+ function loadPlugins(filter = () => true, params = PLUGIN_PARAMETERS) {
73
+ Object.entries(PLUGINS)
74
+ .filter(([, plugin]) => filter(plugin))
75
+ .map(([key]) => loadPlugin(key, params));
76
+ }
37
77
 
38
78
  function trackCheckpoint(checkpoint, data, t) {
39
79
  const { weight, id } = window.hlx.rum;
@@ -64,51 +104,6 @@ function processQueue() {
64
104
  }
65
105
  }
66
106
 
67
- function addCWVTracking() {
68
- setTimeout(() => {
69
- try {
70
- const cwvScript = new URL('.rum/web-vitals/dist/web-vitals.iife.js', sampleRUM.baseURL).href;
71
- if (document.querySelector(`script[src="${cwvScript}"]`)) {
72
- // web vitals script has been loaded already
73
- return;
74
- }
75
- const script = document.createElement('script');
76
- script.src = cwvScript;
77
- script.onload = () => {
78
- const storeCWV = (measurement) => {
79
- const data = { cwv: {} };
80
- data.cwv[measurement.name] = measurement.value;
81
- if (measurement.name === 'LCP' && measurement.entries.length > 0) {
82
- const { element } = measurement.entries.pop();
83
- data.target = targetSelector(element);
84
- data.source = sourceSelector(element) || (element && element.outerHTML.slice(0, 30));
85
- }
86
- sampleRUM('cwv', data);
87
- };
88
-
89
- const isEager = (metric) => ['CLS', 'LCP'].includes(metric);
90
-
91
- // When loading `web-vitals` using a classic script, all the public
92
- // methods can be found on the `webVitals` global namespace.
93
- ['INP', 'TTFB', 'CLS', 'LCP'].forEach((metric) => {
94
- const metricFn = window.webVitals[`on${metric}`];
95
- if (typeof metricFn === 'function') {
96
- let opts = {};
97
- fflags.enabled('eagercwv', () => {
98
- opts = { reportAllChanges: isEager(metric) };
99
- });
100
- metricFn(storeCWV, opts);
101
- }
102
- });
103
- };
104
- document.head.appendChild(script);
105
- /* c8 ignore next 3 */
106
- } catch (error) {
107
- // something went wrong
108
- }
109
- }, 2000); // wait for delayed
110
- }
111
-
112
107
  function addNavigationTracking() {
113
108
  // enter checkpoint when referrer is not the current page url
114
109
  const navigate = (source, type, redirectCount) => {
@@ -210,8 +205,6 @@ function getIntersectionObsever(checkpoint) {
210
205
  if (!window.IntersectionObserver) {
211
206
  return null;
212
207
  }
213
- activateBlocksMO();
214
- activateMediaMO();
215
208
  const observer = new IntersectionObserver((entries) => {
216
209
  try {
217
210
  entries
@@ -250,28 +243,6 @@ function addViewMediaTracking(parent) {
250
243
  }
251
244
  }
252
245
 
253
- function addFormTracking(parent) {
254
- activateBlocksMO();
255
- activateMediaMO();
256
- parent.querySelectorAll('form').forEach((form) => {
257
- form.addEventListener('submit', (e) => sampleRUM('formsubmit', { target: targetSelector(e.target), source: sourceSelector(e.target) }), { once: true });
258
- let lastSource;
259
- form.addEventListener('change', (e) => {
260
- const source = sourceSelector(e.target);
261
- if (source !== lastSource) {
262
- sampleRUM('fill', { source });
263
- lastSource = source;
264
- }
265
- });
266
- form.addEventListener('focusin', (e) => {
267
- if (['INPUT', 'TEXTAREA', 'SELECT', 'BUTTON'].includes(e.target.tagName)
268
- || e.target.getAttribute('contenteditable') === 'true') {
269
- sampleRUM('click', { source: sourceSelector(e.target) });
270
- }
271
- });
272
- });
273
- }
274
-
275
246
  function addObserver(ck, fn, block) {
276
247
  return DEFAULT_TRACKING_EVENTS.includes(ck) && fn(block);
277
248
  }
@@ -283,7 +254,7 @@ function blocksMCB(mutations) {
283
254
  .filter((m) => m.type === 'attributes' && m.attributeName === 'data-block-status')
284
255
  .filter((m) => m.target.dataset.blockStatus === 'loaded')
285
256
  .forEach((m) => {
286
- addObserver('form', addFormTracking, m.target);
257
+ addObserver('form', (el) => loadPlugins((p) => p.isBlockDependent, { ...PLUGIN_PARAMETERS, context: el }), m.target);
287
258
  addObserver('viewblock', addViewBlockTracking, m.target);
288
259
  });
289
260
  }
@@ -298,6 +269,9 @@ function mediaMCB(mutations) {
298
269
  }
299
270
 
300
271
  function addTrackingFromConfig() {
272
+ activateBlocksMO();
273
+ activateMediaMO();
274
+
301
275
  let lastSource;
302
276
  let lastTarget;
303
277
  document.addEventListener('click', (event) => {
@@ -309,16 +283,16 @@ function addTrackingFromConfig() {
309
283
  lastTarget = target;
310
284
  }
311
285
  });
312
- addCWVTracking();
313
- addFormTracking(window.document.body);
286
+
287
+ // Core tracking
314
288
  addNavigationTracking();
315
289
  addLoadResourceTracking();
316
- addUTMParametersTracking(sampleRUM);
317
- addViewBlockTracking(window.document.body);
318
- addViewMediaTracking(window.document.body);
319
- addCookieConsentTracking(sampleRUM);
320
- addAdsParametersTracking(sampleRUM);
321
- addEmailParameterTracking(sampleRUM);
290
+ addViewBlockTracking(document.body);
291
+ addViewMediaTracking(document.body);
292
+
293
+ // Tracking extensions
294
+ loadPlugins();
295
+
322
296
  fflags.enabled('language', () => {
323
297
  const target = navigator.language;
324
298
  const source = document.documentElement.lang;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/helix-rum-enhancer",
3
- "version": "2.31.0-beta.2",
3
+ "version": "2.31.0-beta.4",
4
4
  "description": "Helix RUM Enhancer",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -36,6 +36,7 @@
36
36
  "@adobe/eslint-config-helix": "2.0.8",
37
37
  "@adobe/helix-rum-js": "2.10.0",
38
38
  "@esm-bundle/chai": "4.3.4-fix.0",
39
+ "@rollup/plugin-babel": "6.0.4",
39
40
  "@semantic-release/changelog": "6.0.3",
40
41
  "@semantic-release/git": "10.0.1",
41
42
  "@semantic-release/npm": "12.0.1",
@@ -57,7 +58,6 @@
57
58
  "mocha-multi-reporters": "1.5.1",
58
59
  "rollup": "4.30.1",
59
60
  "rollup-plugin-checksum": "1.0.1",
60
- "rollup-plugin-cleanup": "3.2.1",
61
61
  "rollup-plugin-eslint-bundle": "9.0.0",
62
62
  "semantic-release": "24.2.1",
63
63
  "semantic-release-slack-bot": "^4.0.2",
package/plugins/cwv.js ADDED
@@ -0,0 +1,61 @@
1
+ /*
2
+ * Copyright 2024 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ // eslint-disable-next-line max-len
13
+ // eslint-disable-next-line import/no-extraneous-dependencies, import/no-relative-packages, no-unused-vars
14
+ import * as webVitals from '../node_modules/web-vitals/dist/web-vitals.iife.js';
15
+
16
+ export default function addCWVTracking({
17
+ sampleRUM, sourceSelector, targetSelector, fflags,
18
+ }) {
19
+ setTimeout(() => {
20
+ try {
21
+ const cwvScript = new URL('.rum/web-vitals/dist/web-vitals.iife.js', sampleRUM.baseURL).href;
22
+ if (document.querySelector(`script[src="${cwvScript}"]`)) {
23
+ // web vitals script has been loaded already
24
+ return;
25
+ }
26
+ const script = document.createElement('script');
27
+ script.src = cwvScript;
28
+ script.onload = () => {
29
+ const storeCWV = (measurement) => {
30
+ const data = { cwv: {} };
31
+ data.cwv[measurement.name] = measurement.value;
32
+ if (measurement.name === 'LCP' && measurement.entries.length > 0) {
33
+ const { element } = measurement.entries.pop();
34
+ data.target = targetSelector(element);
35
+ data.source = sourceSelector(element) || (element && element.outerHTML.slice(0, 30));
36
+ }
37
+ sampleRUM('cwv', data);
38
+ };
39
+
40
+ const isEager = (metric) => ['CLS', 'LCP'].includes(metric);
41
+
42
+ // When loading `web-vitals` using a classic script, all the public
43
+ // methods can be found on the `webVitals` global namespace.
44
+ ['INP', 'TTFB', 'CLS', 'LCP'].forEach((metric) => {
45
+ const metricFn = window.webVitals[`on${metric}`];
46
+ if (typeof metricFn === 'function') {
47
+ let opts = {};
48
+ fflags.enabled('eagercwv', () => {
49
+ opts = { reportAllChanges: isEager(metric) };
50
+ });
51
+ metricFn(storeCWV, opts);
52
+ }
53
+ });
54
+ };
55
+ document.head.appendChild(script);
56
+ /* c8 ignore next 3 */
57
+ } catch (error) {
58
+ // something went wrong
59
+ }
60
+ }, 2000); // wait for delayed
61
+ }
@@ -0,0 +1,32 @@
1
+ /*
2
+ * Copyright 2024 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ export default function addFormTracking({
13
+ sampleRUM, sourceSelector, targetSelector, context,
14
+ }) {
15
+ context.querySelectorAll('form').forEach((form) => {
16
+ form.addEventListener('submit', (e) => sampleRUM('formsubmit', { target: targetSelector(e.target), source: sourceSelector(e.target) }), { once: true });
17
+ let lastSource;
18
+ form.addEventListener('change', (e) => {
19
+ const source = sourceSelector(e.target);
20
+ if (source !== lastSource) {
21
+ sampleRUM('fill', { source });
22
+ lastSource = source;
23
+ }
24
+ });
25
+ form.addEventListener('focusin', (e) => {
26
+ if (['INPUT', 'TEXTAREA', 'SELECT', 'BUTTON'].includes(e.target.tagName)
27
+ || e.target.getAttribute('contenteditable') === 'true') {
28
+ sampleRUM('click', { source: sourceSelector(e.target) });
29
+ }
30
+ });
31
+ });
32
+ }
@@ -0,0 +1,54 @@
1
+ /*
2
+ * Copyright 2024 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ function addAdsParametersTracking(usp, { sampleRUM }) {
13
+ const networks = {
14
+ google: /gclid|gclsrc|wbraid|gbraid/,
15
+ doubleclick: /dclid/,
16
+ microsoft: /msclkid/,
17
+ facebook: /fb(cl|ad_|pxl_)id/,
18
+ twitter: /tw(clid|src|term)/,
19
+ linkedin: /li_fat_id/,
20
+ pinterest: /epik/,
21
+ tiktok: /ttclid/,
22
+ };
23
+ const params = Array.from(usp.keys());
24
+ Object.entries(networks).forEach(([network, regex]) => {
25
+ params.filter((param) => regex.test(param)).forEach((param) => sampleRUM('paid', { source: network, target: param }));
26
+ });
27
+ }
28
+
29
+ function addEmailParameterTracking(usp, { sampleRUM }) {
30
+ const networks = {
31
+ mailchimp: /mc_(c|e)id/,
32
+ marketo: /mkt_tok/,
33
+ };
34
+ const params = Array.from(usp.keys());
35
+ Object.entries(networks).forEach(([network, regex]) => {
36
+ params.filter((param) => regex.test(param)).forEach((param) => sampleRUM('email', { source: network, target: param }));
37
+ });
38
+ }
39
+
40
+ function addUTMParametersTracking(usp, { sampleRUM }) {
41
+ Array.from(usp.entries())
42
+ .filter(([key]) => key.startsWith('utm_'))
43
+ // exclude keys that may leak PII
44
+ .filter(([key]) => key !== 'utm_id')
45
+ .filter(([key]) => key !== 'utm_term')
46
+ .forEach(([source, target]) => sampleRUM('utm', { source, target }));
47
+ }
48
+
49
+ export default function addMartechTraking({ sampleRUM }) {
50
+ const usp = new URLSearchParams(window.location.search);
51
+ addAdsParametersTracking(usp, { sampleRUM });
52
+ addEmailParameterTracking(usp, { sampleRUM });
53
+ addUTMParametersTracking(usp, { sampleRUM });
54
+ }
@@ -9,7 +9,7 @@
9
9
  * OF ANY KIND, either express or implied. See the License for the specific language
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
- export function addCookieConsentTracking(sampleRUM) {
12
+ export default function addCookieConsentTracking({ sampleRUM }) {
13
13
  const cmpCookie = document.cookie.split(';')
14
14
  .map((c) => c.trim())
15
15
  .find((cookie) => cookie.startsWith('OptanonAlertBoxClosed='));
@@ -50,39 +50,3 @@ export function addCookieConsentTracking(sampleRUM) {
50
50
  }
51
51
  }
52
52
  }
53
-
54
- export function addUTMParametersTracking(sampleRUM) {
55
- const usp = new URLSearchParams(window.location.search);
56
- [...usp.entries()]
57
- .filter(([key]) => key.startsWith('utm_'))
58
- // exclude keys that may leak PII
59
- .filter(([key]) => key !== 'utm_id')
60
- .filter(([key]) => key !== 'utm_term')
61
- .forEach(([source, target]) => sampleRUM('utm', { source, target }));
62
- }
63
- export function addAdsParametersTracking(sampleRUM) {
64
- const networks = {
65
- google: /gclid|gclsrc|wbraid|gbraid/,
66
- doubleclick: /dclid/,
67
- microsoft: /msclkid/,
68
- facebook: /fb(cl|ad_|pxl_)id/,
69
- twitter: /tw(clid|src|term)/,
70
- linkedin: /li_fat_id/,
71
- pinterest: /epik/,
72
- tiktok: /ttclid/,
73
- };
74
- const params = Array.from(new URLSearchParams(window.location.search).keys());
75
- Object.entries(networks).forEach(([network, regex]) => {
76
- params.filter((param) => regex.test(param)).forEach((param) => sampleRUM('paid', { source: network, target: param }));
77
- });
78
- }
79
- export function addEmailParameterTracking(sampleRUM) {
80
- const networks = {
81
- mailchimp: /mc_(c|e)id/,
82
- marketo: /mkt_tok/,
83
- };
84
- const params = Array.from(new URLSearchParams(window.location.search).keys());
85
- Object.entries(networks).forEach(([network, regex]) => {
86
- params.filter((param) => regex.test(param)).forEach((param) => sampleRUM('email', { source: network, target: param }));
87
- });
88
- }
@@ -0,0 +1,17 @@
1
+ /*
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ export default function addVideoTracking({ context }) {
14
+ context.querySelectorAll('video').forEach(() => {
15
+ // TODO: Add video tracking
16
+ });
17
+ }
package/rollup.config.js CHANGED
@@ -10,7 +10,8 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- import cleanup from 'rollup-plugin-cleanup';
13
+ // eslint-disable-next-line import/no-extraneous-dependencies
14
+ import { babel } from '@rollup/plugin-babel';
14
15
  import pkg from 'rollup-plugin-checksum';
15
16
 
16
17
  const checksum = pkg.default;
@@ -28,10 +29,16 @@ const banner = `/*
28
29
  */`;
29
30
 
30
31
  const bundles = [
32
+ // Core library
31
33
  {
32
34
  source: 'modules/index.js',
33
35
  outputFile: 'src/index',
34
36
  },
37
+ // Library plugins
38
+ ...['cwv', 'form', 'martech', 'onetrust', 'video'].map((plugin) => ({
39
+ source: `plugins/${plugin}.js`,
40
+ outputFile: `src/plugins/${plugin}`,
41
+ })),
35
42
  ];
36
43
 
37
44
  export default [...bundles.map(({ outputFile, source }) => ({
@@ -53,9 +60,9 @@ export default [...bundles.map(({ outputFile, source }) => ({
53
60
  },
54
61
  ],
55
62
  plugins: [
56
- cleanup({
57
- comments: [],
58
- maxEmptyLines: 0,
63
+ babel({
64
+ babelHelpers: 'bundled',
65
+ comments: false,
59
66
  }),
60
67
  checksum({
61
68
  filename: `${outputFile.split('/').pop()}.md5`,