@merkur/integration 0.37.11 → 0.39.0

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <p align="center">
2
2
  <a href="https://merkur.js.org/docs/getting-started" title="Getting started">
3
- <img src="https://raw.githubusercontent.com/mjancarik/merkur/master/images/merkur-illustration.png" width="100px" height="100px" alt="Merkur illustration"/>
3
+ <img src="https://raw.githubusercontent.com/mjancarik/merkur/master/images/merkur-logo.png" width="100px" height="100px" alt="Merkur illustration"/>
4
4
  </a>
5
5
  </p>
6
6
 
package/lib/index.cjs CHANGED
@@ -3,86 +3,60 @@
3
3
  let _isES9Supported;
4
4
  let _isES11Supported;
5
5
  let _isES13Supported;
6
-
7
6
  function isES9Supported() {
8
7
  if (_isES9Supported === undefined) {
9
- _isES9Supported =
10
- exported.test(
11
- 'return (() => { const o = { t: 1 }; return { ...o }; })() && (async () => ({}))()',
12
- ) && !!Object.values;
8
+ _isES9Supported = exported.test('return (() => { const o = { t: 1 }; return { ...o }; })() && (async () => ({}))()') && !!Object.values;
13
9
  }
14
-
15
10
  return _isES9Supported;
16
11
  }
17
-
18
12
  function isES11Supported() {
19
13
  if (_isES11Supported === undefined) {
20
- _isES11Supported =
21
- exported.test(
22
- 'return (() => { const o = { t: { q: true } }; return o?.t?.q && (o?.a?.q ?? true); })()',
23
- ) &&
24
- exported.test('return typeof Promise.allSettled === "function"') &&
25
- exported.test('return typeof globalThis !== "undefined"') &&
26
- exported.test('return typeof 9007199254740991n === "bigint"');
14
+ _isES11Supported = exported.test('return (() => { const o = { t: { q: true } }; return o?.t?.q && (o?.a?.q ?? true); })()') && exported.test('return typeof Promise.allSettled === "function"') && exported.test('return typeof globalThis !== "undefined"') && exported.test('return typeof 9007199254740991n === "bigint"');
27
15
  }
28
-
29
16
  return _isES11Supported;
30
17
  }
31
-
32
18
  function isES13Supported() {
33
19
  if (_isES13Supported === undefined) {
34
- _isES13Supported =
35
- exported.test('return [1,1].findLast(e => e === 1)') &&
36
- exported.test('return Object.hasOwn({a:1}, "a")');
20
+ _isES13Supported = exported.test('return [1,1].findLast(e => e === 1)') && exported.test('return Object.hasOwn({a:1}, "a")');
37
21
  }
38
-
39
22
  return _isES13Supported;
40
23
  }
41
-
42
24
  function test(snippet) {
43
25
  try {
44
26
  const fn = new Function(snippet);
45
27
  const result = fn();
46
-
47
28
  return !!result;
48
29
  } catch (e) {
49
30
  return false;
50
31
  }
51
32
  }
52
-
53
33
  const exported = {
54
34
  isES9Supported,
55
35
  isES11Supported,
56
36
  isES13Supported,
57
- test,
37
+ test
58
38
  };
59
39
 
60
40
  const isLoadedSymbol = Symbol.for('isLoaded');
61
41
  const loadingPromiseSymbol = Symbol.for('loadingPromise');
62
-
63
42
  function _attachElementToAsset(asset, element) {
64
43
  return {
65
44
  ...asset,
66
- element,
45
+ element
67
46
  };
68
47
  }
69
-
70
48
  function _handleAssetError({
71
49
  asset,
72
- message = `Error loading asset ${asset.source}.`,
50
+ message = `Error loading asset ${asset.source}.`
73
51
  }) {
74
52
  if (asset.optional) {
75
53
  console.warn(message);
76
-
77
54
  return _attachElementToAsset(asset, null);
78
55
  }
79
-
80
56
  const error = new Error(message);
81
57
  error.asset = asset;
82
-
83
58
  throw error;
84
59
  }
85
-
86
60
  function _addListenersToAssetElement(asset, element, resolve, reject) {
87
61
  element.addEventListener('load', () => {
88
62
  resolve(_attachElementToAsset(asset, element));
@@ -93,116 +67,94 @@ function _addListenersToAssetElement(asset, element, resolve, reject) {
93
67
  if (element.parentNode) {
94
68
  element.remove();
95
69
  }
96
-
97
70
  try {
98
- resolve(_handleAssetError({ asset }));
71
+ resolve(_handleAssetError({
72
+ asset
73
+ }));
99
74
  } catch (error) {
100
75
  reject(error);
101
76
  }
102
77
  });
103
78
  }
104
-
105
79
  function _loadStyle(asset, root) {
106
80
  if (asset.type === 'inlineStyle') {
107
81
  const style = document.createElement('style');
82
+ style.dataset.merkurAssetName = asset.name;
108
83
  style.innerHTML = asset.source;
109
84
  root.appendChild(style);
110
-
111
85
  return _attachElementToAsset(asset, style);
112
86
  }
113
-
114
87
  const link = document.createElement('link');
115
-
116
88
  link[loadingPromiseSymbol] = new Promise((resolve, reject) => {
117
89
  _addListenersToAssetElement(asset, link, resolve, reject);
118
90
  link.rel = 'stylesheet';
91
+ link.dataset.merkurAssetName = asset.name;
119
92
  link.href = asset.source;
120
-
121
93
  root.appendChild(link);
122
94
  });
123
-
124
95
  return link[loadingPromiseSymbol];
125
96
  }
126
-
127
97
  async function loadStyleAssets(assets, root = document.head) {
128
98
  const styleElements = Array.from(root.querySelectorAll('style'));
129
-
130
- return Promise.all(
131
- assets.map((asset) => {
132
- if (
133
- !['stylesheet', 'inlineStyle'].includes(asset.type) ||
134
- !asset.source
135
- ) {
136
- return _attachElementToAsset(asset, null);
137
- }
138
-
139
- if (asset.type === 'stylesheet') {
140
- const link = root.querySelector(`link[href='${asset.source}']`);
141
-
142
- if (link) {
143
- if (link[loadingPromiseSymbol]) {
144
- return link[loadingPromiseSymbol];
145
- }
146
-
147
- return _attachElementToAsset(asset, link);
99
+ return Promise.all(assets.map(asset => {
100
+ if (!['stylesheet', 'inlineStyle'].includes(asset.type) || !asset.source) {
101
+ return _attachElementToAsset(asset, null);
102
+ }
103
+ if (asset.type === 'stylesheet') {
104
+ const link = root.querySelector(`link[href='${asset.source}']`);
105
+ if (link) {
106
+ if (link[loadingPromiseSymbol]) {
107
+ return link[loadingPromiseSymbol];
148
108
  }
109
+ return _attachElementToAsset(asset, link);
149
110
  }
150
-
151
- if (asset.type === 'inlineStyle') {
152
- const inlineStyle = styleElements.find(
153
- (element) => element.innerHTML === asset.source,
154
- );
155
-
156
- if (inlineStyle) {
157
- return _attachElementToAsset(asset, inlineStyle);
158
- }
111
+ }
112
+ if (asset.type === 'inlineStyle') {
113
+ const inlineStyle = styleElements.find(element => element.innerHTML === asset.source);
114
+ if (inlineStyle) {
115
+ return _attachElementToAsset(asset, inlineStyle);
159
116
  }
160
-
161
- return _loadStyle(asset, root);
162
- }),
163
- );
117
+ }
118
+ return _loadStyle(asset, root);
119
+ }));
164
120
  }
165
-
166
121
  function _findScriptElement(scriptElements, asset) {
167
122
  if (asset.type === 'json') {
168
- return scriptElements.find(
169
- (element) => element.dataset.src === asset.source,
170
- );
123
+ return scriptElements.find(element => element.dataset.src === asset.source);
171
124
  }
172
-
173
125
  if (!['script', 'inlineScript', 'inlineJson'].includes(asset.type)) {
174
126
  return null;
175
127
  }
176
-
177
128
  const attributeKey = asset.type === 'script' ? 'src' : 'textContent';
178
- const source =
179
- asset.type === 'inlineJson' ? JSON.stringify(asset.source) : asset.source;
180
-
181
- return (
182
- scriptElements.find((element) => element[attributeKey] === source) || null
183
- );
129
+ const source = asset.type === 'inlineJson' ? JSON.stringify(asset.source) : asset.source;
130
+ return scriptElements.find(element => element[attributeKey] === source) || null;
184
131
  }
185
-
186
132
  function _loadScript(asset, root) {
187
133
  const script = document.createElement('script');
134
+ script.dataset.merkurAssetName = asset.name;
188
135
 
136
+ // Set script type to module if specified
137
+ if (asset.module) {
138
+ script.type = 'module';
139
+ }
189
140
  if (asset.type === 'inlineScript') {
190
141
  script.textContent = asset.source;
191
142
  root.appendChild(script);
192
-
193
143
  return _attachElementToAsset(asset, script);
194
144
  }
195
-
196
145
  script[loadingPromiseSymbol] = new Promise((resolve, reject) => {
197
- script.defer = true;
146
+ // Don't set defer for module scripts as it can interfere with module loading
147
+ if (!asset.module) {
148
+ script.defer = true;
149
+ }
198
150
  _addListenersToAssetElement(asset, script, resolve, reject);
199
151
  script.src = asset.source;
200
-
201
- const { attr } = asset;
152
+ const {
153
+ attr
154
+ } = asset;
202
155
  if (attr && Object.keys(attr).length) {
203
156
  for (const name in attr) {
204
157
  const value = attr[name];
205
-
206
158
  if (typeof value === 'boolean') {
207
159
  if (value) {
208
160
  script.setAttribute(name, '');
@@ -214,86 +166,73 @@ function _loadScript(asset, root) {
214
166
  }
215
167
  }
216
168
  }
217
-
218
169
  root.appendChild(script);
219
170
  });
220
-
221
171
  return script[loadingPromiseSymbol];
222
172
  }
223
-
224
173
  async function loadScriptAssets(assets, root = document.head) {
225
174
  const scriptElements = Array.from(root.querySelectorAll('script'));
175
+ return Promise.all(assets.map(asset => {
176
+ if (!['script', 'inlineScript'].includes(asset.type) || !asset.source) {
177
+ return _attachElementToAsset(asset, null);
178
+ }
226
179
 
227
- return Promise.all(
228
- assets.map((asset) => {
229
- if (!['script', 'inlineScript'].includes(asset.type) || !asset.source) {
230
- return _attachElementToAsset(asset, null);
231
- }
232
-
233
- const { source } = asset;
234
- const _asset = Object.assign({}, asset);
235
-
236
- if (source === Object(source)) {
237
- if (source.es13 && exported.isES13Supported()) {
238
- _asset.source = source.es13;
239
- } else if (source.es11 && exported.isES11Supported()) {
240
- _asset.source = source.es11;
241
- } else if (source.es9 && exported.isES9Supported()) {
242
- _asset.source = source.es9;
243
- } else {
244
- _asset.source = null;
245
- }
246
-
247
- if (!_asset.source) {
248
- return _handleAssetError({
249
- asset: _asset,
250
- message: `Asset '${_asset.name}' is missing ES variant and could not be loaded.`,
251
- });
180
+ // Module scripts should not use defer attribute as it can cause issues
181
+ if (asset.module && asset.attr && asset.attr.defer !== false) {
182
+ asset = {
183
+ ...asset,
184
+ attr: {
185
+ ...asset.attr,
186
+ defer: false
252
187
  }
188
+ };
189
+ }
190
+ const {
191
+ source
192
+ } = asset;
193
+ const _asset = Object.assign({}, asset);
194
+ if (source === Object(source)) {
195
+ if (source.es13 && exported.isES13Supported()) {
196
+ _asset.source = source.es13;
197
+ } else if (source.es11 && exported.isES11Supported()) {
198
+ _asset.source = source.es11;
199
+ } else if (source.es9 && exported.isES9Supported()) {
200
+ _asset.source = source.es9;
201
+ } else {
202
+ _asset.source = null;
253
203
  }
254
-
255
- if (_asset.test && exported.test(_asset.test)) {
256
- return _attachElementToAsset(
257
- _asset,
258
- _findScriptElement(scriptElements, _asset),
259
- );
204
+ if (!_asset.source) {
205
+ return _handleAssetError({
206
+ asset: _asset,
207
+ message: `Asset '${_asset.name}' is missing ES variant and could not be loaded.`
208
+ });
260
209
  }
261
-
262
- const script = _findScriptElement(scriptElements, _asset);
263
-
264
- if (script && _asset.type === 'script') {
265
- if (script[loadingPromiseSymbol]) {
266
- return script[loadingPromiseSymbol];
267
- }
268
-
269
- if (script[isLoadedSymbol]) {
270
- return _attachElementToAsset(_asset, script);
271
- }
272
-
273
- return new Promise((resolve, reject) =>
274
- _addListenersToAssetElement(_asset, script, resolve, reject),
275
- );
276
- } else if (script && _asset.type === 'inlineScript') {
210
+ }
211
+ if (_asset.test && exported.test(_asset.test)) {
212
+ return _attachElementToAsset(_asset, _findScriptElement(scriptElements, _asset));
213
+ }
214
+ const script = _findScriptElement(scriptElements, _asset);
215
+ if (script && _asset.type === 'script') {
216
+ if (script[loadingPromiseSymbol]) {
217
+ return script[loadingPromiseSymbol];
218
+ }
219
+ if (script[isLoadedSymbol]) {
277
220
  return _attachElementToAsset(_asset, script);
278
221
  }
279
-
280
- return _loadScript(_asset, root);
281
- }),
282
- );
222
+ return new Promise((resolve, reject) => _addListenersToAssetElement(_asset, script, resolve, reject));
223
+ } else if (script && _asset.type === 'inlineScript') {
224
+ return _attachElementToAsset(_asset, script);
225
+ }
226
+ return _loadScript(_asset, root);
227
+ }));
283
228
  }
284
-
285
229
  async function _fetchData(source) {
286
230
  const response = await fetch(source);
287
-
288
231
  if (!response.ok) {
289
- throw new Error(
290
- `Failed to fetch from '${source}' with status ${response.status} ${response.statusText}.`,
291
- );
232
+ throw new Error(`Failed to fetch from '${source}' with status ${response.status} ${response.statusText}.`);
292
233
  }
293
-
294
234
  return response.text();
295
235
  }
296
-
297
236
  function _removeElementAfterTimeout(element, timeout) {
298
237
  if (timeout) {
299
238
  setTimeout(() => {
@@ -303,23 +242,19 @@ function _removeElementAfterTimeout(element, timeout) {
303
242
  }, timeout);
304
243
  }
305
244
  }
306
-
307
245
  function _loadJsonAsset(asset, root) {
308
246
  const script = document.createElement('script');
247
+ script.dataset.merkurAssetName = asset.name;
309
248
  script.type = 'application/json';
310
-
311
249
  if (asset.type === 'inlineJson') {
312
250
  script.textContent = JSON.stringify(asset.source);
313
251
  root.appendChild(script);
314
252
  _removeElementAfterTimeout(script, asset.ttl);
315
-
316
253
  return _attachElementToAsset(asset, script);
317
254
  }
318
-
319
255
  script[loadingPromiseSymbol] = new Promise((resolve, reject) => {
320
256
  script.dataset.src = asset.source;
321
257
  root.appendChild(script);
322
-
323
258
  (async () => {
324
259
  try {
325
260
  const textContent = await _fetchData(asset.source);
@@ -329,57 +264,41 @@ function _loadJsonAsset(asset, root) {
329
264
  resolve(_attachElementToAsset(asset, script));
330
265
  } catch (error) {
331
266
  script.remove();
332
-
333
267
  try {
334
- resolve(
335
- _handleAssetError({
336
- asset,
337
- message: `Error loading JSON asset '${asset.name}': ${error.message}`,
338
- }),
339
- );
268
+ resolve(_handleAssetError({
269
+ asset,
270
+ message: `Error loading JSON asset '${asset.name}': ${error.message}`
271
+ }));
340
272
  } catch (error) {
341
273
  reject(error);
342
274
  }
343
275
  }
344
276
  })();
345
277
  });
346
-
347
278
  return script[loadingPromiseSymbol];
348
279
  }
349
-
350
280
  async function loadJsonAssets(assets, root = document.head) {
351
- const scriptElements = Array.from(
352
- root.querySelectorAll('script[type="application/json"]'),
353
- );
354
-
355
- return Promise.all(
356
- assets.map((asset) => {
357
- if (!['json', 'inlineJson'].includes(asset.type) || !asset.source) {
358
- return _attachElementToAsset(asset, null);
281
+ const scriptElements = Array.from(root.querySelectorAll('script[type="application/json"]'));
282
+ return Promise.all(assets.map(asset => {
283
+ if (!['json', 'inlineJson'].includes(asset.type) || !asset.source) {
284
+ return _attachElementToAsset(asset, null);
285
+ }
286
+ const script = _findScriptElement(scriptElements, asset);
287
+ if (script) {
288
+ if (script[loadingPromiseSymbol]) {
289
+ return script[loadingPromiseSymbol];
359
290
  }
360
-
361
- const script = _findScriptElement(scriptElements, asset);
362
-
363
- if (script) {
364
- if (script[loadingPromiseSymbol]) {
365
- return script[loadingPromiseSymbol];
366
- }
367
-
368
- if (script.textContent) {
369
- return _attachElementToAsset(asset, script);
370
- }
371
-
372
- return _handleAssetError({
373
- asset,
374
- message: `JSON asset '${asset.name}' is missing textContent and could not be loaded.`,
375
- });
291
+ if (script.textContent) {
292
+ return _attachElementToAsset(asset, script);
376
293
  }
377
-
378
- return _loadJsonAsset(asset, root);
379
- }),
380
- );
294
+ return _handleAssetError({
295
+ asset,
296
+ message: `JSON asset '${asset.name}' is missing textContent and could not be loaded.`
297
+ });
298
+ }
299
+ return _loadJsonAsset(asset, root);
300
+ }));
381
301
  }
382
-
383
302
  function _mergeResults(results) {
384
303
  return results.reduce((acc, results) => {
385
304
  results.forEach((result, index) => {
@@ -389,18 +308,11 @@ function _mergeResults(results) {
389
308
  acc[index] = result;
390
309
  }
391
310
  });
392
-
393
311
  return acc;
394
312
  }, []);
395
313
  }
396
-
397
314
  async function loadAssets(assets, root) {
398
- const results = await Promise.all([
399
- loadScriptAssets(assets, root),
400
- loadStyleAssets(assets, root),
401
- loadJsonAssets(assets, root),
402
- ]);
403
-
315
+ const results = await Promise.all([loadScriptAssets(assets, root), loadStyleAssets(assets, root), loadJsonAssets(assets, root)]);
404
316
  return _mergeResults(results);
405
317
  }
406
318
 
package/lib/index.es9.cjs CHANGED
@@ -78,6 +78,7 @@ function _addListenersToAssetElement(asset, element, resolve, reject) {
78
78
  function _loadStyle(asset, root) {
79
79
  if (asset.type === 'inlineStyle') {
80
80
  const style = document.createElement('style');
81
+ style.dataset.merkurAssetName = asset.name;
81
82
  style.innerHTML = asset.source;
82
83
  root.appendChild(style);
83
84
  return _attachElementToAsset(asset, style);
@@ -86,6 +87,7 @@ function _loadStyle(asset, root) {
86
87
  link[loadingPromiseSymbol] = new Promise((resolve, reject) => {
87
88
  _addListenersToAssetElement(asset, link, resolve, reject);
88
89
  link.rel = 'stylesheet';
90
+ link.dataset.merkurAssetName = asset.name;
89
91
  link.href = asset.source;
90
92
  root.appendChild(link);
91
93
  });
@@ -128,13 +130,22 @@ function _findScriptElement(scriptElements, asset) {
128
130
  }
129
131
  function _loadScript(asset, root) {
130
132
  const script = document.createElement('script');
133
+ script.dataset.merkurAssetName = asset.name;
134
+
135
+ // Set script type to module if specified
136
+ if (asset.module) {
137
+ script.type = 'module';
138
+ }
131
139
  if (asset.type === 'inlineScript') {
132
140
  script.textContent = asset.source;
133
141
  root.appendChild(script);
134
142
  return _attachElementToAsset(asset, script);
135
143
  }
136
144
  script[loadingPromiseSymbol] = new Promise((resolve, reject) => {
137
- script.defer = true;
145
+ // Don't set defer for module scripts as it can interfere with module loading
146
+ if (!asset.module) {
147
+ script.defer = true;
148
+ }
138
149
  _addListenersToAssetElement(asset, script, resolve, reject);
139
150
  script.src = asset.source;
140
151
  const {
@@ -164,6 +175,17 @@ async function loadScriptAssets(assets, root = document.head) {
164
175
  if (!['script', 'inlineScript'].includes(asset.type) || !asset.source) {
165
176
  return _attachElementToAsset(asset, null);
166
177
  }
178
+
179
+ // Module scripts should not use defer attribute as it can cause issues
180
+ if (asset.module && asset.attr && asset.attr.defer !== false) {
181
+ asset = {
182
+ ...asset,
183
+ attr: {
184
+ ...asset.attr,
185
+ defer: false
186
+ }
187
+ };
188
+ }
167
189
  const {
168
190
  source
169
191
  } = asset;
@@ -221,6 +243,7 @@ function _removeElementAfterTimeout(element, timeout) {
221
243
  }
222
244
  function _loadJsonAsset(asset, root) {
223
245
  const script = document.createElement('script');
246
+ script.dataset.merkurAssetName = asset.name;
224
247
  script.type = 'application/json';
225
248
  if (asset.type === 'inlineJson') {
226
249
  script.textContent = JSON.stringify(asset.source);
package/lib/index.es9.mjs CHANGED
@@ -76,6 +76,7 @@ function _addListenersToAssetElement(asset, element, resolve, reject) {
76
76
  function _loadStyle(asset, root) {
77
77
  if (asset.type === 'inlineStyle') {
78
78
  const style = document.createElement('style');
79
+ style.dataset.merkurAssetName = asset.name;
79
80
  style.innerHTML = asset.source;
80
81
  root.appendChild(style);
81
82
  return _attachElementToAsset(asset, style);
@@ -84,6 +85,7 @@ function _loadStyle(asset, root) {
84
85
  link[loadingPromiseSymbol] = new Promise((resolve, reject) => {
85
86
  _addListenersToAssetElement(asset, link, resolve, reject);
86
87
  link.rel = 'stylesheet';
88
+ link.dataset.merkurAssetName = asset.name;
87
89
  link.href = asset.source;
88
90
  root.appendChild(link);
89
91
  });
@@ -126,13 +128,22 @@ function _findScriptElement(scriptElements, asset) {
126
128
  }
127
129
  function _loadScript(asset, root) {
128
130
  const script = document.createElement('script');
131
+ script.dataset.merkurAssetName = asset.name;
132
+
133
+ // Set script type to module if specified
134
+ if (asset.module) {
135
+ script.type = 'module';
136
+ }
129
137
  if (asset.type === 'inlineScript') {
130
138
  script.textContent = asset.source;
131
139
  root.appendChild(script);
132
140
  return _attachElementToAsset(asset, script);
133
141
  }
134
142
  script[loadingPromiseSymbol] = new Promise((resolve, reject) => {
135
- script.defer = true;
143
+ // Don't set defer for module scripts as it can interfere with module loading
144
+ if (!asset.module) {
145
+ script.defer = true;
146
+ }
136
147
  _addListenersToAssetElement(asset, script, resolve, reject);
137
148
  script.src = asset.source;
138
149
  const {
@@ -162,6 +173,17 @@ async function loadScriptAssets(assets, root = document.head) {
162
173
  if (!['script', 'inlineScript'].includes(asset.type) || !asset.source) {
163
174
  return _attachElementToAsset(asset, null);
164
175
  }
176
+
177
+ // Module scripts should not use defer attribute as it can cause issues
178
+ if (asset.module && asset.attr && asset.attr.defer !== false) {
179
+ asset = {
180
+ ...asset,
181
+ attr: {
182
+ ...asset.attr,
183
+ defer: false
184
+ }
185
+ };
186
+ }
165
187
  const {
166
188
  source
167
189
  } = asset;
@@ -219,6 +241,7 @@ function _removeElementAfterTimeout(element, timeout) {
219
241
  }
220
242
  function _loadJsonAsset(asset, root) {
221
243
  const script = document.createElement('script');
244
+ script.dataset.merkurAssetName = asset.name;
222
245
  script.type = 'application/json';
223
246
  if (asset.type === 'inlineJson') {
224
247
  script.textContent = JSON.stringify(asset.source);