@pendo/agent 2.347.0 → 2.349.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/dist/dom.esm.js CHANGED
@@ -7555,7 +7555,7 @@ function applyMatrix2dRect(matrix2d, rect) {
7555
7555
  return transformedRect;
7556
7556
  }
7557
7557
 
7558
- var VERSION = '2.347.0_';
7558
+ var VERSION = '2.349.0_';
7559
7559
 
7560
7560
  var decodeURIComponent = _.isFunction(globalScope.decodeURIComponent) ? globalScope.decodeURIComponent : _.identity;
7561
7561
 
@@ -7915,13 +7915,13 @@ var agentStorage = (function () {
7915
7915
  resetCache(storageAvailable);
7916
7916
  if (storageIsDisabled()) {
7917
7917
  inMemoryStorage[key] = ttlWrite(val, duration);
7918
- return;
7918
+ return true;
7919
7919
  }
7920
7920
  if (shouldUseLocalStorage(keyLocalStorageOnly)) {
7921
7921
  if (storageAvailable('localStorage')) {
7922
7922
  try {
7923
7923
  localStorage.setItem(key, ttlWrite(val, duration));
7924
- return;
7924
+ return true;
7925
7925
  }
7926
7926
  catch (e) { }
7927
7927
  }
@@ -7931,11 +7931,12 @@ var agentStorage = (function () {
7931
7931
  if (!isPlain)
7932
7932
  duration = duration || DEFAULT_EXPIRE_LEN;
7933
7933
  setCookie(key, val, duration, isSecure);
7934
- return;
7934
+ return true;
7935
7935
  }
7936
7936
  catch (e) { }
7937
7937
  }
7938
7938
  inMemoryStorage[key] = ttlWrite(val, duration);
7939
+ return false;
7939
7940
  }
7940
7941
  function ttlWrite(value, duration) {
7941
7942
  if (duration === null) {
@@ -4138,8 +4138,8 @@ let SERVER = '';
4138
4138
  let ASSET_HOST = '';
4139
4139
  let ASSET_PATH = '';
4140
4140
  let DESIGNER_SERVER = '';
4141
- let VERSION = '2.347.0_';
4142
- let PACKAGE_VERSION = '2.347.0';
4141
+ let VERSION = '2.349.0_';
4142
+ let PACKAGE_VERSION = '2.349.0';
4143
4143
  let LOADER = 'xhr';
4144
4144
  /* eslint-enable web-sdk-eslint-rules/no-gulp-env-references */
4145
4145
  /**
@@ -5133,13 +5133,13 @@ var agentStorage = (function () {
5133
5133
  resetCache(storageAvailable);
5134
5134
  if (storageIsDisabled()) {
5135
5135
  inMemoryStorage[key] = ttlWrite(val, duration);
5136
- return;
5136
+ return true;
5137
5137
  }
5138
5138
  if (shouldUseLocalStorage(keyLocalStorageOnly)) {
5139
5139
  if (storageAvailable('localStorage')) {
5140
5140
  try {
5141
5141
  localStorage.setItem(key, ttlWrite(val, duration));
5142
- return;
5142
+ return true;
5143
5143
  }
5144
5144
  catch (e) { }
5145
5145
  }
@@ -5149,11 +5149,12 @@ var agentStorage = (function () {
5149
5149
  if (!isPlain)
5150
5150
  duration = duration || DEFAULT_EXPIRE_LEN;
5151
5151
  setCookie(key, val, duration, isSecure);
5152
- return;
5152
+ return true;
5153
5153
  }
5154
5154
  catch (e) { }
5155
5155
  }
5156
5156
  inMemoryStorage[key] = ttlWrite(val, duration);
5157
+ return false;
5157
5158
  }
5158
5159
  function ttlWrite(value, duration) {
5159
5160
  if (duration === null) {
@@ -12995,6 +12996,23 @@ function migrateLegacyCookieEvents(events) {
12995
12996
  clearCookie(getPendoCookieKey(UNSENT_EVENTS_KEY));
12996
12997
  }
12997
12998
  }
12999
+ // the quota error doesn't say how much space is left, so halving keeps the
13000
+ // number of retries during pagehide small
13001
+ function dropOldestHalf(events) {
13002
+ const entries = [];
13003
+ _.each(events, (requests, key) => {
13004
+ _.each(requests, (request) => {
13005
+ entries.push({ key, request });
13006
+ });
13007
+ });
13008
+ const newest = _.sortBy(entries, (entry) => entry.request.ts).slice(Math.ceil(entries.length / 2));
13009
+ const remaining = {};
13010
+ _.each(newest, (entry) => {
13011
+ remaining[entry.key] = remaining[entry.key] || [];
13012
+ remaining[entry.key].push(entry.request);
13013
+ });
13014
+ return remaining;
13015
+ }
12998
13016
  class LocalStorageEventBuffer {
12999
13017
  constructor() {
13000
13018
  this.events = {};
@@ -13039,12 +13057,14 @@ class LocalStorageEventBuffer {
13039
13057
  storage.clear(UNSENT_EVENTS_KEY);
13040
13058
  }
13041
13059
  write(storage) {
13042
- if (_.size(this.events) > 0) {
13043
- storage.write(UNSENT_EVENTS_KEY, JSON.stringify(this.events), UNSENT_EVENTS_MAX_AGE);
13044
- }
13045
- else {
13046
- storage.clear(UNSENT_EVENTS_KEY);
13060
+ let events = this.events;
13061
+ while (_.size(events) > 0) {
13062
+ if (storage.write(UNSENT_EVENTS_KEY, JSON.stringify(events), UNSENT_EVENTS_MAX_AGE)) {
13063
+ return;
13064
+ }
13065
+ events = dropOldestHalf(events);
13047
13066
  }
13067
+ storage.clear(UNSENT_EVENTS_KEY);
13048
13068
  }
13049
13069
  }
13050
13070
  var localStorageEventBuffer = new LocalStorageEventBuffer();
@@ -14239,6 +14259,14 @@ var isWalkthrough = function (guide) {
14239
14259
  var isForm = function (guide) {
14240
14260
  return !!(_.get(guide, 'attributes.form'));
14241
14261
  };
14262
+ // An HTML guide step's type is 'html' and it has no domJson to derive calculatedType
14263
+ // from, so its layout only shows up in buildingBlockLayoutType
14264
+ var isTooltipStep = function (step) {
14265
+ var tooltip = 'tooltip';
14266
+ return _.get(step, 'type') === tooltip ||
14267
+ _.get(step, 'attributes.calculatedType') === tooltip ||
14268
+ _.get(step, 'attributes.buildingBlockLayoutType', _.get(step, 'buildingBlockLayoutType')) === tooltip;
14269
+ };
14242
14270
  function isPreviewing() {
14243
14271
  /* global selmo */
14244
14272
  return (typeof selmo !== 'undefined' && !!selmo.isPreviewing);
@@ -17881,6 +17909,7 @@ var FlexboxPolyfill = (function () {
17881
17909
  wrapElementInMockFlexboxContainer,
17882
17910
  getVisualElementsWrappedInFlexElements,
17883
17911
  initializeFlexRows,
17912
+ initializeNativeFlexRow,
17884
17913
  getRowWidth,
17885
17914
  wrapFlexElementsInFlexRows,
17886
17915
  formatFlexRows,
@@ -18242,32 +18271,26 @@ var FlexboxPolyfill = (function () {
18242
18271
  var computedStyles = getComputedStyle_safe(row);
18243
18272
  return parseInt(width, 10) - parseInt(computedStyles.paddingLeft, 10) - parseInt(computedStyles.paddingRight, 10);
18244
18273
  }
18245
- function initializeFlexRows(row, justifyContent, rowVerticalAlignment, useNativeFlexbox = false) {
18246
- if (useNativeFlexbox) {
18247
- var alignments = {
18248
- top: 'flex-start',
18249
- center: 'center',
18250
- bottom: 'flex-end'
18251
- };
18252
- row.style.display = 'flex';
18253
- row.style.flexWrap = 'wrap';
18254
- row.style.justifyContent = justifyContent;
18255
- row.style.alignItems = alignments[rowVerticalAlignment] || 'flex-start';
18256
- }
18257
- else {
18258
- var flexElements = getFlexboxElements(row.children);
18259
- if (flexElements.length === 0)
18260
- return;
18261
- // In the following steps, we remove and add elements to the guide.
18262
- // Therefore we precalculation the rowWidth to ensure it won't change
18263
- // in case of scrollbar will be added or removed from the screen.
18264
- var rowWidth = FlexboxPolyfill.getRowWidth(row);
18265
- var flexRows = FlexboxPolyfill.wrapFlexElementsInFlexRows(flexElements, row, rowWidth);
18266
- // Once we have all the pendo-mock-flexbox-element elements placed in to
18267
- // pendo-mock-flexbox-row rows, loop through each pendo-mock-flexbox-row and set the
18268
- // height and alignment
18269
- FlexboxPolyfill.formatFlexRows(flexRows, row, justifyContent, rowVerticalAlignment, rowWidth);
18270
- }
18274
+ function initializeNativeFlexRow(row, justifyContent, rowVerticalAlignment) {
18275
+ var alignments = {
18276
+ top: 'flex-start',
18277
+ center: 'center',
18278
+ bottom: 'flex-end'
18279
+ };
18280
+ row.style.display = 'flex';
18281
+ row.style.flexWrap = 'wrap';
18282
+ row.style.justifyContent = justifyContent;
18283
+ row.style.alignItems = alignments[rowVerticalAlignment] || 'flex-start';
18284
+ }
18285
+ function initializeFlexRows(row, justifyContent, rowVerticalAlignment, rowWidth) {
18286
+ var flexElements = getFlexboxElements(row.children);
18287
+ if (flexElements.length === 0)
18288
+ return;
18289
+ var flexRows = FlexboxPolyfill.wrapFlexElementsInFlexRows(flexElements, row, rowWidth);
18290
+ // Once we have all the pendo-mock-flexbox-element elements placed in to
18291
+ // pendo-mock-flexbox-row rows, loop through each pendo-mock-flexbox-row and set the
18292
+ // height and alignment
18293
+ FlexboxPolyfill.formatFlexRows(flexRows, row, justifyContent, rowVerticalAlignment, rowWidth);
18271
18294
  }
18272
18295
  function wrapFlexElementsInFlexRows(flexElements, row, rowWidthPreCalc) {
18273
18296
  var rowWidth = rowWidthPreCalc || getRowWidth(row);
@@ -18347,10 +18370,17 @@ var FlexboxPolyfill = (function () {
18347
18370
  function flexElement(ele, useNativeFlexbox) {
18348
18371
  var rowsToBeFlexed = dom('[data-pendo-display-flex]', ele);
18349
18372
  _.each(rowsToBeFlexed, function (row) {
18350
- var rowWithFlexedElements = useNativeFlexbox ? row : FlexboxPolyfill.initializeFlexElements(row);
18351
18373
  var horizontalAlignment = row.getAttribute('data-pendo-justify-content');
18352
18374
  var rowVerticalAlignment = row.getAttribute('data-row-vertical-alignment');
18353
- FlexboxPolyfill.initializeFlexRows(rowWithFlexedElements, horizontalAlignment, rowVerticalAlignment, useNativeFlexbox);
18375
+ if (useNativeFlexbox) {
18376
+ FlexboxPolyfill.initializeNativeFlexRow(row, horizontalAlignment, rowVerticalAlignment);
18377
+ return;
18378
+ }
18379
+ // Initializing flex elements can add a temporary scrollbar to a scrolling ancestor and shrink the
18380
+ // width of the rows. Pre-measure the row width to prevent its children from wrapping onto a new row.
18381
+ var rowWidth = FlexboxPolyfill.getRowWidth(row);
18382
+ var rowWithFlexedElements = FlexboxPolyfill.initializeFlexElements(row);
18383
+ FlexboxPolyfill.initializeFlexRows(rowWithFlexedElements, horizontalAlignment, rowVerticalAlignment, rowWidth);
18354
18384
  });
18355
18385
  }
18356
18386
  function flexAllThings(containerId, step) {
@@ -22914,7 +22944,7 @@ function stepShowingProc(guide, step) {
22914
22944
  step.checkPlacement();
22915
22945
  return;
22916
22946
  }
22917
- var isTooltip = (step.type === 'tooltip' || step.attributes.calculatedType === 'tooltip');
22947
+ var isTooltip = isTooltipStep(step);
22918
22948
  if (isTooltip && wouldBeVisibleAfterAutoScroll(element) && elementMatchesContainsRules) {
22919
22949
  // the element was scrolled out of view, the guide should be invisible for now, but still "active"
22920
22950
  return;
@@ -23716,10 +23746,9 @@ function attachP1AdvanceActions(step, guide, pendo) {
23716
23746
  return;
23717
23747
  if (isBadge(guide) && !isWalkthrough(guide))
23718
23748
  return;
23719
- const { _ } = pendo;
23720
- const htmlLayoutType = _.get(step, 'attributes.buildingBlockLayoutType', step.buildingBlockLayoutType);
23721
- if (!_.contains([htmlLayoutType, step.type], 'tooltip'))
23749
+ if (!isTooltipStep(step))
23722
23750
  return;
23751
+ const { _ } = pendo;
23723
23752
  const advanceMethods = step.advanceMethod.split(',');
23724
23753
  _.each(advanceMethods, (method) => {
23725
23754
  if (method === 'element') {
@@ -23959,12 +23988,6 @@ var popoverStep = {
23959
23988
  script: popoverRuntimeScript
23960
23989
  };
23961
23990
 
23962
- function isTooltip({ _ }, step) {
23963
- const tooltip = 'tooltip';
23964
- return _.get(step, 'attributes.calculatedType') === tooltip ||
23965
- _.get(step, 'attributes.buildingBlockLayoutType', step.buildingBlockLayoutType) === tooltip ||
23966
- step.type === tooltip;
23967
- }
23968
23991
  function attachScrollHandlers({ _ }, step, scrollCallback) {
23969
23992
  const throttledScrollCallback = _.throttle(_.bind(scrollCallback, step, step), 10);
23970
23993
  step.attachEvent(window, 'scroll', throttledScrollCallback, true);
@@ -23992,7 +24015,7 @@ function attachStepScrollHandlers(step, guide, pendo) {
23992
24015
  // APP-68789
23993
24016
  if (isPreviewing() && step.element === dom.getBody())
23994
24017
  return;
23995
- if (isTooltip(pendo, step)) {
24018
+ if (isTooltipStep(step)) {
23996
24019
  const repositionCallback = step.domJson ? bbRepositionTooltip : p1RepositionTooltip;
23997
24020
  attachScrollHandlers(pendo, step, _.partial(tooltipOnScroll, pendo, step, repositionCallback));
23998
24021
  }
@@ -24691,11 +24714,17 @@ var canStepBeRendered = function (step) {
24691
24714
  if (targetElem && step.elementContainsRulesList && !doesElementMatchContainsRules(targetElem, step.elementContainsRulesList)) {
24692
24715
  return statusWriter(false, 'contains_rules');
24693
24716
  }
24694
- const embedSelector = _.get(step, 'guide.attributes.embedConfig.selector');
24695
- if (embedSelector && !dom(embedSelector).length) {
24696
- return false;
24717
+ const embedConfig = _.get(step, 'guide.attributes.embedConfig');
24718
+ if (embedConfig && embedConfig.selector) {
24719
+ const embedHost = dom(embedConfig.selector)[0];
24720
+ if (!embedHost) {
24721
+ return false;
24722
+ }
24723
+ if (embedConfig.method === 'replace' && isEmbedHostReplacedByAnotherGuide(step.guide, embedHost)) {
24724
+ return false;
24725
+ }
24697
24726
  }
24698
- var isTooltip = step.type === 'tooltip' || BuildingBlockTooltips.isBuildingBlockGuideRelativeToElement(step);
24727
+ var isTooltip = isTooltipStep(step) || BuildingBlockTooltips.isBuildingBlockGuideRelativeToElement(step);
24699
24728
  var isVisible = isElementVisible(elm);
24700
24729
  if (!isTooltip) {
24701
24730
  return statusWriter(isVisible, 'target_element');
@@ -24706,6 +24735,14 @@ var canStepBeRendered = function (step) {
24706
24735
  const wouldBeVisible = wouldBeVisibleAfterAutoScroll(elm);
24707
24736
  return statusWriter(wouldBeVisible, 'target_element_tooltip_scroll');
24708
24737
  };
24738
+ function isEmbedHostReplacedByAnotherGuide(guide, embedHost) {
24739
+ return _.some(getActiveGuides(), function (other) {
24740
+ if (other === guide || !_.isFunction(other.isShown) || !other.isShown())
24741
+ return false;
24742
+ const otherEmbedConfig = _.get(other, 'attributes.embedConfig');
24743
+ return !!otherEmbedConfig && otherEmbedConfig.method === 'replace' && dom(otherEmbedConfig.selector)[0] === embedHost;
24744
+ });
24745
+ }
24709
24746
  function pullContentsFromTargetElement(ele) {
24710
24747
  var wrappedEle = dom(ele);
24711
24748
  var eleText = wrappedEle.text() || ''; // .text() can return undefined
@@ -25549,9 +25586,12 @@ function hasLegacyGuides(guides, pendo) {
25549
25586
  if (pendo && pendo.designer)
25550
25587
  return true;
25551
25588
  return _.any(guides, function (guide) {
25552
- if (isForm(guide))
25589
+ if (isForm(guide) || guide.editorType === 'html')
25553
25590
  return false;
25554
25591
  return _.any(guide.steps, function (step) {
25592
+ // HTML steps load their content from htmlContentUrl and ship their own styles
25593
+ if (step.type === 'html')
25594
+ return false;
25555
25595
  return !(step.domUrl || step.domJsonpUrl || step.domJson);
25556
25596
  });
25557
25597
  });
@@ -29734,10 +29774,6 @@ const PluginAPI = {
29734
29774
  removeGlobalScript: GuideRuntime.removeGlobalScript
29735
29775
  },
29736
29776
  GuideActivity,
29737
- GuideEvents: {
29738
- stageGuideEvent,
29739
- createGuideEvent
29740
- },
29741
29777
  GuideLoop: {
29742
29778
  addUpdatePhase,
29743
29779
  removeUpdatePhase
@@ -29943,6 +29979,19 @@ function initIdentityEvents() {
29943
29979
  };
29944
29980
  }
29945
29981
 
29982
+ /**
29983
+ * The cookie consent tier, or tiers, the visitor has already agreed to. Each tier is the id of a cookie consent
29984
+ * level configured for your subscription, and determines what data the web SDK can collect: visitor identity,
29985
+ * analytics events, guides, and session replay. If not set, the web SDK runs without any consent restrictions.
29986
+ * Use `pendo.updateCookieConsent` to change consent after initialization. Read more about
29987
+ * [Cookie Consent Levels](/cookies/consent-levels).
29988
+ *
29989
+ * @access public
29990
+ * @category Config/Core
29991
+ * @name cookieConsentTiers
29992
+ * @default undefined
29993
+ * @type {string | string[]}
29994
+ */
29946
29995
  const CONSENT_TIERS = 'cookieConsentTiers';
29947
29996
  function applyCookieConsent(tiers, identity) {
29948
29997
  rememberConsentTiers(tiers);
@@ -29964,18 +30013,21 @@ function isCurrentCookieConsent(tiers) {
29964
30013
  }
29965
30014
  /**
29966
30015
  * Enforces the cookie consent policy a visitor has agreed to. The policy is defined by the subscription's cookie consent configuration,
29967
- * and is used to determine whether each product the web SDK may run.
30016
+ * and is used to determine what data the web SDK can collect. The new tiers replace any previously consented tiers,
30017
+ * including those passed to `pendo.initialize` as `cookieConsentTiers`, and are shared with other frames running the web SDK for the same application.
29968
30018
  *
29969
30019
  * A visitor who was not being tracked has no identity for the web SDK to resume, so pass one in
29970
30020
  * `identity` when the new tiers start allowing identity. It is ignored otherwise.
29971
30021
  *
30022
+ * Read more about [Cookie Consent Levels](/cookies/consent-levels).
30023
+ *
29972
30024
  * @access public
29973
30025
  * @category Core
29974
30026
  * @param {string | string[]} tiers tier or tiers the visitor consented to
29975
30027
  * @param {object} [identity] visitor and account to identify, in the same shape as
29976
30028
  * `pendo.updateOptions` -- applied only when consent moves a do-not-track visitor to a tier
29977
30029
  * that permits identity
29978
- * @returns {object} map of product to its resolved value -- `guides` and `identity` are
30030
+ * @returns {object} what data is now collected -- `guides` and `identity` are
29979
30031
  * booleans (identity disabled means DNT), `textCollection` is `none`/`whitelist`/`all`,
29980
30032
  * `analytics` and `guideAnalytics` are each an array of allowed event types
29981
30033
  * @example
@@ -34011,7 +34063,11 @@ var GuideDisplay = (function () {
34011
34063
  return false;
34012
34064
  }
34013
34065
  step.lock();
34014
- return AsyncContent.fetchContent(step).then(function () {
34066
+ // Prefer the step's own fetchContent so a plugin-defined step (e.g. HTML
34067
+ // guides) can supply its content; for building-block steps it is
34068
+ // AsyncContent.fetchContent anyway
34069
+ var contentPromise = _.isFunction(step.fetchContent) ? step.fetchContent() : AsyncContent.fetchContent(step);
34070
+ return contentPromise.then(function () {
34015
34071
  if (step.type !== 'whatsnew' && !step.isShown()) {
34016
34072
  return false;
34017
34073
  }
@@ -37040,6 +37096,16 @@ function registerModules(store) {
37040
37096
  store.registerModule('networkUrl', NetworkUrlModule);
37041
37097
  }
37042
37098
 
37099
+ // Shared by guide automations (ActionAutomation) and the agent-workflows invoke_action tool, so an
37100
+ // element is clicked the same way whichever of them drives it.
37101
+ function simulateClick(element) {
37102
+ element.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true, cancelable: true }));
37103
+ element.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true }));
37104
+ element.dispatchEvent(new MouseEvent('pointerup', { bubbles: true, cancelable: true }));
37105
+ element.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true }));
37106
+ element.click();
37107
+ }
37108
+
37043
37109
  var ActionAutomation = (function () {
37044
37110
  let _;
37045
37111
  var pendoGlobal;
@@ -37063,7 +37129,7 @@ var ActionAutomation = (function () {
37063
37129
  getElement,
37064
37130
  getValue,
37065
37131
  injectText,
37066
- simulateClick,
37132
+ simulateClick: simulateClick$1,
37067
37133
  isAutomationInQueue,
37068
37134
  popQueue,
37069
37135
  setActive
@@ -37112,12 +37178,8 @@ var ActionAutomation = (function () {
37112
37178
  changeEvent.simulated = true; // for React ≤ 15.6.0
37113
37179
  element.dispatchEvent(changeEvent);
37114
37180
  }
37115
- function simulateClick(element) {
37116
- element.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true, cancelable: true }));
37117
- element.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true }));
37118
- element.dispatchEvent(new MouseEvent('pointerup', { bubbles: true, cancelable: true }));
37119
- element.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true }));
37120
- element.click();
37181
+ function simulateClick$1(element) {
37182
+ simulateClick(element);
37121
37183
  }
37122
37184
  function isAutomationInQueue(automation) {
37123
37185
  return !!_.find(this.automationQueue, function (item) {
@@ -41557,8 +41619,9 @@ var P1GuidePlugin = (function () {
41557
41619
  // Adds a close button to the guide
41558
41620
  function CloseButton(guide) {
41559
41621
  var step = this;
41560
- // We only want to have the agent add close buttons to legacy guides, not building block inserts
41561
- if (step.domJson || step.domJsonpUrl)
41622
+ // We only want to have the agent add close buttons to legacy guides, not building block
41623
+ // inserts or HTML guides (which have no domJson either)
41624
+ if (step.domJson || step.domJsonpUrl || step.type === 'html')
41562
41625
  return step;
41563
41626
  step.after('render', function () {
41564
41627
  if (!step.guideElement || !step.guideElement.length)
@@ -41575,7 +41638,7 @@ var P1GuidePlugin = (function () {
41575
41638
  // Adds pendo credits to the guide unless disabled
41576
41639
  function Credits() {
41577
41640
  var step = this;
41578
- if (!step.hideCredits && !step.domJson && !step.domJsonpUrl && !isForm(step.guide)) {
41641
+ if (!step.hideCredits && !step.domJson && !step.domJsonpUrl && step.type !== 'html' && !isForm(step.guide)) {
41579
41642
  step.after('render', function () {
41580
41643
  _addCredits(step.guideElement[0]);
41581
41644
  });
@@ -52817,6 +52880,42 @@ class SessionRecorder {
52817
52880
  return null;
52818
52881
  }
52819
52882
  }
52883
+ /**
52884
+ * Run URL attributes in snapshot and mutation events through the Location API attribute transforms, the same
52885
+ * ones applied to elementPath.
52886
+ *
52887
+ * @access private
52888
+ * @param event The rrweb event being handled
52889
+ */
52890
+ applyAttributeTransforms(event) {
52891
+ const _ = this.pendo._;
52892
+ if (_.isEmpty(_.get(this.api.store.state, 'nodeAttr.transforms')))
52893
+ return;
52894
+ const getAttribute = this.api.store.getters['nodeAttr/getAttribute']();
52895
+ const transformAttributes = (attributes) => {
52896
+ _.each(attributes, (value, name) => {
52897
+ // same as rrweb's absolutizing, leave same-document refs (svg <use href="#id">), data: and blob: URLs alone
52898
+ if (!_.isString(value) || /^(#|data:|blob:)/.test(value))
52899
+ return;
52900
+ // rrweb renames an iframe's src to rr_src when it can't access the frame's document
52901
+ const attrName = name === 'rr_src' ? 'src' : name;
52902
+ attributes[name] = getAttribute({ [attrName]: value }, attrName);
52903
+ });
52904
+ };
52905
+ const transformNode = (node) => {
52906
+ if (!node)
52907
+ return;
52908
+ transformAttributes(node.attributes);
52909
+ _.each(node.childNodes, transformNode);
52910
+ };
52911
+ if (event.type === EVENT_TYPES.FULL_SNAPSHOT) {
52912
+ transformNode(event.data.node);
52913
+ }
52914
+ else if (event.type === EVENT_TYPES.INCREMENTAL_SNAPSHOT && event.data.source === EVENT_TYPES.INCREMENTAL_SOURCE_MUTATION) {
52915
+ _.each(event.data.adds, (add) => transformNode(add.node));
52916
+ _.each(event.data.attributes, (item) => transformAttributes(item.attributes));
52917
+ }
52918
+ }
52820
52919
  /**
52821
52920
  * Handle new rrweb events coming in. This will also make sure that we are properly sending a "keyframe"
52822
52921
  * as the BE expects it. A "keyframe" should consist of only the events needed to start a recording. This includes
@@ -52885,6 +52984,7 @@ class SessionRecorder {
52885
52984
  }
52886
52985
  this.send();
52887
52986
  }
52987
+ this.applyAttributeTransforms(event);
52888
52988
  this.buffer.push(event);
52889
52989
  if (isSnapshot) {
52890
52990
  this.lastKeyFrameTime = event.timestamp;