@c15t/dev-tools 2.0.0-rc.6 → 2.0.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
@@ -184,4 +184,4 @@ You can also force dark mode:
184
184
 
185
185
  ## License
186
186
 
187
- GPL-3.0-only
187
+ Apache-2.0
package/dist/379.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { subscribeToScriptDebugEvents } from "c15t";
1
2
  import { __webpack_require__ } from "./0~rslib-runtime.js";
2
3
  __webpack_require__.add({
3
4
  "../../node_modules/.bun/@rsbuild+core@2.0.0-beta.11+490411ac90707e06/node_modules/@rsbuild/core/compiled/css-loader/index.js??ruleSet[1].rules[1].oneOf[2].use[1]!builtin:lightningcss-loader??ruleSet[1].rules[1].oneOf[2].use[2]!./src/styles/animations.module.css" (module, __webpack_exports__, __webpack_require__) {
@@ -2293,7 +2294,6 @@ function getPreferenceCenterOpener(namespace = 'c15tStore') {
2293
2294
  }
2294
2295
  return null;
2295
2296
  }
2296
- const version = '2.0.0-rc.6';
2297
2297
  const DEVTOOLS_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 446 445" aria-label="c15t">
2298
2298
  <path fill="currentColor" d="M223.178.313c39.064 0 70.732 31.668 70.732 70.732-.001 39.064-31.668 70.731-70.732 70.731-12.181 0-23.642-3.079-33.649-8.502l-55.689 55.689a70.267 70.267 0 0 1 5.574 13.441h167.531c8.695-29.217 35.762-50.523 67.804-50.523 39.064 0 70.731 31.668 70.731 70.732s-31.668 70.732-70.731 70.732c-32.042 0-59.108-21.306-67.803-50.523H139.413a70.417 70.417 0 0 1-7.888 17.396l54.046 54.046c10.893-6.851 23.786-10.815 37.605-10.815 39.064 0 70.732 31.669 70.732 70.733 0 39.064-31.668 70.731-70.732 70.731s-70.732-31.667-70.732-70.731c0-10.518 2.296-20.499 6.414-29.471l-57.78-57.78c-8.972 4.117-18.952 6.414-29.47 6.414-39.063 0-70.731-31.668-70.732-70.732 0-39.064 31.669-70.732 70.733-70.732 12.18 0 23.642 3.079 33.649 8.502l55.688-55.688c-5.423-10.007-8.502-21.469-8.502-33.65 0-39.064 31.668-70.733 70.732-70.733Zm0 343.555c-16.742 0-30.314 13.572-30.314 30.314 0 16.741 13.572 30.313 30.314 30.313s30.314-13.572 30.314-30.313c0-16.742-13.572-30.314-30.314-30.314ZM71.611 192.299c-16.742 0-30.315 13.572-30.315 30.314s13.573 30.314 30.315 30.314c16.741 0 30.313-13.572 30.313-30.314 0-16.741-13.572-30.314-30.313-30.314Zm303.138 0c-16.729 0-30.294 13.551-30.315 30.275l.001.039-.001.038c.021 16.725 13.586 30.276 30.315 30.276 16.741 0 30.313-13.572 30.313-30.314 0-16.741-13.572-30.314-30.313-30.314ZM223.178 40.73c-16.742 0-30.314 13.573-30.314 30.315s13.573 30.313 30.314 30.313c16.742 0 30.313-13.572 30.314-30.313 0-16.742-13.572-30.314-30.314-30.315Z"/>
2299
2299
  </svg>`;
@@ -2710,7 +2710,7 @@ function createPanel(options) {
2710
2710
  }
2711
2711
  }));
2712
2712
  footerElement.appendChild(renderer_span({
2713
- text: `v${version}`
2713
+ text: "v2.0.0"
2714
2714
  }));
2715
2715
  }
2716
2716
  function renderErrorState(container) {
@@ -4015,7 +4015,8 @@ const EVENT_FILTERS = [
4015
4015
  'error',
4016
4016
  'consent',
4017
4017
  'network',
4018
- 'iab'
4018
+ 'iab',
4019
+ "script"
4019
4020
  ];
4020
4021
  function createFilterButton(filter, active, onClick) {
4021
4022
  return createButton({
@@ -4030,6 +4031,7 @@ function matchesFilter(event, filter) {
4030
4031
  if ('error' === filter) return 'error' === event.type;
4031
4032
  if ('consent' === filter) return 'consent_set' === event.type || 'consent_save' === event.type || 'consent_reset' === event.type;
4032
4033
  if ('network' === filter) return 'network' === event.type;
4034
+ if ("script" === filter) return "script" === event.type;
4033
4035
  return 'iab' === event.type;
4034
4036
  }
4035
4037
  function matchesSearch(event, query) {
@@ -4153,6 +4155,8 @@ function getEventIcon(type) {
4153
4155
  return '◉';
4154
4156
  case 'iab':
4155
4157
  return '◆';
4158
+ case "script":
4159
+ return '⌘';
4156
4160
  default:
4157
4161
  return '○';
4158
4162
  }
@@ -4170,6 +4174,8 @@ function getEventColor(type) {
4170
4174
  return 'var(--c15t-devtools-badge-warning, #f59e0b)';
4171
4175
  case 'iab':
4172
4176
  return 'var(--c15t-devtools-badge-info, #3b82f6)';
4177
+ case "script":
4178
+ return 'var(--c15t-devtools-badge-info, #14b8a6)';
4173
4179
  default:
4174
4180
  return 'var(--c15t-text-muted)';
4175
4181
  }
@@ -5470,6 +5476,20 @@ const CODE_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" f
5470
5476
  <polyline points="8 6 2 12 8 18"></polyline>
5471
5477
  </svg>`;
5472
5478
  const scriptsSearchByContainer = new WeakMap();
5479
+ const expandedScriptsByContainer = new WeakMap();
5480
+ const CHEVRON_DOWN_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
5481
+ <polyline points="6 9 12 15 18 9"></polyline>
5482
+ </svg>`;
5483
+ const CHEVRON_RIGHT_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
5484
+ <polyline points="9 18 15 12 9 6"></polyline>
5485
+ </svg>`;
5486
+ function getExpandedScripts(container) {
5487
+ const existing = expandedScriptsByContainer.get(container);
5488
+ if (existing) return existing;
5489
+ const expanded = new Set();
5490
+ expandedScriptsByContainer.set(container, expanded);
5491
+ return expanded;
5492
+ }
5473
5493
  function renderScriptsPanel(container, options) {
5474
5494
  const { getState, getEvents } = options;
5475
5495
  clearElement(container);
@@ -5531,6 +5551,10 @@ function renderScriptsPanel(container, options) {
5531
5551
  for (const script of filteredScripts){
5532
5552
  const scriptId = script.id;
5533
5553
  const isLoaded = true === loadedScripts[scriptId];
5554
+ const scriptEvents = getScriptActivityEvents(events, scriptId);
5555
+ const latestActivity = scriptEvents[scriptEvents.length - 1];
5556
+ const expandedScripts = getExpandedScripts(container);
5557
+ const isExpanded = expandedScripts.has(scriptId);
5534
5558
  const category = script.category;
5535
5559
  const categoryDisplay = 'string' == typeof category ? category : JSON.stringify(category);
5536
5560
  let status = 'pending';
@@ -5552,7 +5576,7 @@ function renderScriptsPanel(container, options) {
5552
5576
  text: status.charAt(0).toUpperCase() + status.slice(1),
5553
5577
  variant: statusVariant
5554
5578
  });
5555
- const row = renderer_div({
5579
+ const header = renderer_div({
5556
5580
  style: {
5557
5581
  display: 'flex',
5558
5582
  alignItems: 'center',
@@ -5591,19 +5615,57 @@ function renderScriptsPanel(container, options) {
5591
5615
  whiteSpace: 'nowrap'
5592
5616
  },
5593
5617
  text: `Category: ${categoryDisplay}`
5594
- })
5618
+ }),
5619
+ ...latestActivity && scriptEvents.length > 0 ? [
5620
+ renderer_div({
5621
+ style: {
5622
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
5623
+ color: 'var(--c15t-text-muted)',
5624
+ overflow: 'hidden',
5625
+ textOverflow: 'ellipsis',
5626
+ whiteSpace: 'nowrap'
5627
+ },
5628
+ text: `Activity: ${latestActivity.message} (${scriptEvents.length} event${1 === scriptEvents.length ? '' : 's'})`
5629
+ })
5630
+ ] : []
5595
5631
  ]
5596
5632
  }),
5597
5633
  renderer_div({
5598
5634
  style: {
5599
- flexShrink: '0'
5635
+ flexShrink: '0',
5636
+ display: 'flex',
5637
+ alignItems: 'center',
5638
+ gap: '8px'
5600
5639
  },
5601
5640
  children: [
5602
- badge
5641
+ badge,
5642
+ ...scriptEvents.length > 0 ? [
5643
+ createAccordionToggle({
5644
+ scriptId,
5645
+ isExpanded,
5646
+ onToggle: ()=>{
5647
+ if (isExpanded) expandedScripts.delete(scriptId);
5648
+ else expandedScripts.add(scriptId);
5649
+ renderScriptsPanel(container, options);
5650
+ }
5651
+ })
5652
+ ] : []
5603
5653
  ]
5604
5654
  })
5605
5655
  ]
5606
5656
  });
5657
+ const details = isExpanded && scriptEvents.length > 0 ? createScriptActivityDetails(scriptEvents) : null;
5658
+ const row = renderer_div({
5659
+ style: {
5660
+ display: 'flex',
5661
+ flexDirection: 'column',
5662
+ borderBottom: '1px solid var(--c15t-border)'
5663
+ },
5664
+ children: [
5665
+ header,
5666
+ details
5667
+ ]
5668
+ });
5607
5669
  scriptsList.appendChild(row);
5608
5670
  }
5609
5671
  const lastRow = scriptsList.lastElementChild;
@@ -5740,13 +5802,172 @@ function getEventUrl(event) {
5740
5802
  return 'string' == typeof url ? url : event.message;
5741
5803
  }
5742
5804
  function formatEventTime(timestamp) {
5743
- return new Date(timestamp).toLocaleTimeString('en-US', {
5744
- hour12: false,
5745
- hour: '2-digit',
5746
- minute: '2-digit',
5747
- second: '2-digit'
5805
+ const date = new Date(timestamp);
5806
+ const hours = String(date.getHours()).padStart(2, '0');
5807
+ const minutes = String(date.getMinutes()).padStart(2, '0');
5808
+ const seconds = String(date.getSeconds()).padStart(2, '0');
5809
+ const milliseconds = String(date.getMilliseconds()).padStart(3, '0');
5810
+ return `${hours}:${minutes}:${seconds}.${milliseconds}`;
5811
+ }
5812
+ function getScriptActivityEvents(events, scriptId) {
5813
+ return events.filter((event)=>{
5814
+ if ("script" !== event.type) return false;
5815
+ const data = event.data;
5816
+ if (data?.scriptId !== scriptId) return false;
5817
+ return data?.scope === 'lifecycle' || data?.scope === 'phase';
5818
+ }).sort((left, right)=>left.timestamp - right.timestamp);
5819
+ }
5820
+ function createAccordionToggle(options) {
5821
+ const { scriptId, isExpanded, onToggle } = options;
5822
+ const toggle = renderer_button({
5823
+ ariaLabel: `${isExpanded ? 'Collapse' : 'Expand'} ${scriptId} activity`,
5824
+ ariaExpanded: isExpanded ? 'true' : 'false',
5825
+ style: {
5826
+ display: 'inline-flex',
5827
+ alignItems: 'center',
5828
+ justifyContent: 'center',
5829
+ width: '24px',
5830
+ height: '24px',
5831
+ padding: '0',
5832
+ border: '1px solid var(--c15t-border)',
5833
+ borderRadius: '6px',
5834
+ background: 'transparent',
5835
+ color: 'var(--c15t-text-muted)',
5836
+ cursor: 'pointer',
5837
+ flexShrink: '0'
5838
+ },
5839
+ onClick: onToggle
5840
+ });
5841
+ toggle.innerHTML = isExpanded ? CHEVRON_DOWN_ICON : CHEVRON_RIGHT_ICON;
5842
+ return toggle;
5843
+ }
5844
+ function createScriptActivityDetails(events) {
5845
+ const groupedEvents = groupScriptActivityEvents(events.slice(-8));
5846
+ return renderer_div({
5847
+ style: {
5848
+ display: 'flex',
5849
+ flexDirection: 'column',
5850
+ gap: '6px',
5851
+ padding: '0 0 10px 0',
5852
+ marginLeft: '0'
5853
+ },
5854
+ children: groupedEvents.map(([groupName, groupEvents])=>createScriptActivityGroup(groupName, groupEvents))
5748
5855
  });
5749
5856
  }
5857
+ function createScriptActivityGroup(groupName, events) {
5858
+ return renderer_div({
5859
+ style: {
5860
+ display: 'flex',
5861
+ flexDirection: 'column',
5862
+ gap: '4px'
5863
+ },
5864
+ children: [
5865
+ renderer_span({
5866
+ style: {
5867
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
5868
+ fontWeight: '600',
5869
+ color: 'var(--c15t-text)',
5870
+ textTransform: 'none'
5871
+ },
5872
+ text: groupName
5873
+ }),
5874
+ ...events.map((event)=>createScriptActivityRow(event))
5875
+ ]
5876
+ });
5877
+ }
5878
+ function createScriptActivityRow(event) {
5879
+ const data = event.data ?? {};
5880
+ const scope = 'string' == typeof data.scope ? data.scope : void 0;
5881
+ const phase = 'string' == typeof data.phase ? data.phase : void 0;
5882
+ const stepType = 'string' == typeof data.stepType ? data.stepType : void 0;
5883
+ const metadata = [
5884
+ scope,
5885
+ phase,
5886
+ stepType
5887
+ ].filter(Boolean).join(' / ');
5888
+ return renderer_div({
5889
+ style: {
5890
+ display: 'flex',
5891
+ flexDirection: 'column',
5892
+ gap: '2px',
5893
+ padding: '6px 10px',
5894
+ marginLeft: '0',
5895
+ borderLeft: '2px solid var(--c15t-border)',
5896
+ backgroundColor: 'var(--c15t-devtools-surface-secondary, rgba(127,127,127,0.06))',
5897
+ borderRadius: '0 8px 8px 0'
5898
+ },
5899
+ children: [
5900
+ renderer_div({
5901
+ style: {
5902
+ display: 'flex',
5903
+ alignItems: 'center',
5904
+ justifyContent: 'space-between',
5905
+ gap: '8px'
5906
+ },
5907
+ children: [
5908
+ renderer_span({
5909
+ style: {
5910
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
5911
+ fontWeight: '600',
5912
+ color: 'var(--c15t-text)'
5913
+ },
5914
+ text: event.message
5915
+ }),
5916
+ renderer_span({
5917
+ style: {
5918
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
5919
+ color: 'var(--c15t-text-muted)',
5920
+ flexShrink: '0'
5921
+ },
5922
+ text: formatEventTime(event.timestamp)
5923
+ })
5924
+ ]
5925
+ }),
5926
+ ...metadata ? [
5927
+ renderer_span({
5928
+ style: {
5929
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
5930
+ color: 'var(--c15t-text-muted)'
5931
+ },
5932
+ text: metadata
5933
+ })
5934
+ ] : []
5935
+ ]
5936
+ });
5937
+ }
5938
+ function groupScriptActivityEvents(events) {
5939
+ const groups = new Map();
5940
+ for (const event of events){
5941
+ const groupName = getScriptActivityGroupName(event);
5942
+ const existing = groups.get(groupName);
5943
+ if (existing) existing.push(event);
5944
+ else groups.set(groupName, [
5945
+ event
5946
+ ]);
5947
+ }
5948
+ const orderedGroupNames = [
5949
+ 'onBeforeLoad',
5950
+ 'onLoad',
5951
+ 'onConsentChange',
5952
+ 'other'
5953
+ ];
5954
+ return orderedGroupNames.map((groupName)=>{
5955
+ const groupEvents = groups.get(groupName);
5956
+ return groupEvents ? [
5957
+ groupName,
5958
+ groupEvents
5959
+ ] : null;
5960
+ }).filter((group)=>null !== group);
5961
+ }
5962
+ function getScriptActivityGroupName(event) {
5963
+ const data = event.data ?? {};
5964
+ if ('string' == typeof data.callback) return data.callback;
5965
+ const phase = 'string' == typeof data.phase ? data.phase : '';
5966
+ if ('bootstrap' === phase || 'consent-default' === phase || 'setup' === phase || 'onBeforeLoadGranted' === phase || 'onBeforeLoadDenied' === phase) return 'onBeforeLoad';
5967
+ if ('afterLoad' === phase || 'onLoadGranted' === phase || 'onLoadDenied' === phase) return 'onLoad';
5968
+ if ('consent-update' === phase || 'onConsentChange' === phase || 'onConsentGranted' === phase || 'onConsentDenied' === phase) return 'onConsentChange';
5969
+ return 'other';
5970
+ }
5750
5971
  function scripts_truncateText(text, maxLength) {
5751
5972
  if (text.length <= maxLength) return text;
5752
5973
  return `${text.slice(0, maxLength - 3)}...`;
@@ -6324,6 +6545,7 @@ function restoreInstrumentation(entry) {
6324
6545
  const state = entry.store.getState();
6325
6546
  state.setCallback('onBannerFetched', entry.originalCallbacks.onBannerFetched);
6326
6547
  state.setCallback('onConsentSet', entry.originalCallbacks.onConsentSet);
6548
+ state.setCallback('onConsentChanged', entry.originalCallbacks.onConsentChanged);
6327
6549
  state.setCallback('onError', entry.originalCallbacks.onError);
6328
6550
  state.setCallback('onBeforeConsentRevocationReload', entry.originalCallbacks.onBeforeConsentRevocationReload);
6329
6551
  const blocker = state.networkBlocker;
@@ -6361,6 +6583,14 @@ function createInstrumentationEntry(store) {
6361
6583
  });
6362
6584
  if ('function' == typeof entry.originalCallbacks.onConsentSet) entry.originalCallbacks.onConsentSet(payload);
6363
6585
  });
6586
+ store.getState().setCallback('onConsentChanged', (payload)=>{
6587
+ emitEvent(entry, {
6588
+ type: 'consent_save',
6589
+ message: 'Consent preferences changed',
6590
+ data: payload
6591
+ });
6592
+ if ('function' == typeof entry.originalCallbacks.onConsentChanged) entry.originalCallbacks.onConsentChanged(payload);
6593
+ });
6364
6594
  store.getState().setCallback('onError', (payload)=>{
6365
6595
  const errorMessage = payload.error;
6366
6596
  emitEvent(entry, {
@@ -6501,6 +6731,25 @@ function createStateCopy(state) {
6501
6731
  loadedScripts: state.loadedScripts
6502
6732
  };
6503
6733
  }
6734
+ function scriptDebugEventToLogEntry(event) {
6735
+ return {
6736
+ type: "script",
6737
+ message: event.message,
6738
+ data: {
6739
+ ...event.data ?? {},
6740
+ source: event.source,
6741
+ scope: event.scope,
6742
+ action: event.action,
6743
+ scriptId: event.scriptId,
6744
+ elementId: event.elementId,
6745
+ hasConsent: event.hasConsent,
6746
+ callback: event.callback,
6747
+ phase: event.phase,
6748
+ stepType: event.stepType,
6749
+ stepIndex: event.stepIndex
6750
+ }
6751
+ };
6752
+ }
6504
6753
  function createDevTools(options = {}) {
6505
6754
  const { namespace = 'c15tStore', position = 'bottom-right', defaultOpen = false } = options;
6506
6755
  const stateManager = createStateManager({
@@ -6508,6 +6757,7 @@ function createDevTools(options = {}) {
6508
6757
  isOpen: defaultOpen
6509
6758
  });
6510
6759
  let detachInstrumentation = null;
6760
+ let detachScriptDebug = null;
6511
6761
  const storeConnector = createStoreConnector({
6512
6762
  namespace,
6513
6763
  onConnect: (_state, store)=>{
@@ -6519,6 +6769,10 @@ function createDevTools(options = {}) {
6519
6769
  stateManager.addEvent(event);
6520
6770
  }
6521
6771
  });
6772
+ detachScriptDebug?.();
6773
+ detachScriptDebug = subscribeToScriptDebugEvents((event)=>{
6774
+ stateManager.addEvent(scriptDebugEventToLogEntry(event));
6775
+ });
6522
6776
  stateManager.setConnected(true);
6523
6777
  stateManager.addEvent({
6524
6778
  type: 'info',
@@ -6555,6 +6809,8 @@ function createDevTools(options = {}) {
6555
6809
  stateManager.setConnected(false);
6556
6810
  detachInstrumentation?.();
6557
6811
  detachInstrumentation = null;
6812
+ detachScriptDebug?.();
6813
+ detachScriptDebug = null;
6558
6814
  stateManager.addEvent({
6559
6815
  type: 'error',
6560
6816
  message: 'Disconnected from c15tStore'
@@ -6644,6 +6900,8 @@ function createDevTools(options = {}) {
6644
6900
  destroy: ()=>{
6645
6901
  detachInstrumentation?.();
6646
6902
  detachInstrumentation = null;
6903
+ detachScriptDebug?.();
6904
+ detachScriptDebug = null;
6647
6905
  panelHeightAnimator.destroy();
6648
6906
  tabsInstance?.destroy();
6649
6907
  panelInstance.destroy();
@@ -6658,6 +6916,7 @@ function createDevTools(options = {}) {
6658
6916
  function createDevToolsPanel(options) {
6659
6917
  const { namespace = 'c15tStore' } = options;
6660
6918
  let detachInstrumentation = null;
6919
+ let detachScriptDebug = null;
6661
6920
  const stateManager = createStateManager({
6662
6921
  isOpen: true
6663
6922
  });
@@ -6670,6 +6929,10 @@ function createDevToolsPanel(options) {
6670
6929
  store,
6671
6930
  onEvent: (event)=>stateManager.addEvent(event)
6672
6931
  });
6932
+ detachScriptDebug?.();
6933
+ detachScriptDebug = subscribeToScriptDebugEvents((event)=>{
6934
+ stateManager.addEvent(scriptDebugEventToLogEntry(event));
6935
+ });
6673
6936
  stateManager.setConnected(true);
6674
6937
  const persistedOverrides = loadPersistedOverrides();
6675
6938
  if (persistedOverrides) {
@@ -6686,6 +6949,8 @@ function createDevToolsPanel(options) {
6686
6949
  stateManager.setConnected(false);
6687
6950
  detachInstrumentation?.();
6688
6951
  detachInstrumentation = null;
6952
+ detachScriptDebug?.();
6953
+ detachScriptDebug = null;
6689
6954
  }
6690
6955
  });
6691
6956
  const panelRenderer = createPanelRenderer({
@@ -6778,6 +7043,8 @@ function createDevToolsPanel(options) {
6778
7043
  destroy: ()=>{
6779
7044
  detachInstrumentation?.();
6780
7045
  detachInstrumentation = null;
7046
+ detachScriptDebug?.();
7047
+ detachScriptDebug = null;
6781
7048
  unsubscribe();
6782
7049
  tabsInstance?.destroy();
6783
7050
  storeConnector.destroy();