bee-ladybug 0.6.2 → 0.6.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bee-ladybug",
3
- "version": "0.6.2",
3
+ "version": "0.6.4",
4
4
  "description": "Universal telemetry and visual inspection overlay for Canvas, DOM, Python and AI flows.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -189,6 +189,7 @@ function isBeeChrome(node) {
189
189
  if (tag === 'BEE-LADYBUG-OVERLAY') return true;
190
190
  if (el.hasAttribute?.('data-bee-ladybug-dom')) return true;
191
191
  if (el.hasAttribute?.('data-bee-ladybug-canvas')) return true;
192
+ if (el.hasAttribute?.('data-bee-ladybug-css')) return true;
192
193
  el = el.parentElement;
193
194
  }
194
195
  return false;
@@ -61,9 +61,13 @@ export class CSSAdapter {
61
61
  this.#hoverBox = null;
62
62
  this.#pinBox = null;
63
63
  this.#observer = null;
64
+ this.#unsubscribe = null;
65
+ this.#hasPointer = false;
64
66
  this.#onMove = (event) => {
67
+ if (this.core && this.core.visible === false) return;
65
68
  this.#x = event.clientX;
66
69
  this.#y = event.clientY;
70
+ this.#hasPointer = true;
67
71
  this.#schedule();
68
72
  };
69
73
  this.#onKey = (event) => this.#handleKey(event);
@@ -71,7 +75,7 @@ export class CSSAdapter {
71
75
  this.#onMutate = (records) => {
72
76
  if (!records.some(touchesSheet)) return;
73
77
  this.#sheetsDirty = true;
74
- this.#schedule();
78
+ if (this.#hasPointer) this.#schedule();
75
79
  };
76
80
  }
77
81
 
@@ -92,6 +96,9 @@ export class CSSAdapter {
92
96
  #hoverBox;
93
97
  #pinBox;
94
98
  #observer;
99
+ #unsubscribe;
100
+ /** True after the first mousemove: before that (x, y) is not a real pointer. */
101
+ #hasPointer;
95
102
  #onMove;
96
103
  #onKey;
97
104
  #onScroll;
@@ -104,6 +111,9 @@ export class CSSAdapter {
104
111
  attach() {
105
112
  if (this.#attached) return this;
106
113
  this.#attached = true;
114
+ if (this.core && typeof this.core.subscribe === 'function') {
115
+ this.#unsubscribe = this.core.subscribe((packet) => this.#onCore(packet));
116
+ }
107
117
  this.core?.registerAdapter('css', {
108
118
  label: this.label,
109
119
  hotkey: this.hotkey,
@@ -128,10 +138,21 @@ export class CSSAdapter {
128
138
  if (!this.#attached) return this;
129
139
  this.#disable();
130
140
  this.#attached = false;
141
+ if (this.#unsubscribe) this.#unsubscribe();
142
+ this.#unsubscribe = null;
131
143
  this.core?.unregisterAdapter('css');
132
144
  return this;
133
145
  }
134
146
 
147
+ #onCore(packet) {
148
+ if (packet.type !== 'sys' || packet.payload?.op !== 'visibility') return;
149
+ this.#placeBoxes();
150
+ }
151
+
152
+ #boxesVisible() {
153
+ return !(this.core && this.core.visible === false);
154
+ }
155
+
135
156
  /** Page scan. Click a row to outline one element of that group. */
136
157
  scan() {
137
158
  if (!this.#active || typeof document === 'undefined') return this;
@@ -141,15 +162,15 @@ export class CSSAdapter {
141
162
  const rows = [];
142
163
  for (let i = 0; i < nodes.length; i++) {
143
164
  const el = nodes[i];
144
- if (!el || isBeeChrome(el) || isSkippedTag(el)) continue;
165
+ if (!el || isBeeChrome(el) || isSkippedTag(el) || isReportNoise(el)) continue;
145
166
  const measured = measureViewportOverflow(el);
146
167
  if (measured) overflow.push(measured);
147
168
  const findings = [];
148
169
  pushNegativeMargins(el, findings);
149
170
  pushInvisible(el, findings);
150
- pushBlockers(el, findings);
171
+ pushBlockers(el, findings, true);
151
172
  pushImage(el, findings);
152
- pushStacking(el, findings);
173
+ pushStacking(el, findings, true);
153
174
  pushImportant(el, this.#rules, findings);
154
175
  for (let j = 0; j < findings.length; j++) {
155
176
  rows.push({ el, selector: cssPath(el), ...findings[j] });
@@ -245,7 +266,9 @@ export class CSSAdapter {
245
266
  for (let i = 0; i < rows.length; i++) {
246
267
  const row = rows[i];
247
268
  if (describeCause(row.kind, row.selector)) {
248
- causes = addCause(causes, { kind: row.kind, path: row.selector, el: row.el }, MAX_SNAPSHOT);
269
+ // No cap here: MAX_SNAPSHOT applies after the severity sort, so an info row
270
+ // can never push a real error out.
271
+ causes = addCause(causes, { kind: row.kind, path: row.selector, el: row.el }, Infinity);
249
272
  } else {
250
273
  plain.push(row);
251
274
  }
@@ -319,6 +342,7 @@ export class CSSAdapter {
319
342
  #disable() {
320
343
  if (!this.#active) return;
321
344
  this.#active = false;
345
+ this.#hasPointer = false;
322
346
  if (typeof window !== 'undefined') {
323
347
  window.removeEventListener('mousemove', this.#onMove, true);
324
348
  window.removeEventListener('keydown', this.#onKey);
@@ -340,11 +364,16 @@ export class CSSAdapter {
340
364
  this.core?.publishDetail([]);
341
365
  this.core?.publishIssues([]);
342
366
  this.core?.sendData('state', { source: this.source, key: 'css.hunt', value: 'off' });
367
+ this.core?.sendData('state', { source: this.source, key: 'css.target', value: '—' });
368
+ this.core?.sendData('state', { source: this.source, key: 'css.hits', value: '0' });
369
+ this.core?.sendData('state', { source: this.source, key: 'css.pin', value: 'off' });
343
370
  this.core?.sendData('log', { source: this.source, message: 'CSS hunt off.' });
344
371
  }
345
372
 
346
373
  #handleKey(event) {
347
374
  if (!this.#active || event.repeat) return;
375
+ if (event.ctrlKey || event.metaKey || event.altKey) return;
376
+ if (this.core && this.core.visible === false) return;
348
377
  if (isTypingTarget(event.target)) return;
349
378
  if (event.code === this.pinKey) {
350
379
  event.preventDefault();
@@ -377,22 +406,23 @@ export class CSSAdapter {
377
406
 
378
407
  #inspect(x, y) {
379
408
  const el = pickElement(x, y);
380
- placeBox(this.#hoverBox, el);
409
+ placeBox(this.#hoverBox, el, this.#boxesVisible());
381
410
  if (this.#panelLock) return;
382
411
  if (el === this.#lastEl) return;
383
412
  this.#lastEl = el;
384
413
  if (!el) {
385
414
  this.core?.publishDetail([]);
386
415
  this.core?.sendData('state', { source: this.source, key: 'css.target', value: '—' });
416
+ this.core?.sendData('state', { source: this.source, key: 'css.hits', value: '0' });
387
417
  return;
388
418
  }
389
419
  const findings = [];
390
420
  pushImportant(el, this.#rules, findings);
391
421
  pushOverflow(el, findings);
392
422
  pushInvisible(el, findings);
393
- pushBlockers(el, findings);
423
+ pushBlockers(el, findings, true);
394
424
  pushImage(el, findings);
395
- pushStacking(el, findings);
425
+ pushStacking(el, findings, true);
396
426
  const path = cssPath(el);
397
427
  this.core?.sendData('state', { source: this.source, key: 'css.target', value: path });
398
428
  this.core?.sendData('state', {
@@ -419,7 +449,7 @@ export class CSSAdapter {
419
449
  if (this.#panelLock) {
420
450
  this.#panelLock = false;
421
451
  this.#pinned = null;
422
- placeBox(this.#pinBox, null);
452
+ placeBox(this.#pinBox, null, this.#boxesVisible());
423
453
  this.core?.sendData('state', { source: this.source, key: 'css.pin', value: 'off' });
424
454
  this.core?.sendData('log', { source: this.source, message: 'CSS pin off.' });
425
455
  this.#lastEl = null;
@@ -504,15 +534,16 @@ export class CSSAdapter {
504
534
 
505
535
  #pin(el) {
506
536
  this.#pinned = el;
507
- placeBox(this.#pinBox, el);
537
+ placeBox(this.#pinBox, el, this.#boxesVisible());
508
538
  if (el && typeof el.scrollIntoView === 'function') {
509
539
  el.scrollIntoView({ block: 'center', inline: 'nearest', behavior: 'smooth' });
510
540
  }
511
541
  }
512
542
 
513
543
  #placeBoxes() {
514
- placeBox(this.#hoverBox, this.#lastEl);
515
- placeBox(this.#pinBox, this.#pinned);
544
+ const visible = this.#boxesVisible();
545
+ placeBox(this.#hoverBox, this.#lastEl, visible);
546
+ placeBox(this.#pinBox, this.#pinned, visible);
516
547
  }
517
548
 
518
549
  #mountBoxes() {
@@ -538,6 +569,8 @@ function collectImportantRules() {
538
569
  const sheets = document.styleSheets;
539
570
  for (let i = 0; i < sheets.length; i++) {
540
571
  const sheet = sheets[i];
572
+ if (sheet.disabled === true) continue;
573
+ if (sheet.media && sheet.media.mediaText && !mediaMatches(sheet.media.mediaText)) continue;
541
574
  let list = null;
542
575
  try {
543
576
  list = sheet.cssRules;
@@ -550,21 +583,21 @@ function collectImportantRules() {
550
583
  return { rules, unreadable };
551
584
  }
552
585
 
586
+ function mediaMatches(mediaText) {
587
+ try {
588
+ return typeof matchMedia === 'function' ? matchMedia(mediaText).matches : true;
589
+ } catch {
590
+ return true;
591
+ }
592
+ }
593
+
553
594
  function walkRules(list, source, into) {
554
595
  if (!list) return;
555
596
  for (let i = 0; i < list.length; i++) {
556
597
  const rule = list[i];
557
598
  if (!rule) continue;
558
599
  if (rule.type === 4 && rule.media) {
559
- let active = true;
560
- try {
561
- active = typeof matchMedia === 'function'
562
- ? matchMedia(rule.media.mediaText).matches
563
- : true;
564
- } catch {
565
- active = true;
566
- }
567
- if (active) walkRules(rule.cssRules, source, into);
600
+ if (mediaMatches(rule.media.mediaText)) walkRules(rule.cssRules, source, into);
568
601
  continue;
569
602
  }
570
603
  if (rule.type === 1 && rule.selectorText && rule.style) {
@@ -745,7 +778,9 @@ function pushInvisible(el, findings) {
745
778
  findings.push(issue('invisible text (opacity 0)', ISSUE_RANK.invisible, 30));
746
779
  }
747
780
  const color = parseColor(style.color);
748
- if (!color || color.a === 0) {
781
+ // Unknown syntax (oklch, lab, color(), color-mix): nothing to compare, nothing to report.
782
+ if (!color) return;
783
+ if (color.a === 0) {
749
784
  findings.push(issue('invisible text (transparent color)', ISSUE_RANK.invisible, 30));
750
785
  return;
751
786
  }
@@ -1096,7 +1131,7 @@ function pickElement(x, y) {
1096
1131
  const stack = document.elementsFromPoint(x, y);
1097
1132
  for (let i = 0; i < stack.length; i++) {
1098
1133
  const el = stack[i];
1099
- if (!el || isBeeChrome(el)) continue;
1134
+ if (!el || isBeeChrome(el) || isReportNoise(el)) continue;
1100
1135
  if (el === document.documentElement || el === document.body) continue;
1101
1136
  return el;
1102
1137
  }
@@ -1154,12 +1189,16 @@ function hasOwnText(el) {
1154
1189
  function cssPath(el) {
1155
1190
  if (!el || !el.tagName) return 'node';
1156
1191
  const tag = el.tagName.toLowerCase();
1157
- if (el.id) return `${tag}#${el.id}`;
1192
+ if (el.id) return `${tag}#${cssEscape(el.id)}`;
1158
1193
  const classes = el.classList ? [...el.classList].slice(0, 2) : [];
1159
- if (classes.length) return `${tag}.${classes.join('.')}`;
1194
+ if (classes.length) return `${tag}.${classes.map(cssEscape).join('.')}`;
1160
1195
  return tag;
1161
1196
  }
1162
1197
 
1198
+ function cssEscape(value) {
1199
+ return String(value).replace(/[^\w-]/g, '\\$&');
1200
+ }
1201
+
1163
1202
  function isSkippedTag(el) {
1164
1203
  const tag = el.tagName;
1165
1204
  return tag === 'SCRIPT' || tag === 'STYLE' || tag === 'LINK' || tag === 'META';
@@ -1179,7 +1218,10 @@ function touchesSheet(record) {
1179
1218
  const name = record.target?.nodeName;
1180
1219
  return name === 'STYLE' || name === 'LINK';
1181
1220
  }
1182
- const nodes = [record.target];
1221
+ // Only what was added or removed: the target's whole subtree always holds some <style> or <link>.
1222
+ // A <style> that receives new text is the one target worth checking, and that check is O(1).
1223
+ if (record.target?.nodeName === 'STYLE') return true;
1224
+ const nodes = [];
1183
1225
  if (record.addedNodes) {
1184
1226
  for (let i = 0; i < record.addedNodes.length; i++) nodes.push(record.addedNodes[i]);
1185
1227
  }
@@ -1220,9 +1262,9 @@ function makeBox(kind, border, fill) {
1220
1262
  return node;
1221
1263
  }
1222
1264
 
1223
- function placeBox(node, el) {
1265
+ function placeBox(node, el, visible = true) {
1224
1266
  if (!node) return;
1225
- if (!el || typeof el.getBoundingClientRect !== 'function' || isBeeChrome(el)) {
1267
+ if (visible === false || !el || typeof el.getBoundingClientRect !== 'function' || isBeeChrome(el)) {
1226
1268
  node.style.display = 'none';
1227
1269
  return;
1228
1270
  }
@@ -17,6 +17,12 @@
17
17
  import { isReportNoise } from '../core/ReportExporter.js';
18
18
 
19
19
  const MAX_PROBLEM_ROWS = 40;
20
+ const OBSERVE_OPTIONS = Object.freeze({
21
+ childList: true,
22
+ subtree: true,
23
+ attributes: true,
24
+ attributeFilter: ['class', 'style', 'hidden', 'disabled', 'open']
25
+ });
20
26
 
21
27
  export const WEB_DOM_ADAPTER_DEFAULTS = Object.freeze({
22
28
  overlay: true,
@@ -74,6 +80,7 @@ export class WebDOMAdapter {
74
80
  this.#seenAttr = 0;
75
81
  this.#mutTimer = 0;
76
82
  this.#lastHoverKey = '';
83
+ this.#overlayStyle = null;
77
84
  this.#onMove = (event) => {
78
85
  this.#pointer.x = event.clientX;
79
86
  this.#pointer.y = event.clientY;
@@ -104,6 +111,8 @@ export class WebDOMAdapter {
104
111
  #seenAttr;
105
112
  #mutTimer;
106
113
  #lastHoverKey;
114
+ /** Last style values written to the overlay. */
115
+ #overlayStyle;
107
116
  #onMove;
108
117
  #onResize;
109
118
  #onTick;
@@ -118,6 +127,7 @@ export class WebDOMAdapter {
118
127
  if (this.core && typeof this.core.subscribe === 'function') {
119
128
  this.#unsubscribe = this.core.subscribe((packet) => this.#onCore(packet));
120
129
  }
130
+ this.#reporting = true;
121
131
  if (this.overlayEnabled) this.#mountOverlay();
122
132
  if (typeof window !== 'undefined') {
123
133
  window.addEventListener('mousemove', this.#onMove, true);
@@ -126,18 +136,12 @@ export class WebDOMAdapter {
126
136
  }
127
137
  if (this.root && typeof MutationObserver !== 'undefined') {
128
138
  this.#observer = new MutationObserver(this.#onMutate);
129
- this.#observer.observe(this.root, {
130
- childList: true,
131
- subtree: true,
132
- attributes: true,
133
- attributeFilter: ['class', 'style', 'hidden', 'disabled', 'open']
134
- });
139
+ this.#observer.observe(this.root, OBSERVE_OPTIONS);
135
140
  }
136
141
  if (this.autoTick && typeof requestAnimationFrame === 'function') {
137
142
  this.#rafId = requestAnimationFrame(this.#onTick);
138
143
  }
139
144
 
140
- this.#reporting = true;
141
145
  this.core?.registerAdapter('dom', {
142
146
  label: 'DOM',
143
147
  enabled: true,
@@ -178,24 +182,41 @@ export class WebDOMAdapter {
178
182
  window.removeEventListener('scroll', this.#onResize, true);
179
183
  }
180
184
  this.#unmountOverlay();
185
+ this.hover = null;
186
+ this.#lastHoverKey = '';
187
+ this.#lastPump = 0;
188
+ this.#fps = 0;
189
+ this.#pointer = { x: 0, y: 0, dirty: false };
190
+ this.#mutAdded = 0;
191
+ this.#mutRemoved = 0;
192
+ this.#mutAttr = 0;
193
+ this.#seenAdded = 0;
194
+ this.#seenRemoved = 0;
195
+ this.#seenAttr = 0;
181
196
  return this;
182
197
  }
183
198
 
184
199
  /** @param {ParentNode | null} root */
185
200
  setRoot(root) {
186
201
  this.root = root;
187
- if (this.#attached && this.#observer && root) {
188
- this.#observer.disconnect();
189
- this.#observer.observe(root, {
190
- childList: true,
191
- subtree: true,
192
- attributes: true,
193
- attributeFilter: ['class', 'style', 'hidden', 'disabled', 'open']
194
- });
202
+ if (this.#observer) this.#observer.disconnect();
203
+ if (!root) {
204
+ this.#observer = null;
205
+ } else if (this.#attached && typeof MutationObserver !== 'undefined') {
206
+ if (!this.#observer) this.#observer = new MutationObserver(this.#onMutate);
207
+ this.#observer.observe(root, OBSERVE_OPTIONS);
195
208
  }
209
+ if (this.hover && !this.#rootHolds(this.hover)) this.hover = null;
196
210
  return this;
197
211
  }
198
212
 
213
+ #rootHolds(node) {
214
+ const root = this.root;
215
+ if (!root) return false;
216
+ if (typeof document !== 'undefined' && root === document) return true;
217
+ return node === root || Boolean(root.contains?.(node));
218
+ }
219
+
199
220
  /**
200
221
  * Box model of the hover and watched nodes, layout problems under root,
201
222
  * and the latest mutation counts. Returns null when detached.
@@ -311,6 +332,7 @@ export class WebDOMAdapter {
311
332
  this.#lastHoverKey = '';
312
333
  this.core.sendData('state', { source: this.source, key: 'hover', value: '—' });
313
334
  this.core.sendData('state', { source: this.source, key: 'box', value: '—' });
335
+ this.core.sendData('state', { source: this.source, key: 'display', value: '—' });
314
336
  }
315
337
  return;
316
338
  }
@@ -341,7 +363,7 @@ export class WebDOMAdapter {
341
363
  }
342
364
 
343
365
  #queueMutations(records) {
344
- if (this.frozen) return;
366
+ if (this.frozen || !this.#reporting) return;
345
367
  for (let i = 0; i < records.length; i++) {
346
368
  const rec = records[i];
347
369
  if (isBeeChrome(rec.target)) continue;
@@ -433,12 +455,14 @@ export class WebDOMAdapter {
433
455
  canvas.style.margin = '0';
434
456
  document.body.appendChild(canvas);
435
457
  this.#overlay = canvas;
458
+ this.#overlayStyle = null;
436
459
  this.#syncOverlay();
437
460
  }
438
461
 
439
462
  #unmountOverlay() {
440
463
  if (this.#overlay?.parentNode) this.#overlay.parentNode.removeChild(this.#overlay);
441
464
  this.#overlay = null;
465
+ this.#overlayStyle = null;
442
466
  }
443
467
 
444
468
  #syncOverlay() {
@@ -447,12 +471,22 @@ export class WebDOMAdapter {
447
471
  const dpr = Math.min(window.devicePixelRatio || 1, 2);
448
472
  const w = window.innerWidth;
449
473
  const h = window.innerHeight;
450
- canvas.style.width = `${w}px`;
451
- canvas.style.height = `${h}px`;
452
- canvas.width = Math.round(w * dpr);
453
- canvas.height = Math.round(h * dpr);
474
+ // Assigning width/height clears and reallocates the bitmap: only when they change.
475
+ const bitmapW = Math.round(w * dpr);
476
+ const bitmapH = Math.round(h * dpr);
477
+ if (canvas.width !== bitmapW) canvas.width = bitmapW;
478
+ if (canvas.height !== bitmapH) canvas.height = bitmapH;
454
479
  const hidden = !this.#reporting || (this.core && this.core.visible === false);
455
- canvas.style.display = hidden ? 'none' : 'block';
480
+ const next = {
481
+ width: `${w}px`,
482
+ height: `${h}px`,
483
+ display: hidden ? 'none' : 'block'
484
+ };
485
+ const prev = this.#overlayStyle;
486
+ for (const key of Object.keys(next)) {
487
+ if (!prev || prev[key] !== next[key]) canvas.style[key] = next[key];
488
+ }
489
+ this.#overlayStyle = next;
456
490
  }
457
491
 
458
492
  #enable() {
@@ -462,6 +496,11 @@ export class WebDOMAdapter {
462
496
 
463
497
  #disable() {
464
498
  this.#reporting = false;
499
+ if (this.#mutTimer && typeof clearTimeout === 'function') clearTimeout(this.#mutTimer);
500
+ this.#mutTimer = 0;
501
+ this.#mutAdded = 0;
502
+ this.#mutRemoved = 0;
503
+ this.#mutAttr = 0;
465
504
  this.#syncOverlay();
466
505
  }
467
506
 
@@ -481,6 +520,7 @@ function isBeeChrome(node) {
481
520
  if (tag === 'BEE-LADYBUG-OVERLAY') return true;
482
521
  if (el.hasAttribute?.('data-bee-ladybug-dom')) return true;
483
522
  if (el.hasAttribute?.('data-bee-ladybug-canvas')) return true;
523
+ if (el.hasAttribute?.('data-bee-ladybug-css')) return true;
484
524
  el = el.parentElement;
485
525
  }
486
526
  return false;
@@ -10,7 +10,7 @@ import { UIOverlay } from './UIOverlay.js';
10
10
  import { buildAssistantSnapshot, normalizeAssistant } from './AiAssistant.js';
11
11
  import { exportReport as writeReport } from './ReportExporter.js';
12
12
 
13
- export const BEE_LADYBUG_VERSION = '0.6.2';
13
+ export const BEE_LADYBUG_VERSION = '0.6.4';
14
14
 
15
15
  export const CORE_DEFAULTS = Object.freeze({
16
16
  toggleKey: 'F2',
package/src/index.d.ts CHANGED
@@ -356,6 +356,8 @@ export interface WebDOMAdapterOptions {
356
356
 
357
357
  export const WEB_DOM_ADAPTER_DEFAULTS: Required<Omit<WebDOMAdapterOptions, 'root'>>;
358
358
 
359
+ export function domNoiseQuiet(cssEnabled: boolean, frozen: boolean, timeScale: number): boolean;
360
+
359
361
  export class WebDOMAdapter {
360
362
  core: BeeLadybugCore | null;
361
363
  root: ParentNode | null;
package/src/index.js CHANGED
@@ -2,7 +2,7 @@ export { BeeLadybugCore, BEE_LADYBUG_VERSION, CORE_DEFAULTS, WELL_KNOWN_TYPES, f
2
2
  export { exportReport, isReportNoise } from './core/ReportExporter.js';
3
3
  export { UIOverlay } from './core/UIOverlay.js';
4
4
  export { CanvasAdapter, CANVAS_ADAPTER_DEFAULTS } from './adapters/CanvasAdapter.js';
5
- export { WebDOMAdapter, WEB_DOM_ADAPTER_DEFAULTS } from './adapters/WebDOMAdapter.js';
5
+ export { WebDOMAdapter, WEB_DOM_ADAPTER_DEFAULTS, domNoiseQuiet } from './adapters/WebDOMAdapter.js';
6
6
  export { CSSAdapter, CSS_ADAPTER_DEFAULTS } from './adapters/CSSAdapter.js';
7
7
  export { AntAdapter, ANT_ADAPTER_DEFAULTS } from './adapters/AntAdapter.js';
8
8
  export { SpiderAdapter, SPIDER_ADAPTER_DEFAULTS } from './adapters/SpiderAdapter.js';