@pendo/agent 2.328.1 → 2.329.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.
@@ -2916,7 +2916,15 @@ var ConfigReader = (function () {
2916
2916
  addOption('disableAutoInitialize');
2917
2917
  /**
2918
2918
  * If set to `true` the web SDK will wait for the host application to be both loaded and visible before
2919
- * starting the initialization process.
2919
+ * starting the initialization process. Only the first call to `initialize` is honored while waiting
2920
+ * for visibility; subsequent calls are rejected and logged. This setting takes precedence over
2921
+ * `initializeImmediately`.
2922
+ *
2923
+ * This is a server-delivered setting and cannot be provided through the options passed to
2924
+ * `pendo.initialize`: the visibility gate runs before those options are read.
2925
+ *
2926
+ * This relies on the Page Visibility API. In browsers that do not support `document.visibilityState`,
2927
+ * enabling this option will defer initialization indefinitely.
2920
2928
  *
2921
2929
  * @access public
2922
2930
  * @category Config/Core
@@ -2924,7 +2932,7 @@ var ConfigReader = (function () {
2924
2932
  * @default false
2925
2933
  * @type {boolean}
2926
2934
  */
2927
- addOption('initializeWhenVisible', [SNIPPET_SRC, PENDO_CONFIG_SRC], false);
2935
+ addOption('initializeWhenVisible', [PENDO_CONFIG_SRC], false);
2928
2936
  /**
2929
2937
  * Although the name refers to cookies, if set to `true` the web SDK will not persist any data in local
2930
2938
  * storage or cookies and will rely only on memory.
@@ -4002,8 +4010,8 @@ let SERVER = '';
4002
4010
  let ASSET_HOST = '';
4003
4011
  let ASSET_PATH = '';
4004
4012
  let DESIGNER_SERVER = '';
4005
- let VERSION = '2.328.1_';
4006
- let PACKAGE_VERSION = '2.328.1';
4013
+ let VERSION = '2.329.0_';
4014
+ let PACKAGE_VERSION = '2.329.0';
4007
4015
  let LOADER = 'xhr';
4008
4016
  /* eslint-enable web-sdk-eslint-rules/no-gulp-env-references */
4009
4017
  /**
@@ -20089,6 +20097,7 @@ var GuideStateModule = (function () {
20089
20097
  storageKey: LAST_STEP_ADVANCED_COOKIE,
20090
20098
  guideRequestExpiration: 60 * 60 * 1000,
20091
20099
  scopedStorageKey: null,
20100
+ scopedThrottlingStorageKeys: {},
20092
20101
  receivedStateChangeAt: null,
20093
20102
  receivedLastGuideStepSeen: null,
20094
20103
  lastGuideStepSeen: null,
@@ -20111,6 +20120,11 @@ var GuideStateModule = (function () {
20111
20120
  */
20112
20121
  context.getters.storage().registry.addLocal(LAST_STEP_ADVANCED_COOKIE);
20113
20122
  context.commit('setScopedStorageKey', getPendoCookieKey(context.state.storageKey));
20123
+ var scopedThrottlingStorageKeys = {};
20124
+ _.each(THROTTLING_STATE, function (throttlingStorageKey) {
20125
+ scopedThrottlingStorageKeys[throttlingStorageKey] = getPendoCookieKey(throttlingStorageKey);
20126
+ });
20127
+ context.commit('setScopedThrottlingStorageKeys', scopedThrottlingStorageKeys);
20114
20128
  Events.identify.on(function (evt) {
20115
20129
  if (wasSessionCleared(evt)) {
20116
20130
  removeIdentificationCookies([LAST_STEP_ADVANCED_COOKIE]);
@@ -20149,11 +20163,21 @@ var GuideStateModule = (function () {
20149
20163
  });
20150
20164
  }
20151
20165
  }
20166
+ context.dispatch('loadThrottling');
20167
+ },
20168
+ loadThrottling(context) {
20169
+ const storage = context.getters.storage();
20152
20170
  _.each(THROTTLING_STATE, function (throttlingStorageKey) {
20153
20171
  const value = storage.read(throttlingStorageKey);
20154
20172
  context.dispatch('updateThrottlingState', { name: throttlingStorageKey, value });
20155
20173
  });
20156
20174
  },
20175
+ applyThrottling(context) {
20176
+ _.each(THROTTLING_STATE, function (throttlingStorageKey) {
20177
+ pendo$1[throttlingStorageKey] = applyTimerCache(pendo$1[throttlingStorageKey], context.state[throttlingStorageKey]);
20178
+ context.dispatch('updateThrottlingState', { name: throttlingStorageKey, value: pendo$1[throttlingStorageKey] });
20179
+ });
20180
+ },
20157
20181
  forceExpire(context) {
20158
20182
  _.each(context.state.steps, function (stepState, stepId) {
20159
20183
  context.commit('expireStepState', stepId);
@@ -20229,10 +20253,7 @@ var GuideStateModule = (function () {
20229
20253
  if (mostRecentLastGuideStepSeen) {
20230
20254
  context.dispatch('updateLastGuideStepSeen', _.extend({}, context.state.lastGuideStepSeen, mostRecentLastGuideStepSeen));
20231
20255
  }
20232
- _.each(THROTTLING_STATE, function (throttlingStorageKey) {
20233
- pendo$1[throttlingStorageKey] = applyTimerCache(pendo$1[throttlingStorageKey], context.state[throttlingStorageKey]);
20234
- context.dispatch('updateThrottlingState', { name: throttlingStorageKey, value: pendo$1[throttlingStorageKey] });
20235
- });
20256
+ context.dispatch('applyThrottling');
20236
20257
  },
20237
20258
  receiveLastGuideStepSeen(context, lastGuideStepSeen) {
20238
20259
  context.commit('setReceivedLastGuideStepSeen', lastGuideStepSeen);
@@ -20295,6 +20316,10 @@ var GuideStateModule = (function () {
20295
20316
  }
20296
20317
  }
20297
20318
  }
20319
+ else if (_.contains(_.values(context.state.scopedThrottlingStorageKeys), storageEvent.key)) {
20320
+ context.dispatch('loadThrottling');
20321
+ context.dispatch('applyThrottling');
20322
+ }
20298
20323
  },
20299
20324
  regainFocus(context) {
20300
20325
  var tabLostFocus = context.getters.tabLostFocus();
@@ -20322,6 +20347,9 @@ var GuideStateModule = (function () {
20322
20347
  setScopedStorageKey(state, scopedStorageKey) {
20323
20348
  state.scopedStorageKey = scopedStorageKey;
20324
20349
  },
20350
+ setScopedThrottlingStorageKeys(state, scopedThrottlingStorageKeys) {
20351
+ state.scopedThrottlingStorageKeys = scopedThrottlingStorageKeys;
20352
+ },
20325
20353
  setLastGuideStepSeen(state, lastGuideStepSeen) {
20326
20354
  state.lastGuideStepSeen = lastGuideStepSeen;
20327
20355
  },
@@ -22089,22 +22117,6 @@ var whenLoadedCall = function (callback, win) {
22089
22117
  }
22090
22118
  return _.noop;
22091
22119
  };
22092
- const whenVisibleCall = (callback, win = window) => {
22093
- const { document } = win;
22094
- const waitForVis = ConfigReader.get('initializeWhenVisible', false);
22095
- if (!waitForVis || document.visibilityState === 'visible') {
22096
- callback();
22097
- return _.noop;
22098
- }
22099
- const stopVisListener = attachEventInternal(document, 'visibilitychange', () => {
22100
- if (document.visibilityState === 'visible') {
22101
- callback();
22102
- // need to shut this down immediately as visibility can continue to change
22103
- stopVisListener();
22104
- }
22105
- });
22106
- return stopVisListener;
22107
- };
22108
22120
 
22109
22121
  class GuideTypeIdentifier {
22110
22122
  constructor(identificationFn, typeName) {
@@ -23578,13 +23590,13 @@ var onGuideDismissed = function (evt, step) {
23578
23590
  var seenReason = firstStep && firstStep.seenReason;
23579
23591
  var language = currentGuide && currentGuide.language;
23580
23592
  var dismissCount = _.get(step, 'dismissCount', 0) + 1;
23581
- dismissedGuide(guideId, stepId, get_visitor_id(), seenReason, language, dismissCount);
23582
23593
  var now = getNow();
23583
- _updateGuideStepStatus(guideId, stepId, 'dismissed', now, dismissCount);
23584
- // maintain latestDismissedAutoAt client-side
23594
+ // maintain latestDismissedAutoAt client-side before guideDismissed writes lastStepAdvanced
23585
23595
  if (shouldAffectThrottling(currentGuide, seenReason)) {
23586
23596
  writeThrottlingStateCache(now, THROTTLING_STATE.DISMISSED);
23587
23597
  }
23598
+ dismissedGuide(guideId, stepId, get_visitor_id(), seenReason, language, dismissCount);
23599
+ _updateGuideStepStatus(guideId, stepId, 'dismissed', now, dismissCount);
23588
23600
  step.hide();
23589
23601
  if (!isGuideShown()) {
23590
23602
  stopGuides();
@@ -23640,12 +23652,12 @@ var onGuideSnoozed = function (evt, step, snoozeDuration) {
23640
23652
  log.info('snoozing guide for ' + snoozeDuration + ' ms');
23641
23653
  var snoozeEndTime = now + snoozeDuration;
23642
23654
  step.snoozeEndTime = snoozeEndTime;
23643
- snoozedGuide(guideId, stepId, visitorId, seenReason, language, snoozeDuration);
23644
- _updateGuideStepStatus(guideId, stepId, 'snoozed', now);
23645
- // maintain latestSnoozedAutoAt client-side
23655
+ // maintain latestSnoozedAutoAt client-side before guideSnoozed writes lastStepAdvanced
23646
23656
  if (shouldAffectThrottling(guide, seenReason)) {
23647
23657
  writeThrottlingStateCache(now, THROTTLING_STATE.SNOOZED);
23648
23658
  }
23659
+ snoozedGuide(guideId, stepId, visitorId, seenReason, language, snoozeDuration);
23660
+ _updateGuideStepStatus(guideId, stepId, 'snoozed', now);
23649
23661
  step.hide();
23650
23662
  if (!isGuideShown()) {
23651
23663
  stopGuides();
@@ -23794,15 +23806,15 @@ var onGuideAdvanced = function (evt, step, isIntermediateStep) {
23794
23806
  if (currentGuide && _.last(currentGuide.steps).id === stepId) {
23795
23807
  dismissCount = _.get(step, 'dismissCount', 0) + 1;
23796
23808
  }
23797
- log.info('advancing guide');
23798
- advancedGuide(guideId, stepId, get_visitor_id(), seenReason, language, isIntermediateStep, destinationStepId, dismissCount);
23799
- log.info('update guide status');
23800
23809
  var now = new Date().getTime();
23801
- _updateGuideStepStatus(guideId, stepId, 'advanced', now, dismissCount, destinationStepId);
23802
- // maintain finalAdvancedAutoAt client-side
23810
+ // maintain finalAdvancedAutoAt client-side before guideAdvanced writes lastStepAdvanced
23803
23811
  if (shouldAffectThrottling(currentGuide, seenReason)) {
23804
23812
  writeThrottlingStateCache(now, THROTTLING_STATE.ADVANCED);
23805
23813
  }
23814
+ log.info('advancing guide');
23815
+ advancedGuide(guideId, stepId, get_visitor_id(), seenReason, language, isIntermediateStep, destinationStepId, dismissCount);
23816
+ log.info('update guide status');
23817
+ _updateGuideStepStatus(guideId, stepId, 'advanced', now, dismissCount, destinationStepId);
23806
23818
  log.info('stop guide');
23807
23819
  stopGuides();
23808
23820
  log.info('start guides');
@@ -26043,7 +26055,7 @@ function getWhiteLabelSettings(config) {
26043
26055
  var whiteLabelSettings = ConfigReader.get('whiteLabelSettings');
26044
26056
  if (!whiteLabelSettings && config && config.ux === 'novus') {
26045
26057
  whiteLabelSettings = {
26046
- logoUrl: 'https://novus.pendo.io/novus-square-icon.svg',
26058
+ logoUrl: 'https://novus.pendo.io/branding/novus-vector-white.svg',
26047
26059
  logoStyle: {
26048
26060
  maxWidth: '40px',
26049
26061
  maxHeight: '40px'
@@ -28513,6 +28525,7 @@ const PluginAPI = {
28513
28525
  trim,
28514
28526
  base64EncodeString,
28515
28527
  parseUrl,
28528
+ testPageRule,
28516
28529
  addInlineStyles: _.partial(addInlineStyles, ConfigReader),
28517
28530
  getNow,
28518
28531
  escapeRegExp
@@ -29016,6 +29029,44 @@ function applyDoNotTrackConfigOverrides(options) {
29016
29029
  // ----------------------------------------------------------------------------------
29017
29030
  let initializeCounter = 0;
29018
29031
  const initializeImmediately = 'initializeImmediately';
29032
+ const initializeWhenVisible = 'initializeWhenVisible';
29033
+ const teardownFns = [];
29034
+ // State for the visibility gate. Only the first gated initialize() call is
29035
+ // honored — it attaches the single visibilitychange listener and its arguments
29036
+ // replay once the document becomes visible. Any later calls while the gate is
29037
+ // pending are rejected and ignored. Must live at module scope so later
29038
+ // initialize() calls can see a gate is active; null when no gate is active.
29039
+ let pendingInitializeArgs = null;
29040
+ function shouldGateOnVisibility() {
29041
+ return ConfigReader.get(initializeWhenVisible, false) &&
29042
+ typeof document !== 'undefined' &&
29043
+ document.visibilityState !== 'visible';
29044
+ }
29045
+ function gateInitializeOnVisibility(args) {
29046
+ if (pendingInitializeArgs !== null) {
29047
+ log.warn('pendo.initialize call rejected: an earlier call is already waiting for the document to become visible.');
29048
+ return;
29049
+ }
29050
+ pendingInitializeArgs = args;
29051
+ let stopVisibilityListener = attachEvent(document, 'visibilitychange', () => {
29052
+ if (document.visibilityState !== 'visible')
29053
+ return;
29054
+ if (stopVisibilityListener) {
29055
+ stopVisibilityListener();
29056
+ stopVisibilityListener = null;
29057
+ }
29058
+ const pendingArgs = pendingInitializeArgs;
29059
+ pendingInitializeArgs = null;
29060
+ initialize.apply(null, pendingArgs);
29061
+ });
29062
+ teardownFns.push(() => {
29063
+ if (stopVisibilityListener) {
29064
+ stopVisibilityListener();
29065
+ stopVisibilityListener = null;
29066
+ }
29067
+ pendingInitializeArgs = null;
29068
+ });
29069
+ }
29019
29070
  /**
29020
29071
  * Initializes the Pendo Web SDK in a browser window. This function only needs to be called once per page load. Any subsequent calls, without first having called `teardown`, will be ignored.
29021
29072
  * Once the web SDK has been initialized, any updates to identity or metadata should be done using `identify` or `updateOptions`.
@@ -29048,8 +29099,16 @@ const initializeImmediately = 'initializeImmediately';
29048
29099
  }
29049
29100
  });
29050
29101
  */
29051
- const teardownFns = [];
29052
29102
  function initialize(options) {
29103
+ if (shouldGateOnVisibility()) {
29104
+ try {
29105
+ gateInitializeOnVisibility(_.toArray(arguments));
29106
+ }
29107
+ catch (e) {
29108
+ log.critical('pendo.initialize failed while gating on visibility.', e);
29109
+ }
29110
+ return;
29111
+ }
29053
29112
  if (document.readyState !== 'complete' && !(_.get(options, initializeImmediately) || ConfigReader.get(initializeImmediately))) {
29054
29113
  try {
29055
29114
  enqueueCall(pendo$1, 'initialize', arguments);
@@ -29303,9 +29362,7 @@ function startup(callQueue, autoInitialize) {
29303
29362
  autoInitialize();
29304
29363
  }
29305
29364
  else {
29306
- teardownFns.push(whenLoadedCall(() => {
29307
- teardownFns.push(whenVisibleCall(autoInitialize));
29308
- }));
29365
+ teardownFns.push(whenLoadedCall(autoInitialize));
29309
29366
  }
29310
29367
  }
29311
29368
  /**
@@ -40212,364 +40269,6 @@ class DOMPrompt {
40212
40269
  }
40213
40270
  }
40214
40271
 
40215
- const ASSISTANT_MESSAGE = 'assistantMessage';
40216
- const CONVERSATION_ID_URL_PATTERN = 'conversationIdUrlPattern';
40217
- const MESSAGE_ID_ATTR = 'messageIdAttr';
40218
- const MODEL_USED_ATTR = 'modelUsedAttr';
40219
- const REACTION_ACTIVE = 'reactionActive';
40220
- const STREAMING_ACTIVE = 'streamingActive';
40221
- const STREAMING_ACTIVE_ATTR = 'streamingActiveAttr';
40222
- const THUMB_DOWN = 'thumbDown';
40223
- const THUMB_UP = 'thumbUp';
40224
- const TURN_CONTAINER = 'turnContainer';
40225
- const TURN_ATTR = 'turnAttr';
40226
- const USER_MESSAGE = 'userMessage';
40227
- const CUSTOM_AGENT_ID_URL_PATTERN = 'customAgentIdUrlPattern';
40228
- const CUSTOM_AGENT_NAME = 'customAgentName';
40229
- const REQUIRED_SELECTORS = [
40230
- ASSISTANT_MESSAGE,
40231
- CONVERSATION_ID_URL_PATTERN,
40232
- MESSAGE_ID_ATTR,
40233
- STREAMING_ACTIVE,
40234
- TURN_CONTAINER,
40235
- TURN_ATTR,
40236
- USER_MESSAGE
40237
- ];
40238
- const STREAMING_END_SETTLE_MS = 500;
40239
- const SUBMISSION_START_RETRY_MS = 1000;
40240
- const SUBMISSION_START_MAX_ATTEMPTS = 4;
40241
- class DOMConversation {
40242
- // Returns the list of required selector types that are missing or empty
40243
- // in the given cssSelectors config. An empty array means the config is
40244
- // valid for instantiation.
40245
- static validateConfig(cssSelectors) {
40246
- if (!Array.isArray(cssSelectors)) {
40247
- return REQUIRED_SELECTORS.slice();
40248
- }
40249
- const present = new Set();
40250
- for (const cfg of cssSelectors) {
40251
- if (!cfg || !cfg.type || !cfg.cssSelector)
40252
- continue;
40253
- if (cfg.type === CONVERSATION_ID_URL_PATTERN) {
40254
- try {
40255
- RegExp(cfg.cssSelector);
40256
- }
40257
- catch (e) {
40258
- continue;
40259
- }
40260
- }
40261
- present.add(cfg.type);
40262
- }
40263
- return REQUIRED_SELECTORS.filter((r) => !present.has(r));
40264
- }
40265
- static supportedPreset(preset) {
40266
- return preset === 'chatgpt-full';
40267
- }
40268
- constructor(pendo, PluginAPI, id, privacyFilters, cssSelectors) {
40269
- this.selectors = {};
40270
- this.listeners = [];
40271
- this.isActive = true;
40272
- this.observers = [];
40273
- this.wasStreaming = false;
40274
- this.streamingEndTimer = null;
40275
- this.submissionStartRetryTimer = null;
40276
- this.requestNode = null;
40277
- this.conversationIdRegex = null;
40278
- this.customAgentIdRegex = null;
40279
- this.lastReturnedMessageId = null;
40280
- this.dom = pendo.dom;
40281
- this._ = pendo._;
40282
- this.api = PluginAPI;
40283
- this.Sizzle = pendo.Sizzle;
40284
- this.id = id;
40285
- this.setFilters(privacyFilters);
40286
- if (!this._.isArray(cssSelectors)) {
40287
- this.api.log.error(`cssSelectors must be an array, received: ${typeof cssSelectors}`);
40288
- cssSelectors = [];
40289
- }
40290
- this._.each(cssSelectors, (cfg) => {
40291
- if (cfg && cfg.type) {
40292
- this.selectors[cfg.type] = cfg.cssSelector;
40293
- }
40294
- });
40295
- this.conversationIdRegex = new RegExp(this.selectors[CONVERSATION_ID_URL_PATTERN]);
40296
- const customAgentIdUrlPattern = this.selectors[CUSTOM_AGENT_ID_URL_PATTERN];
40297
- if (customAgentIdUrlPattern) { // this is optional
40298
- try {
40299
- this.customAgentIdRegex = new RegExp(customAgentIdUrlPattern);
40300
- }
40301
- catch (error) {
40302
- this.api.log.error(`bad customAgentIdUrlPattern ${customAgentIdUrlPattern}`, { error });
40303
- }
40304
- }
40305
- this.root = document.body;
40306
- this.setupReactionListener();
40307
- this.setupStreamingObserver();
40308
- }
40309
- setupReactionListener() {
40310
- if (!this.findSelector(THUMB_UP) && !this.findSelector(THUMB_DOWN))
40311
- return;
40312
- this.reactionClickHandler = this.handleReactionClick.bind(this);
40313
- this.root.addEventListener('click', this.reactionClickHandler, true);
40314
- }
40315
- handleReactionClick(evt) {
40316
- const target = evt.target;
40317
- if (!target || target.nodeType !== 1)
40318
- return;
40319
- const upSelector = this.findSelector(THUMB_UP);
40320
- const downSelector = this.findSelector(THUMB_DOWN);
40321
- const thumb = this.dom(target).closest(`${upSelector}, ${downSelector}`);
40322
- if (!thumb.length)
40323
- return;
40324
- const isUp = this.Sizzle.matchesSelector(thumb[0], upSelector);
40325
- const activeSelector = this.findSelector(REACTION_ACTIVE);
40326
- const wasPressed = activeSelector && this.Sizzle.matchesSelector(thumb[0], activeSelector);
40327
- const direction = isUp ? 'positive' : 'negative';
40328
- const content = wasPressed ? 'unreact' : direction;
40329
- const assistantNode = thumb.closest(this.findSelector(TURN_CONTAINER))
40330
- .find(this.findSelector(ASSISTANT_MESSAGE));
40331
- this.emit('user_reaction', {
40332
- agentId: this.id,
40333
- messageId: this.getMessageId(assistantNode),
40334
- content,
40335
- privacyFilterApplied: false
40336
- });
40337
- }
40338
- // observe the streaming indicator
40339
- setupStreamingObserver() {
40340
- this.wasStreaming = this.select(STREAMING_ACTIVE).length > 0;
40341
- this.stopStreamingEndTimer();
40342
- const MutationObserver = getZoneSafeMethod('MutationObserver');
40343
- const observer = new MutationObserver(this.handleMutation.bind(this));
40344
- const attrName = this.findSelector(STREAMING_ACTIVE_ATTR);
40345
- observer.observe(this.root, {
40346
- childList: true,
40347
- subtree: true,
40348
- attributes: true,
40349
- attributeFilter: attrName ? [attrName] : undefined
40350
- });
40351
- this.observers.push(observer);
40352
- }
40353
- // look for changes in the state of the streaming indicator.
40354
- // streaming started -> a prompt has been submitted
40355
- // streaming ended -> got a response
40356
- // we don't send the prompt immediately when it's submitted because it might not have a
40357
- // conversation id yet.
40358
- // we don't send the agent_response immediately when the streaming indicator is cleared
40359
- // because it clears slightly before the final text chunk is committed to the DOM so the
40360
- // end-handling is deferred by a short settle window
40361
- handleMutation() {
40362
- const isStreaming = this.select(STREAMING_ACTIVE).length > 0;
40363
- if (isStreaming === this.wasStreaming)
40364
- return;
40365
- if (isStreaming) { // started streaming
40366
- if (!this.streamingEndTimer) {
40367
- this.onSubmissionStart();
40368
- }
40369
- else {
40370
- // stream restarted during the settle window (multi-phase response).
40371
- // treat as a continuation of the prior request, not a new submission.
40372
- // we'll handle it next time streaming stops
40373
- this.stopStreamingEndTimer();
40374
- }
40375
- }
40376
- else { // finished streaming
40377
- this.startStreamingEndTimer();
40378
- }
40379
- this.wasStreaming = isStreaming;
40380
- }
40381
- onSubmissionStart(attempt = 1) {
40382
- this.requestNode = this.findLastRequestNode();
40383
- if (this.requestNode) {
40384
- this.handleUserMessage(this.requestNode);
40385
- return;
40386
- }
40387
- // URL hasn't flipped yet to include the conversation id on a fresh chat
40388
- // retry, if that still fails, onSubmissionEnd handles it
40389
- if (attempt < SUBMISSION_START_MAX_ATTEMPTS) {
40390
- this.startSubmissionStartRetryTimer(attempt + 1);
40391
- }
40392
- }
40393
- onSubmissionEnd() {
40394
- this.stopSubmissionStartRetryTimer();
40395
- let requestNode = this.requestNode;
40396
- this.requestNode = null;
40397
- if (!requestNode) {
40398
- // onSubmissionStart didn't send, send it now
40399
- requestNode = this.findLastRequestNode();
40400
- if (!requestNode)
40401
- return;
40402
- this.handleUserMessage(requestNode);
40403
- }
40404
- const requestTurn = this.findTurnNumber(requestNode);
40405
- if (requestTurn === null)
40406
- return;
40407
- const assistantNodes = this.select(ASSISTANT_MESSAGE);
40408
- const toEmit = [];
40409
- for (let i = assistantNodes.length - 1; i >= 0; i--) {
40410
- const n = this.findTurnNumber(this.dom(assistantNodes[i]));
40411
- if (n === null)
40412
- continue;
40413
- if (n <= requestTurn)
40414
- break;
40415
- toEmit.push(assistantNodes[i]);
40416
- }
40417
- // emit in chronological order (reverse of collection order)
40418
- for (let i = toEmit.length - 1; i >= 0; i--) {
40419
- this.handleAssistantMessage(this.dom(toEmit[i]));
40420
- }
40421
- }
40422
- extractContent(node) {
40423
- const rawContent = node.text().trim();
40424
- const content = this.applyPrivacyFilter(rawContent);
40425
- return { content, privacyFilterApplied: content !== rawContent };
40426
- }
40427
- getMessageId(node) {
40428
- return node.attr(this.findSelector(MESSAGE_ID_ATTR));
40429
- }
40430
- handleUserMessage(node) {
40431
- this.emit('prompt', Object.assign({ agentId: this.id, messageId: this.getMessageId(node) }, this.extractContent(node)));
40432
- }
40433
- handleAssistantMessage(node) {
40434
- const modelUsedAttr = this.findSelector(MODEL_USED_ATTR);
40435
- const modelUsed = modelUsedAttr && node.attr(modelUsedAttr);
40436
- this.emit('agent_response', Object.assign({ agentId: this.id, messageId: this.getMessageId(node), agentModelsUsed: modelUsed ? [modelUsed] : [] }, this.extractContent(node)));
40437
- }
40438
- findLastRequestNode() {
40439
- if (!this.getConversationId())
40440
- return null;
40441
- const node = this._.last(this.select(USER_MESSAGE));
40442
- if (!node)
40443
- return null;
40444
- const $node = this.dom(node);
40445
- const messageId = this.getMessageId($node);
40446
- if (!messageId)
40447
- return null;
40448
- if (messageId === this.lastReturnedMessageId)
40449
- return null;
40450
- this.lastReturnedMessageId = messageId;
40451
- return $node;
40452
- }
40453
- findTurnNumber(node) {
40454
- const turnSelector = this.findSelector(TURN_CONTAINER);
40455
- const turnAttr = this.findSelector(TURN_ATTR);
40456
- const turn = node.closest(turnSelector).attr(turnAttr);
40457
- if (!turn)
40458
- return null;
40459
- const seqMatch = String(turn).match(/\d+/);
40460
- return seqMatch ? parseInt(seqMatch[0], 10) : null;
40461
- }
40462
- findSelector(type) {
40463
- return this.selectors[type];
40464
- }
40465
- select(type) {
40466
- return this.dom(this.findSelector(type), this.root);
40467
- }
40468
- getConversationId() {
40469
- const m = location.href.match(this.conversationIdRegex);
40470
- if (!m)
40471
- return null;
40472
- return m[1] !== undefined ? m[1] : m[0];
40473
- }
40474
- getCustomAgentId() {
40475
- if (!this.customAgentIdRegex)
40476
- return undefined;
40477
- const m = location.href.match(this.customAgentIdRegex);
40478
- if (!m)
40479
- return undefined;
40480
- return m[1] !== undefined ? m[1] : m[0];
40481
- }
40482
- getCustomAgentName() {
40483
- if (!this.findSelector(CUSTOM_AGENT_NAME))
40484
- return '';
40485
- const node = this.select(CUSTOM_AGENT_NAME);
40486
- if (!node.length)
40487
- return '';
40488
- return node.text().trim();
40489
- }
40490
- addCustomAgentInfo(eventPayload) {
40491
- const customAgentId = this.getCustomAgentId();
40492
- if (!customAgentId)
40493
- return;
40494
- eventPayload.customAgentId = customAgentId;
40495
- const customAgentName = this.getCustomAgentName();
40496
- if (customAgentName) {
40497
- eventPayload.customAgentName = customAgentName;
40498
- }
40499
- }
40500
- setFilters(candidateFilter) {
40501
- if (!candidateFilter) {
40502
- this.privacyFilters = null;
40503
- return null;
40504
- }
40505
- try {
40506
- this.privacyFilters = new RegExp(candidateFilter, 'gmi');
40507
- }
40508
- catch (e) {
40509
- this.privacyFilters = null;
40510
- this.api.log.error(e);
40511
- }
40512
- return this.privacyFilters;
40513
- }
40514
- applyPrivacyFilter(candidateValue, filters = null) {
40515
- const filtersToUse = filters || this.privacyFilters;
40516
- if (!filtersToUse || !this._.isRegExp(filtersToUse))
40517
- return candidateValue;
40518
- return candidateValue.replace(filtersToUse, 'redacted');
40519
- }
40520
- onSubmit(callback) {
40521
- this.listeners.push(callback);
40522
- }
40523
- emit(eventType, eventPayload) {
40524
- eventPayload.conversationId = this.getConversationId();
40525
- this.addCustomAgentInfo(eventPayload);
40526
- this._.each(this.listeners, (cb) => cb(eventType, eventPayload));
40527
- }
40528
- startStreamingEndTimer() {
40529
- this.stopStreamingEndTimer();
40530
- this.streamingEndTimer = setTimeout$1(() => {
40531
- this.streamingEndTimer = null;
40532
- this.onSubmissionEnd();
40533
- }, STREAMING_END_SETTLE_MS);
40534
- }
40535
- stopStreamingEndTimer() {
40536
- if (!this.streamingEndTimer)
40537
- return;
40538
- clearTimeout(this.streamingEndTimer);
40539
- this.streamingEndTimer = null;
40540
- }
40541
- startSubmissionStartRetryTimer(attempt) {
40542
- this.stopSubmissionStartRetryTimer();
40543
- this.submissionStartRetryTimer = setTimeout$1(() => {
40544
- this.submissionStartRetryTimer = null;
40545
- this.onSubmissionStart(attempt);
40546
- }, SUBMISSION_START_RETRY_MS);
40547
- }
40548
- stopSubmissionStartRetryTimer() {
40549
- if (!this.submissionStartRetryTimer)
40550
- return;
40551
- clearTimeout(this.submissionStartRetryTimer);
40552
- this.submissionStartRetryTimer = null;
40553
- }
40554
- suspend() {
40555
- this.isActive = false;
40556
- }
40557
- resume() {
40558
- this.isActive = true;
40559
- }
40560
- teardown() {
40561
- this._.each(this.observers, (o) => o && o.disconnect && o.disconnect());
40562
- this.observers = [];
40563
- if (this.reactionClickHandler && this.root) {
40564
- this.root.removeEventListener('click', this.reactionClickHandler, true);
40565
- this.reactionClickHandler = null;
40566
- }
40567
- this.stopStreamingEndTimer();
40568
- this.stopSubmissionStartRetryTimer();
40569
- this.listeners = [];
40570
- }
40571
- }
40572
-
40573
40272
  /*
40574
40273
  * Prompt Analytics Plugin
40575
40274
  *
@@ -40654,6 +40353,9 @@ class PromptPlugin {
40654
40353
  });
40655
40354
  const currentlyActiveIds = this._.map(this._.filter(this.prompts, prompt => prompt.isActive), prompt => prompt.id);
40656
40355
  this._.each(allAgents, aiAgent => {
40356
+ if (this.isConversationAgent(aiAgent)) {
40357
+ return;
40358
+ }
40657
40359
  const isCurrentlyActive = this._.contains(currentlyActiveIds, aiAgent.id);
40658
40360
  const shouldBeActive = this.testPageRule(aiAgent.pageRule, currentUrl, aiAgent.id);
40659
40361
  if (shouldBeActive && !isCurrentlyActive) {
@@ -40672,6 +40374,10 @@ class PromptPlugin {
40672
40374
  return candidateValue;
40673
40375
  return candidateValue.replace(filters, 'redacted');
40674
40376
  }
40377
+ // conversation agents, owned by the ConversationAnalytics plugin.
40378
+ isConversationAgent(agent) {
40379
+ return agent.preset && agent.preset != 'chatgpt';
40380
+ }
40675
40381
  onConfigLoaded(aiAgents = []) {
40676
40382
  if (!aiAgents || !this._.isArray(aiAgents) || aiAgents.length === 0) {
40677
40383
  return;
@@ -40679,6 +40385,9 @@ class PromptPlugin {
40679
40385
  const networkAgents = [];
40680
40386
  const domAgents = [];
40681
40387
  for (const agent of aiAgents) {
40388
+ if (this.isConversationAgent(agent)) {
40389
+ continue;
40390
+ }
40682
40391
  if (agent.trackingMethod === 'network') {
40683
40392
  networkAgents.push(agent);
40684
40393
  }
@@ -40734,25 +40443,12 @@ class PromptPlugin {
40734
40443
  }
40735
40444
  }
40736
40445
  observePrompt(config) {
40737
- const { id, cssSelectors, privacyFilters, preset } = config;
40446
+ const { id, cssSelectors, privacyFilters } = config;
40738
40447
  // Check if agent already exists
40739
40448
  const existingPrompt = this._.find(this.prompts, prompt => prompt.id === id);
40740
40449
  if (existingPrompt) {
40741
40450
  return;
40742
40451
  }
40743
- if (DOMConversation.supportedPreset(preset)) {
40744
- const missing = DOMConversation.validateConfig(cssSelectors);
40745
- if (missing.length) {
40746
- this.api.log.error('aiAgent config missing required selectors', { agentId: id, missing });
40747
- return;
40748
- }
40749
- const conversation = new DOMConversation(this.pendo, this.api, id, privacyFilters, cssSelectors);
40750
- conversation.onSubmit((eventType, payload) => {
40751
- this.sendConversationEvent(eventType, payload);
40752
- });
40753
- this.prompts.push(conversation);
40754
- return;
40755
- }
40756
40452
  let inputCssSelectors, submitCssSelectors;
40757
40453
  inputCssSelectors = this.parseCssSelector('input', cssSelectors);
40758
40454
  submitCssSelectors = this.parseCssSelector('submit', cssSelectors);
@@ -40779,15 +40475,6 @@ class PromptPlugin {
40779
40475
  }, promptEvent);
40780
40476
  this.api.analytics.collectEvent('prompt', event, undefined, 'agentic');
40781
40477
  }
40782
- sendConversationEvent(eventType, eventPayload) {
40783
- // Block event if the prompt is suspended
40784
- const conv = this._.find(this.prompts, p => p.id === eventPayload.agentId);
40785
- if (conv && !conv.isActive) {
40786
- return;
40787
- }
40788
- eventPayload = this._.extend({ agentType: 'conversation' }, eventPayload);
40789
- this.api.analytics.collectEvent(eventType, eventPayload, undefined, 'agentic');
40790
- }
40791
40478
  teardown() {
40792
40479
  this._.each(this.prompts, (prompt) => prompt.teardown());
40793
40480
  if (this.agentsCache) {
@@ -41174,10 +40861,7 @@ class WebAnalytics {
41174
40861
  PluginAPI.attachEvent(PluginAPI.Events, 'eventCaptured', bind(this.addUtmToEvent, this)),
41175
40862
  PluginAPI.attachEvent(PluginAPI.Events, 'sessionChanged', bind(this.sessionChanged, this))
41176
40863
  ];
41177
- let params = this.loadParameters(PluginAPI.agentStorage);
41178
- if (!params || pendo._.isEmpty(params)) {
41179
- params = this.extractParameters(window.location.href, document.referrer);
41180
- }
40864
+ this.suffix = this.api.ConfigReader.get('identityStorageSuffix');
41181
40865
  /**
41182
40866
  * Stores UTM parameters that were present in the URL when the visitor loaded the application.
41183
40867
  *
@@ -41186,9 +40870,12 @@ class WebAnalytics {
41186
40870
  * @access public
41187
40871
  * @label WEB_ANALYTICS_STORAGE_KEY
41188
40872
  */
41189
- this.api.agentStorage.registry.addLocal(WEB_ANALYTICS_STORAGE_KEY);
40873
+ this.api.agentStorage.registry.addLocal(WEB_ANALYTICS_STORAGE_KEY, { cookieSuffix: this.suffix, isSecure: true });
40874
+ let params = this.loadParameters(PluginAPI.agentStorage);
40875
+ if (!params || pendo._.isEmpty(params)) {
40876
+ params = this.extractParameters(window.location.href, document.referrer);
40877
+ }
41190
40878
  this.storeParameters(params, PluginAPI.agentStorage);
41191
- this.suffix = this.api.ConfigReader.get('identityStorageSuffix');
41192
40879
  }
41193
40880
  extractParameters(url, referrer) {
41194
40881
  const locationUrl = new URL(url);
@@ -41243,12 +40930,12 @@ class WebAnalytics {
41243
40930
  }
41244
40931
  storeParameters(params, storage) {
41245
40932
  if (this.pendo._.size(params) > 0) {
41246
- storage.write(WEB_ANALYTICS_STORAGE_KEY, JSON.stringify(params), undefined, false, true, this.suffix);
40933
+ storage.write(WEB_ANALYTICS_STORAGE_KEY, JSON.stringify(params));
41247
40934
  }
41248
40935
  }
41249
40936
  loadParameters(storage) {
41250
- const storedParamsJson = storage.read(WEB_ANALYTICS_STORAGE_KEY, false, this.suffix) ||
41251
- storage.read(WEB_ANALYTICS_STORAGE_KEY);
40937
+ const storedParamsJson = storage.read(WEB_ANALYTICS_STORAGE_KEY) ||
40938
+ storage.read(WEB_ANALYTICS_STORAGE_KEY, false, '');
41252
40939
  if (storedParamsJson)
41253
40940
  return JSON.parse(storedParamsJson);
41254
40941
  return null;
@@ -41274,7 +40961,7 @@ class WebAnalytics {
41274
40961
  sessionChanged() {
41275
40962
  const agentStorage = this.api.agentStorage;
41276
40963
  agentStorage.clear(WEB_ANALYTICS_STORAGE_KEY);
41277
- agentStorage.clear(WEB_ANALYTICS_STORAGE_KEY, false, this.suffix);
40964
+ agentStorage.clear(WEB_ANALYTICS_STORAGE_KEY, false, '');
41278
40965
  const params = this.extractParameters(window.location.href, document.referrer);
41279
40966
  this.storeParameters(params, agentStorage);
41280
40967
  }
@@ -41607,20 +41294,20 @@ function getZoneSafeMethod(_, method, target) {
41607
41294
  }
41608
41295
 
41609
41296
  // Does not support submit and go to
41610
- var goToRegex = new RegExp(guideMarkdownUtil.goToString);
41611
- var PollBranching = {
41297
+ const goToRegex = new RegExp(guideMarkdownUtil.goToString);
41298
+ const PollBranching = {
41612
41299
  name: 'PollBranching',
41613
- script: function (step, guide, pendo) {
41614
- var isAdvanceIntercepted = false;
41615
- var branchingQuestions = initialBranchingSetup(step, pendo);
41300
+ script(step, guide, pendo) {
41301
+ let isAdvanceIntercepted = false;
41302
+ const branchingQuestions = initialBranchingSetup(step, pendo);
41616
41303
  if (branchingQuestions) {
41617
41304
  // If there are too many branching questions saved, exit and run the guide normally.
41618
41305
  if (pendo._.size(branchingQuestions) > 1)
41619
41306
  return;
41620
- this.on('beforeAdvance', function (evt) {
41621
- var noResponseSelected = step.guideElement.find('[branching] .pendo-radio:checked').length === 0;
41622
- var responseLabel = step.guideElement.find('[branching] .pendo-radio:checked + label')[0];
41623
- var noGotoLabel;
41307
+ this.on('beforeAdvance', (evt) => {
41308
+ const noResponseSelected = step.guideElement.find('[branching] .pendo-radio:checked').length === 0;
41309
+ const responseLabel = step.guideElement.find('[branching] .pendo-radio:checked + label')[0];
41310
+ let noGotoLabel;
41624
41311
  if (responseLabel) {
41625
41312
  noGotoLabel = pendo._.isNull(responseLabel.getAttribute('goToStep'));
41626
41313
  }
@@ -41631,58 +41318,58 @@ var PollBranching = {
41631
41318
  });
41632
41319
  }
41633
41320
  },
41634
- test: function (step, guide, pendo) {
41321
+ test(step, guide, pendo) {
41635
41322
  var _a;
41636
- var branchingQuestions = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find('._pendo-multi-choice-poll-question:contains("{branching/}")');
41323
+ let branchingQuestions = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find('._pendo-multi-choice-poll-question:contains("{branching/}")');
41637
41324
  return !pendo._.isUndefined(branchingQuestions) && pendo._.size(branchingQuestions);
41638
41325
  },
41639
- designerListener: function (pendo) {
41640
- var target = pendo.dom.getBody();
41641
- var config = {
41326
+ designerListener(pendo) {
41327
+ const target = pendo.dom.getBody();
41328
+ const config = {
41642
41329
  attributeFilter: ['data-layout'],
41643
41330
  attributes: true,
41644
41331
  childList: true,
41645
41332
  characterData: true,
41646
41333
  subtree: true
41647
41334
  };
41648
- var MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
41649
- var observer = new MutationObserver(applyBranchingIndicators);
41335
+ const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
41336
+ const observer = new MutationObserver(applyBranchingIndicators);
41650
41337
  observer.observe(target, config);
41651
41338
  function applyBranchingIndicators(mutations) {
41652
41339
  pendo._.each(mutations, function (mutation) {
41653
41340
  var _a;
41654
- var nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelector);
41341
+ const nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelector);
41655
41342
  if (mutation.addedNodes.length && nodeHasQuerySelector) {
41656
41343
  if (mutation.addedNodes[0].querySelector('._pendo-multi-choice-poll-select-border')) {
41657
41344
  if (pendo._.size(pendo.dom('._pendo-multi-choice-poll-question:contains("{branching/}")'))) {
41658
41345
  pendo
41659
41346
  .dom('._pendo-multi-choice-poll-question:contains("{branching/}")')
41660
- .each(function (question, index) {
41661
- pendo._.each(pendo.dom("#".concat(question.id, " *")), function (element) {
41347
+ .each((question, index) => {
41348
+ pendo._.each(pendo.dom(`#${question.id} *`), (element) => {
41662
41349
  guideMarkdownUtil.removeMarkdownSyntax(element, '{branching/}', '', pendo);
41663
41350
  });
41664
41351
  pendo
41665
- .dom("#".concat(question.id, " p"))
41352
+ .dom(`#${question.id} p`)
41666
41353
  .css({ display: 'inline-block !important' })
41667
41354
  .append(branchingIcon('#999', '20px'))
41668
41355
  .attr({ title: 'Custom Branching Added' });
41669
- var dataPendoPollId = question.getAttribute('data-pendo-poll-id');
41670
- if (pendo.dom("._pendo-multi-choice-poll-question[data-pendo-poll-id=".concat(dataPendoPollId, "]"))[0]) {
41356
+ let dataPendoPollId = question.getAttribute('data-pendo-poll-id');
41357
+ if (pendo.dom(`._pendo-multi-choice-poll-question[data-pendo-poll-id=${dataPendoPollId}]`)[0]) {
41671
41358
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
41672
41359
  pendo
41673
- .dom("._pendo-multi-choice-poll-question[data-pendo-poll-id=".concat(dataPendoPollId, "]"))[0]
41360
+ .dom(`._pendo-multi-choice-poll-question[data-pendo-poll-id=${dataPendoPollId}]`)[0]
41674
41361
  .textContent.trim();
41675
41362
  }
41676
- var pollLabels = pendo.dom("label[for*=".concat(dataPendoPollId, "]"));
41363
+ let pollLabels = pendo.dom(`label[for*=${dataPendoPollId}]`);
41677
41364
  if (pendo._.size(pollLabels)) {
41678
- pendo._.forEach(pollLabels, function (label) {
41365
+ pendo._.forEach(pollLabels, (label) => {
41679
41366
  if (goToRegex.test(label.textContent)) {
41680
- var labelTitle = goToRegex.exec(label.textContent)[2];
41367
+ let labelTitle = goToRegex.exec(label.textContent)[2];
41681
41368
  guideMarkdownUtil.removeMarkdownSyntax(label, goToRegex, '', pendo);
41682
41369
  pendo
41683
41370
  .dom(label)
41684
41371
  .append(branchingIcon('#999', '14px'))
41685
- .attr({ title: "Branching to step ".concat(labelTitle) });
41372
+ .attr({ title: `Branching to step ${labelTitle}` });
41686
41373
  }
41687
41374
  });
41688
41375
  }
@@ -41690,9 +41377,9 @@ var PollBranching = {
41690
41377
  pendo
41691
41378
  .dom(question)
41692
41379
  .append(branchingErrorHTML(question.dataset.pendoPollId));
41693
- pendo.dom("#".concat(question.id, " #pendo-ps-branching-svg")).remove();
41380
+ pendo.dom(`#${question.id} #pendo-ps-branching-svg`).remove();
41694
41381
  pendo
41695
- .dom("#".concat(question.id, " p"))
41382
+ .dom(`#${question.id} p`)
41696
41383
  .css({ display: 'inline-block !important' })
41697
41384
  .append(branchingIcon('red', '20px'))
41698
41385
  .attr({ title: 'Unsupported Branching configuration' });
@@ -41704,31 +41391,49 @@ var PollBranching = {
41704
41391
  });
41705
41392
  }
41706
41393
  function branchingErrorHTML(dataPendoPollId) {
41707
- return "<div style=\"text-align:lrft; font-size: 14px; color: red;\n font-style: italic; margin-top: 0px;\" class=\"branching-wrapper\"\n name=\"".concat(dataPendoPollId, "\">\n * Branching Error: Multiple branching polls not supported</div>");
41394
+ return `<div style="text-align:lrft; font-size: 14px; color: red;
41395
+ font-style: italic; margin-top: 0px;" class="branching-wrapper"
41396
+ name="${dataPendoPollId}">
41397
+ * Branching Error: Multiple branching polls not supported</div>`;
41708
41398
  }
41709
41399
  function branchingIcon(color, size) {
41710
- return "<svg id=\"pendo-ps-branching-svg\" viewBox=\"0 0 24 24\" fill=\"none\"\n style=\"margin-left: 5px;\n height:".concat(size, "; width:").concat(size, "; display:inline; vertical-align:middle;\" xmlns=\"http://www.w3.org/2000/svg\">\n <g stroke-width=\"0\"></g>\n <g stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g> <circle cx=\"4\" cy=\"7\" r=\"2\" stroke=\"").concat(color, "\"\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></circle>\n <circle cx=\"20\" cy=\"7\" r=\"2\" stroke=\"").concat(color, "\"\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></circle>\n <circle cx=\"20\" cy=\"17\" r=\"2\" stroke=\"").concat(color, "\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"></circle>\n <path d=\"M18 7H6\" stroke=\"").concat(color, "\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n <path d=\"M7 7V7C8.65685 7 10 8.34315 10 10V15C10 16.1046 10.8954 17 12 17H18\"\n stroke=\"").concat(color, "\" stroke-width=\"2\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\"></path> </g></svg>");
41400
+ return `<svg id="pendo-ps-branching-svg" viewBox="0 0 24 24" fill="none"
41401
+ style="margin-left: 5px;
41402
+ height:${size}; width:${size}; display:inline; vertical-align:middle;" xmlns="http://www.w3.org/2000/svg">
41403
+ <g stroke-width="0"></g>
41404
+ <g stroke-linecap="round" stroke-linejoin="round"></g>
41405
+ <g> <circle cx="4" cy="7" r="2" stroke="${color}"
41406
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></circle>
41407
+ <circle cx="20" cy="7" r="2" stroke="${color}"
41408
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></circle>
41409
+ <circle cx="20" cy="17" r="2" stroke="${color}" stroke-width="2"
41410
+ stroke-linecap="round" stroke-linejoin="round"></circle>
41411
+ <path d="M18 7H6" stroke="${color}" stroke-width="2"
41412
+ stroke-linecap="round" stroke-linejoin="round"></path>
41413
+ <path d="M7 7V7C8.65685 7 10 8.34315 10 10V15C10 16.1046 10.8954 17 12 17H18"
41414
+ stroke="${color}" stroke-width="2" stroke-linecap="round"
41415
+ stroke-linejoin="round"></path> </g></svg>`;
41711
41416
  }
41712
41417
  }
41713
41418
  };
41714
41419
  function initialBranchingSetup(step, pendo) {
41715
- var questions = step.guideElement.find('._pendo-multi-choice-poll-question:contains("{branching/}")');
41716
- pendo._.forEach(questions, function (question) {
41717
- var dataPendoPollId = question.getAttribute('data-pendo-poll-id');
41718
- pendo._.each(step.guideElement.find("#".concat(question.id, " *")), function (element) {
41420
+ const questions = step.guideElement.find('._pendo-multi-choice-poll-question:contains("{branching/}")');
41421
+ pendo._.forEach(questions, (question) => {
41422
+ let dataPendoPollId = question.getAttribute('data-pendo-poll-id');
41423
+ pendo._.each(step.guideElement.find(`#${question.id} *`), (element) => {
41719
41424
  guideMarkdownUtil.removeMarkdownSyntax(element, '{branching/}', '', pendo);
41720
41425
  });
41721
- var pollLabels = step.guideElement.find("label[for*=".concat(dataPendoPollId, "]"));
41722
- pendo._.forEach(pollLabels, function (label) {
41426
+ let pollLabels = step.guideElement.find(`label[for*=${dataPendoPollId}]`);
41427
+ pendo._.forEach(pollLabels, (label) => {
41723
41428
  if (pendo._.isNull(goToRegex.exec(label.textContent))) {
41724
41429
  return;
41725
41430
  }
41726
- var gotoSubstring = goToRegex.exec(label.textContent)[1];
41727
- var gotoIndex = goToRegex.exec(label.textContent)[2];
41431
+ let gotoSubstring = goToRegex.exec(label.textContent)[1];
41432
+ let gotoIndex = goToRegex.exec(label.textContent)[2];
41728
41433
  label.setAttribute('goToStep', gotoIndex);
41729
41434
  guideMarkdownUtil.removeMarkdownSyntax(label, gotoSubstring, '', pendo);
41730
41435
  });
41731
- var pollChoiceContainer = step.guideElement.find("[data-pendo-poll-id=".concat(dataPendoPollId, "]._pendo-multi-choice-poll-select-border"));
41436
+ let pollChoiceContainer = step.guideElement.find(`[data-pendo-poll-id=${dataPendoPollId}]._pendo-multi-choice-poll-select-border`);
41732
41437
  if (pollChoiceContainer && pollChoiceContainer.length) {
41733
41438
  pollChoiceContainer[0].setAttribute('branching', '');
41734
41439
  }
@@ -41737,24 +41442,39 @@ function initialBranchingSetup(step, pendo) {
41737
41442
  }
41738
41443
  function branchingGoToStep(event, step, guide, pendo) {
41739
41444
  var _a;
41740
- var checkedPollInputId = (_a = step.guideElement.find('[branching] input.pendo-radio[data-pendo-poll-id]:checked')[0]) === null || _a === void 0 ? void 0 : _a.id;
41741
- var checkedPollLabel = step.guideElement.find("label[for=\"".concat(checkedPollInputId, "\"]"))[0];
41742
- var checkedPollLabelStepIndex = checkedPollLabel === null || checkedPollLabel === void 0 ? void 0 : checkedPollLabel.getAttribute('goToStep');
41743
- var pollStepIndex = checkedPollLabelStepIndex - 1;
41445
+ let checkedPollInputId = (_a = step.guideElement.find('[branching] input.pendo-radio[data-pendo-poll-id]:checked')[0]) === null || _a === void 0 ? void 0 : _a.id;
41446
+ let checkedPollLabel = step.guideElement.find(`label[for="${checkedPollInputId}"]`)[0];
41447
+ let checkedPollLabelStepIndex = checkedPollLabel === null || checkedPollLabel === void 0 ? void 0 : checkedPollLabel.getAttribute('goToStep');
41448
+ let pollStepIndex = checkedPollLabelStepIndex - 1;
41744
41449
  if (pollStepIndex < 0)
41745
41450
  return;
41746
- var destinationObject = {
41451
+ const destinationObject = {
41747
41452
  destinationStepId: guide.steps[pollStepIndex].id,
41748
- step: step
41453
+ step
41749
41454
  };
41750
41455
  pendo.goToStep(destinationObject);
41751
41456
  event.cancel = true;
41752
41457
  }
41753
41458
 
41754
- var MetadataSubstitution = {
41459
+ var DANGEROUS_URL_SCHEME = /^\s*(javascript|data|vbscript):/i;
41460
+ function encodeMetadataForUrl(value, urlBeforePlaceholder) {
41461
+ if (urlBeforePlaceholder === void 0) { urlBeforePlaceholder = ''; }
41462
+ var str = value === undefined || value === null ? '' : String(value);
41463
+ var inUrlComponent = urlBeforePlaceholder.indexOf('?') !== -1 || urlBeforePlaceholder.indexOf('#') !== -1;
41464
+ if (inUrlComponent) {
41465
+ return window.encodeURIComponent(str);
41466
+ }
41467
+ var schemeAlreadySet = urlBeforePlaceholder.indexOf(':') !== -1;
41468
+ if (!schemeAlreadySet && DANGEROUS_URL_SCHEME.test(str)) {
41469
+ return '';
41470
+ }
41471
+ return window.encodeURI(str);
41472
+ }
41473
+
41474
+ const MetadataSubstitution = {
41755
41475
  name: 'MetadataSubstitution',
41756
- script: function (step, guide, pendo) {
41757
- var placeholderData = findSubstitutableElements(pendo);
41476
+ script(step, guide, pendo) {
41477
+ const placeholderData = findSubstitutableElements(pendo);
41758
41478
  if (step.domJson) {
41759
41479
  findSubstitutableUrlsInJson(step.domJson, placeholderData, pendo);
41760
41480
  }
@@ -41762,22 +41482,22 @@ var MetadataSubstitution = {
41762
41482
  pendo._.each(placeholderData, function (placeholder) {
41763
41483
  processPlaceholder(placeholder, pendo);
41764
41484
  });
41765
- var containerId = "pendo-g-".concat(step.id);
41766
- var context_1 = step.guideElement;
41767
- updateGuideContainer(containerId, context_1, pendo);
41485
+ const containerId = `pendo-g-${step.id}`;
41486
+ const context = step.guideElement;
41487
+ updateGuideContainer(containerId, context, pendo);
41768
41488
  }
41769
41489
  },
41770
- designerListener: function (pendo) {
41771
- var target = pendo.dom.getBody();
41490
+ designerListener(pendo) {
41491
+ const target = pendo.dom.getBody();
41772
41492
  if (pendo.designerv2) {
41773
41493
  pendo.designerv2.runMetadataSubstitutionForDesignerPreview = function runMetadataSubstitutionForDesignerPreview() {
41774
41494
  var _a;
41775
41495
  if (!document.querySelector(guideMarkdownUtil.containerSelector))
41776
41496
  return;
41777
- var step = (_a = pendo.designerv2.currentlyPreviewedGuide) === null || _a === void 0 ? void 0 : _a.steps[0];
41497
+ const step = (_a = pendo.designerv2.currentlyPreviewedGuide) === null || _a === void 0 ? void 0 : _a.steps[0];
41778
41498
  if (!step)
41779
41499
  return;
41780
- var placeholderData = findSubstitutableElements(pendo);
41500
+ const placeholderData = findSubstitutableElements(pendo);
41781
41501
  if (step.buildingBlocks) {
41782
41502
  findSubstitutableUrlsInJson(step.buildingBlocks, placeholderData, pendo);
41783
41503
  }
@@ -41787,32 +41507,32 @@ var MetadataSubstitution = {
41787
41507
  return;
41788
41508
  processPlaceholder(placeholder, pendo);
41789
41509
  });
41790
- var containerId = "pendo-g-".concat(step.id);
41791
- var context_2 = step.guideElement;
41792
- updateGuideContainer(containerId, context_2, pendo);
41510
+ const containerId = `pendo-g-${step.id}`;
41511
+ const context = step.guideElement;
41512
+ updateGuideContainer(containerId, context, pendo);
41793
41513
  }
41794
41514
  };
41795
41515
  }
41796
- var config = {
41516
+ const config = {
41797
41517
  attributeFilter: ['data-layout'],
41798
41518
  attributes: true,
41799
41519
  childList: true,
41800
41520
  characterData: true,
41801
41521
  subtree: true
41802
41522
  };
41803
- var MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
41804
- var observer = new MutationObserver(applySubstitutionIndicators);
41523
+ const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
41524
+ const observer = new MutationObserver(applySubstitutionIndicators);
41805
41525
  observer.observe(target, config);
41806
41526
  function applySubstitutionIndicators(mutations) {
41807
41527
  pendo._.each(mutations, function (mutation) {
41808
41528
  var _a;
41809
41529
  if (mutation.addedNodes.length) {
41810
41530
  if (document.querySelector(guideMarkdownUtil.containerSelector)) {
41811
- var placeholderData = findSubstitutableElements(pendo);
41812
- var step = (_a = pendo.designerv2.currentlyPreviewedGuide) === null || _a === void 0 ? void 0 : _a.steps[0];
41531
+ const placeholderData = findSubstitutableElements(pendo);
41532
+ const step = (_a = pendo.designerv2.currentlyPreviewedGuide) === null || _a === void 0 ? void 0 : _a.steps[0];
41813
41533
  if (!step)
41814
41534
  return;
41815
- var pendoBlocks = step.buildingBlocks;
41535
+ const pendoBlocks = step.buildingBlocks;
41816
41536
  if (!pendo._.isUndefined(pendoBlocks)) {
41817
41537
  findSubstitutableUrlsInJson(pendoBlocks, placeholderData, pendo);
41818
41538
  }
@@ -41822,9 +41542,9 @@ var MetadataSubstitution = {
41822
41542
  return;
41823
41543
  processPlaceholder(placeholder, pendo);
41824
41544
  });
41825
- var containerId = "pendo-g-".concat(step.id);
41826
- var context_3 = step.guideElement;
41827
- updateGuideContainer(containerId, context_3, pendo);
41545
+ const containerId = `pendo-g-${step.id}`;
41546
+ const context = step.guideElement;
41547
+ updateGuideContainer(containerId, context, pendo);
41828
41548
  }
41829
41549
  }
41830
41550
  }
@@ -41833,18 +41553,18 @@ var MetadataSubstitution = {
41833
41553
  }
41834
41554
  };
41835
41555
  function processPlaceholder(placeholder, pendo) {
41836
- var match;
41837
- var data = placeholder.data, target = placeholder.target;
41838
- var subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
41556
+ let match;
41557
+ const { data, target } = placeholder;
41558
+ const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
41839
41559
  while ((match = matchPlaceholder(placeholder, subRegex))) {
41840
- var usedArrayPath = Array.isArray(match) && match.length >= 2;
41841
- var currentStr = target === 'textContent'
41560
+ const usedArrayPath = Array.isArray(match) && match.length >= 2;
41561
+ const currentStr = target === 'textContent'
41842
41562
  ? data[target]
41843
41563
  : decodeURI((data.getAttribute && (target === 'href' || target === 'value') ? (data.getAttribute(target) || '') : data[target]));
41844
- var matched = usedArrayPath ? match : subRegex.exec(currentStr);
41564
+ const matched = usedArrayPath ? match : subRegex.exec(currentStr);
41845
41565
  if (!matched)
41846
41566
  continue;
41847
- var mdValue = getSubstituteValue(matched, pendo);
41567
+ const mdValue = getSubstituteValue(matched, pendo);
41848
41568
  substituteMetadataByTarget(data, target, mdValue, matched);
41849
41569
  }
41850
41570
  }
@@ -41853,49 +41573,51 @@ function matchPlaceholder(placeholder, regex) {
41853
41573
  return placeholder.data[placeholder.target].match(regex);
41854
41574
  }
41855
41575
  else {
41856
- var raw = placeholder.data.getAttribute && (placeholder.target === 'href' || placeholder.target === 'value')
41576
+ const raw = placeholder.data.getAttribute && (placeholder.target === 'href' || placeholder.target === 'value')
41857
41577
  ? (placeholder.data.getAttribute(placeholder.target) || '')
41858
41578
  : placeholder.data[placeholder.target];
41859
41579
  return decodeURI(raw).match(regex);
41860
41580
  }
41861
41581
  }
41862
41582
  function getMetadataValueCaseInsensitive(metadata, type, property) {
41863
- var kind = metadata && metadata[type];
41583
+ const kind = metadata && metadata[type];
41864
41584
  if (!kind || typeof kind !== 'object')
41865
41585
  return undefined;
41866
- var direct = Object.prototype.hasOwnProperty.call(kind, property) ? kind[property] : undefined;
41586
+ const direct = Object.prototype.hasOwnProperty.call(kind, property) ? kind[property] : undefined;
41867
41587
  if (direct !== undefined) {
41868
41588
  return direct;
41869
41589
  }
41870
- var propLower = property.toLowerCase();
41871
- var key = Object.keys(kind).find(function (k) { return k.toLowerCase() === propLower; });
41872
- var value = key !== undefined ? kind[key] : undefined;
41590
+ const propLower = property.toLowerCase();
41591
+ const key = Object.keys(kind).find(k => k.toLowerCase() === propLower);
41592
+ const value = key !== undefined ? kind[key] : undefined;
41873
41593
  return value;
41874
41594
  }
41875
41595
  function getSubstituteValue(match, pendo) {
41876
41596
  if (pendo._.isUndefined(match[1]) || pendo._.isUndefined(match[2])) {
41877
41597
  return;
41878
41598
  }
41879
- var type = match[1];
41880
- var property = match[2];
41881
- var defaultValue = match[3];
41599
+ let type = match[1];
41600
+ let property = match[2];
41601
+ let defaultValue = match[3];
41882
41602
  if (pendo._.isUndefined(type) || pendo._.isUndefined(property)) {
41883
41603
  return;
41884
41604
  }
41885
- var metadata = pendo.getSerializedMetadata();
41886
- var mdValue = getMetadataValueCaseInsensitive(metadata, type, property);
41605
+ const metadata = pendo.getSerializedMetadata();
41606
+ let mdValue = getMetadataValueCaseInsensitive(metadata, type, property);
41887
41607
  if (mdValue === undefined || mdValue === null)
41888
41608
  mdValue = defaultValue || '';
41889
41609
  return mdValue;
41890
41610
  }
41891
41611
  function substituteMetadataByTarget(data, target, mdValue, matched) {
41892
- var isElement = data && typeof data.getAttribute === 'function';
41893
- var current = (target === 'href' || target === 'value') && isElement
41612
+ const isElement = data && typeof data.getAttribute === 'function';
41613
+ const current = (target === 'href' || target === 'value') && isElement
41894
41614
  ? (data.getAttribute(target) || '')
41895
41615
  : data[target];
41896
41616
  if (target === 'href' || target === 'value') {
41897
- var safeValue = window.encodeURIComponent(String(mdValue === undefined || mdValue === null ? '' : mdValue));
41898
- data[target] = decodeURI(current).replace(matched[0], safeValue);
41617
+ const decodedUrl = decodeURI(current);
41618
+ const urlBeforePlaceholder = decodedUrl.slice(0, decodedUrl.indexOf(matched[0]));
41619
+ const safeValue = encodeMetadataForUrl(mdValue, urlBeforePlaceholder);
41620
+ data[target] = decodedUrl.replace(matched[0], safeValue);
41899
41621
  }
41900
41622
  else {
41901
41623
  data[target] = current.replace(matched[0], mdValue);
@@ -41908,9 +41630,8 @@ function updateGuideContainer(containerId, context, pendo) {
41908
41630
  pendo.flexElement(pendo.dom(guideMarkdownUtil.containerSelector));
41909
41631
  pendo.BuildingBlocks.BuildingBlockGuides.recalculateGuideHeight(containerId, context);
41910
41632
  }
41911
- function findSubstitutableUrlsInJson(originalData, placeholderData, pendo) {
41912
- if (placeholderData === void 0) { placeholderData = []; }
41913
- var subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
41633
+ function findSubstitutableUrlsInJson(originalData, placeholderData = [], pendo) {
41634
+ const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
41914
41635
  if ((originalData.name === 'url' || originalData.name === 'href') && originalData.value) {
41915
41636
  if (subRegex.test(originalData.value)) {
41916
41637
  placeholderData.push({
@@ -41920,37 +41641,37 @@ function findSubstitutableUrlsInJson(originalData, placeholderData, pendo) {
41920
41641
  }
41921
41642
  }
41922
41643
  if (originalData.properties && originalData.id === 'href_link_block') {
41923
- pendo._.each(originalData.properties, function (prop) {
41644
+ pendo._.each(originalData.properties, (prop) => {
41924
41645
  findSubstitutableUrlsInJson(prop, placeholderData, pendo);
41925
41646
  });
41926
41647
  }
41927
41648
  if (originalData.views) {
41928
- pendo._.each(originalData.views, function (view) {
41649
+ pendo._.each(originalData.views, (view) => {
41929
41650
  findSubstitutableUrlsInJson(view, placeholderData, pendo);
41930
41651
  });
41931
41652
  }
41932
41653
  if (originalData.parameters) {
41933
- pendo._.each(originalData.parameters, function (param) {
41654
+ pendo._.each(originalData.parameters, (param) => {
41934
41655
  findSubstitutableUrlsInJson(param, placeholderData, pendo);
41935
41656
  });
41936
41657
  }
41937
41658
  if (originalData.actions) {
41938
- pendo._.each(originalData.actions, function (action) {
41659
+ pendo._.each(originalData.actions, (action) => {
41939
41660
  findSubstitutableUrlsInJson(action, placeholderData, pendo);
41940
41661
  });
41941
41662
  }
41942
41663
  if (originalData.children) {
41943
- pendo._.each(originalData.children, function (child) {
41664
+ pendo._.each(originalData.children, (child) => {
41944
41665
  findSubstitutableUrlsInJson(child, placeholderData, pendo);
41945
41666
  });
41946
41667
  }
41947
41668
  return placeholderData;
41948
41669
  }
41949
41670
  function findSubstitutableElements(pendo) {
41950
- var elements = pendo.dom("".concat(guideMarkdownUtil.containerSelector, " *:not(.pendo-inline-ui)"));
41671
+ let elements = pendo.dom(`${guideMarkdownUtil.containerSelector} *:not(.pendo-inline-ui)`);
41951
41672
  return pendo._.chain(elements)
41952
41673
  .filter(function (placeholder) {
41953
- var subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
41674
+ const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
41954
41675
  if (placeholder.localName === 'a') {
41955
41676
  return subRegex.test(decodeURI(placeholder.href)) || subRegex.test(placeholder.textContent);
41956
41677
  }
@@ -42006,25 +41727,51 @@ function findSubstitutableElements(pendo) {
42006
41727
  .value();
42007
41728
  }
42008
41729
  function substitutionIcon(color, size) {
42009
- return ("<div title=\"Metadata Substitution added\">\n <svg id=\"pendo-ps-substitution-icon\" viewBox=\"0 0 24 24\"\n preserveAspectRatio=\"xMidYMid meet\"\n height=".concat(size, " width=").concat(size, " title=\"Metadata Substitution\"\n style=\"bottom:5px; right:10px; position: absolute;\"\n fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" stroke=\"").concat(color, "\"\n transform=\"matrix(1, 0, 0, 1, 0, 0)rotate(0)\">\n <g stroke-width=\"0\"></g>\n <g stroke-linecap=\"round\" stroke-linejoin=\"round\"\n stroke=\"").concat(color, "\" stroke-width=\"0.528\"></g>\n <g><path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M5 5.5C4.17157 5.5 3.5 6.17157 3.5 7V10C3.5 10.8284\n 4.17157 11.5 5 11.5H8C8.82843 11.5 9.5 10.8284 9.5\n 10V9H17V11C17 11.2761 17.2239 11.5 17.5 11.5C17.7761\n 11.5 18 11.2761 18 11V8.5C18 8.22386 17.7761 8 17.5\n 8H9.5V7C9.5 6.17157 8.82843 5.5 8 5.5H5ZM8.5 7C8.5\n 6.72386 8.27614 6.5 8 6.5H5C4.72386 6.5 4.5 6.72386\n 4.5 7V10C4.5 10.2761 4.72386 10.5 5 10.5H8C8.27614\n 10.5 8.5 10.2761 8.5 10V7Z\" fill=\"").concat(color, "\"></path>\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M7 13C7 12.7239 6.77614 12.5 6.5 12.5C6.22386 12.5\n 6 12.7239 6 13V15.5C6 15.7761 6.22386 16 6.5\n 16H14.5V17C14.5 17.8284 15.1716 18.5 16 18.5H19C19.8284\n 18.5 20.5 17.8284 20.5 17V14C20.5 13.1716 19.8284 12.5\n 19 12.5H16C15.1716 12.5 14.5 13.1716 14.5\n 14V15H7V13ZM15.5 17C15.5 17.2761 15.7239 17.5 16\n 17.5H19C19.2761 17.5 19.5 17.2761 19.5 17V14C19.5\n 13.7239 19.2761 13.5 19 13.5H16C15.7239 13.5 15.5\n 13.7239 15.5 14V17Z\" fill=\"").concat(color, "\"></path> </g></svg></div>"));
42010
- }
42011
-
42012
- var requiredElement = '<span class="_pendo-required-indicator" style="color:red; font-style:italic;" title="Question is required"> *</span>';
42013
- var requiredSyntax = '{required/}';
42014
- var RequiredQuestions = {
41730
+ return (`<div title="Metadata Substitution added">
41731
+ <svg id="pendo-ps-substitution-icon" viewBox="0 0 24 24"
41732
+ preserveAspectRatio="xMidYMid meet"
41733
+ height=${size} width=${size} title="Metadata Substitution"
41734
+ style="bottom:5px; right:10px; position: absolute;"
41735
+ fill="none" xmlns="http://www.w3.org/2000/svg" stroke="${color}"
41736
+ transform="matrix(1, 0, 0, 1, 0, 0)rotate(0)">
41737
+ <g stroke-width="0"></g>
41738
+ <g stroke-linecap="round" stroke-linejoin="round"
41739
+ stroke="${color}" stroke-width="0.528"></g>
41740
+ <g><path fill-rule="evenodd" clip-rule="evenodd"
41741
+ d="M5 5.5C4.17157 5.5 3.5 6.17157 3.5 7V10C3.5 10.8284
41742
+ 4.17157 11.5 5 11.5H8C8.82843 11.5 9.5 10.8284 9.5
41743
+ 10V9H17V11C17 11.2761 17.2239 11.5 17.5 11.5C17.7761
41744
+ 11.5 18 11.2761 18 11V8.5C18 8.22386 17.7761 8 17.5
41745
+ 8H9.5V7C9.5 6.17157 8.82843 5.5 8 5.5H5ZM8.5 7C8.5
41746
+ 6.72386 8.27614 6.5 8 6.5H5C4.72386 6.5 4.5 6.72386
41747
+ 4.5 7V10C4.5 10.2761 4.72386 10.5 5 10.5H8C8.27614
41748
+ 10.5 8.5 10.2761 8.5 10V7Z" fill="${color}"></path>
41749
+ <path fill-rule="evenodd" clip-rule="evenodd"
41750
+ d="M7 13C7 12.7239 6.77614 12.5 6.5 12.5C6.22386 12.5
41751
+ 6 12.7239 6 13V15.5C6 15.7761 6.22386 16 6.5
41752
+ 16H14.5V17C14.5 17.8284 15.1716 18.5 16 18.5H19C19.8284
41753
+ 18.5 20.5 17.8284 20.5 17V14C20.5 13.1716 19.8284 12.5
41754
+ 19 12.5H16C15.1716 12.5 14.5 13.1716 14.5
41755
+ 14V15H7V13ZM15.5 17C15.5 17.2761 15.7239 17.5 16
41756
+ 17.5H19C19.2761 17.5 19.5 17.2761 19.5 17V14C19.5
41757
+ 13.7239 19.2761 13.5 19 13.5H16C15.7239 13.5 15.5
41758
+ 13.7239 15.5 14V17Z" fill="${color}"></path> </g></svg></div>`);
41759
+ }
41760
+
41761
+ const requiredElement = '<span class="_pendo-required-indicator" style="color:red; font-style:italic;" title="Question is required"> *</span>';
41762
+ const requiredSyntax = '{required/}';
41763
+ const RequiredQuestions = {
42015
41764
  name: 'RequiredQuestions',
42016
- script: function (step, guide, pendo) {
41765
+ script(step, guide, pendo) {
42017
41766
  var _a;
42018
- var requiredPollIds = [];
42019
- var submitButtons = (_a = guideMarkdownUtil.lookupGuideButtons(step.domJson)) === null || _a === void 0 ? void 0 : _a.filter(function (button) {
42020
- return button.actions.find(function (action) { return action.action === 'submitPoll' || action.action === 'submitPollAndGoToStep'; });
42021
- });
42022
- var requiredQuestions = processRequiredQuestions();
41767
+ let requiredPollIds = [];
41768
+ let submitButtons = (_a = guideMarkdownUtil.lookupGuideButtons(step.domJson)) === null || _a === void 0 ? void 0 : _a.filter(button => button.actions.find(action => action.action === 'submitPoll' || action.action === 'submitPollAndGoToStep'));
41769
+ const requiredQuestions = processRequiredQuestions();
42023
41770
  if (requiredQuestions) {
42024
- pendo._.forEach(requiredQuestions, function (question) {
41771
+ pendo._.forEach(requiredQuestions, (question) => {
42025
41772
  if (question.classList.contains('_pendo-open-text-poll-question')) {
42026
- var pollId = question.dataset.pendoPollId;
42027
- step.attachEvent(step.guideElement.find("[data-pendo-poll-id=".concat(pollId, "]._pendo-open-text-poll-input"))[0], 'input', function () {
41773
+ let pollId = question.dataset.pendoPollId;
41774
+ step.attachEvent(step.guideElement.find(`[data-pendo-poll-id=${pollId}]._pendo-open-text-poll-input`)[0], 'input', function () {
42028
41775
  evaluateRequiredQuestions(requiredQuestions);
42029
41776
  });
42030
41777
  }
@@ -42036,13 +41783,11 @@ var RequiredQuestions = {
42036
41783
  });
42037
41784
  }
42038
41785
  function getEligibleQuestions() {
42039
- var pollQuestions = pendo._.toArray(step.guideElement.find("[class*=-poll-question]:contains(".concat(requiredSyntax, ")")));
42040
- var surveyMatches = pendo._.toArray(step.guideElement.find("[data-pendo-poll-id]:contains(".concat(requiredSyntax, ")")));
42041
- var surveyQuestions = pendo._.filter(surveyMatches, function (candidate) {
42042
- return !pendo._.some(surveyMatches, function (other) { return other !== candidate && candidate.contains(other); });
42043
- });
42044
- var allQuestions = pendo._.uniq(pollQuestions.concat(surveyQuestions));
42045
- return pendo._.reduce(allQuestions, function (eligibleQuestions, question) {
41786
+ const pollQuestions = pendo._.toArray(step.guideElement.find(`[class*=-poll-question]:contains(${requiredSyntax})`));
41787
+ const surveyMatches = pendo._.toArray(step.guideElement.find(`[data-pendo-poll-id]:contains(${requiredSyntax})`));
41788
+ const surveyQuestions = pendo._.filter(surveyMatches, (candidate) => !pendo._.some(surveyMatches, (other) => other !== candidate && candidate.contains(other)));
41789
+ const allQuestions = pendo._.uniq(pollQuestions.concat(surveyQuestions));
41790
+ return pendo._.reduce(allQuestions, (eligibleQuestions, question) => {
42046
41791
  if (question.classList.contains('_pendo-yes-no-poll-question'))
42047
41792
  return eligibleQuestions;
42048
41793
  eligibleQuestions.push(question);
@@ -42050,24 +41795,22 @@ var RequiredQuestions = {
42050
41795
  }, []);
42051
41796
  }
42052
41797
  function ownsRequiredText(element) {
42053
- return pendo._.some(element.childNodes, function (node) {
42054
- return node.nodeType === 3 && node.nodeValue && node.nodeValue.indexOf(requiredSyntax) !== -1;
42055
- });
41798
+ return pendo._.some(element.childNodes, (node) => node.nodeType === 3 && node.nodeValue && node.nodeValue.indexOf(requiredSyntax) !== -1);
42056
41799
  }
42057
41800
  function processRequiredQuestions() {
42058
- var questions = getEligibleQuestions();
41801
+ let questions = getEligibleQuestions();
42059
41802
  if (questions) {
42060
- pendo._.forEach(questions, function (question) {
42061
- var dataPendoPollId = question.getAttribute('data-pendo-poll-id');
41803
+ pendo._.forEach(questions, question => {
41804
+ let dataPendoPollId = question.getAttribute('data-pendo-poll-id');
42062
41805
  requiredPollIds.push(dataPendoPollId);
42063
- var candidates = step.guideElement.find("#".concat(question.id, " *, #").concat(question.id));
42064
- var textHost = pendo._.find(candidates, ownsRequiredText) || question;
42065
- pendo._.each(candidates, function (element) {
41806
+ const candidates = step.guideElement.find(`#${question.id} *, #${question.id}`);
41807
+ const textHost = pendo._.find(candidates, ownsRequiredText) || question;
41808
+ pendo._.each(candidates, (element) => {
42066
41809
  guideMarkdownUtil.removeMarkdownSyntax(element, requiredSyntax, '', pendo);
42067
41810
  });
42068
- var textHostEl = pendo.dom(textHost);
41811
+ const textHostEl = pendo.dom(textHost);
42069
41812
  if (textHostEl.find('._pendo-required-indicator').length === 0) {
42070
- var questionParagraph = textHostEl.find('p');
41813
+ const questionParagraph = textHostEl.find('p');
42071
41814
  if (questionParagraph && questionParagraph.length) {
42072
41815
  pendo.dom(questionParagraph[0]).append(requiredElement);
42073
41816
  }
@@ -42078,7 +41821,15 @@ var RequiredQuestions = {
42078
41821
  });
42079
41822
  }
42080
41823
  if (pendo._.size(requiredPollIds)) {
42081
- var disabledButtonStyles = "<style type=text/css\n id=_pendo-guide-required-disabled>\n ._pendo-button:disabled, ._pendo-buttons[disabled] {\n border: 1px solid #999999 !important;\n background-color: #cccccc !important;\n color: #666666 !important;\n pointer-events: none !important;\n }\n </style>";
41824
+ const disabledButtonStyles = `<style type=text/css
41825
+ id=_pendo-guide-required-disabled>
41826
+ ._pendo-button:disabled, ._pendo-buttons[disabled] {
41827
+ border: 1px solid #999999 !important;
41828
+ background-color: #cccccc !important;
41829
+ color: #666666 !important;
41830
+ pointer-events: none !important;
41831
+ }
41832
+ </style>`;
42082
41833
  if (pendo.dom('#_pendo-guide-required-disabled').length === 0) {
42083
41834
  pendo.dom('head').append(disabledButtonStyles);
42084
41835
  }
@@ -42089,11 +41840,15 @@ var RequiredQuestions = {
42089
41840
  function evaluateRequiredQuestions(questions) {
42090
41841
  if (questions.length === 0)
42091
41842
  return;
42092
- var allRequiredComplete = true;
42093
- var responses = [];
42094
- responses = responses.concat(pendo._.map(questions, function (question) {
42095
- var pollId = question.getAttribute('data-pendo-poll-id');
42096
- var input = step.guideElement.find("\n [data-pendo-poll-id=".concat(pollId, "] textarea,\n [data-pendo-poll-id=").concat(pollId, "] input:text,\n [data-pendo-poll-id=").concat(pollId, "] select,\n [data-pendo-poll-id=").concat(pollId, "] input:radio:checked"));
41843
+ let allRequiredComplete = true;
41844
+ let responses = [];
41845
+ responses = responses.concat(pendo._.map(questions, (question) => {
41846
+ let pollId = question.getAttribute('data-pendo-poll-id');
41847
+ let input = step.guideElement.find(`
41848
+ [data-pendo-poll-id=${pollId}] textarea,
41849
+ [data-pendo-poll-id=${pollId}] input:text,
41850
+ [data-pendo-poll-id=${pollId}] select,
41851
+ [data-pendo-poll-id=${pollId}] input:radio:checked`);
42097
41852
  if (input && input.length && input[0].value) {
42098
41853
  return input[0].value;
42099
41854
  }
@@ -42110,50 +41865,50 @@ var RequiredQuestions = {
42110
41865
  }
42111
41866
  function disableEligibleButtons(buttons) {
42112
41867
  pendo._.each(buttons, function (button) {
42113
- if (step.guideElement.find("#".concat(button.props.id))[0]) {
42114
- step.guideElement.find("#".concat(button.props.id))[0].disabled = true;
42115
- step.guideElement.find("#".concat(button.props.id))[0].parentElement.title = 'Please complete all required questions.';
41868
+ if (step.guideElement.find(`#${button.props.id}`)[0]) {
41869
+ step.guideElement.find(`#${button.props.id}`)[0].disabled = true;
41870
+ step.guideElement.find(`#${button.props.id}`)[0].parentElement.title = 'Please complete all required questions.';
42116
41871
  }
42117
41872
  });
42118
41873
  }
42119
41874
  function enableEligibleButtons(buttons) {
42120
41875
  pendo._.each(buttons, function (button) {
42121
- if (step.guideElement.find("#".concat(button.props.id))[0]) {
42122
- step.guideElement.find("#".concat(button.props.id))[0].disabled = false;
42123
- step.guideElement.find("#".concat(button.props.id))[0].parentElement.title = '';
41876
+ if (step.guideElement.find(`#${button.props.id}`)[0]) {
41877
+ step.guideElement.find(`#${button.props.id}`)[0].disabled = false;
41878
+ step.guideElement.find(`#${button.props.id}`)[0].parentElement.title = '';
42124
41879
  }
42125
41880
  });
42126
41881
  }
42127
41882
  },
42128
- test: function (step, guide, pendo) {
41883
+ test(step, guide, pendo) {
42129
41884
  var _a, _b;
42130
- var pollQuestions = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find("[class*=-poll-question]:contains(".concat(requiredSyntax, ")"));
42131
- var surveyQuestions = (_b = step.guideElement) === null || _b === void 0 ? void 0 : _b.find("[data-pendo-poll-id]:contains(".concat(requiredSyntax, ")"));
41885
+ const pollQuestions = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find(`[class*=-poll-question]:contains(${requiredSyntax})`);
41886
+ const surveyQuestions = (_b = step.guideElement) === null || _b === void 0 ? void 0 : _b.find(`[data-pendo-poll-id]:contains(${requiredSyntax})`);
42132
41887
  return (!pendo._.isUndefined(pollQuestions) && pendo._.size(pollQuestions)) ||
42133
41888
  (!pendo._.isUndefined(surveyQuestions) && pendo._.size(surveyQuestions));
42134
41889
  },
42135
- designerListener: function (pendo) {
42136
- var requiredQuestions = [];
42137
- var target = pendo.dom.getBody();
42138
- var config = {
41890
+ designerListener(pendo) {
41891
+ const requiredQuestions = [];
41892
+ const target = pendo.dom.getBody();
41893
+ const config = {
42139
41894
  attributeFilter: ['data-layout'],
42140
41895
  attributes: true,
42141
41896
  childList: true,
42142
41897
  characterData: true,
42143
41898
  subtree: true
42144
41899
  };
42145
- var MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
42146
- var observer = new MutationObserver(applyRequiredIndicators);
41900
+ const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
41901
+ const observer = new MutationObserver(applyRequiredIndicators);
42147
41902
  observer.observe(target, config);
42148
41903
  function applyRequiredIndicators(mutations) {
42149
41904
  pendo._.each(mutations, function (mutation) {
42150
41905
  var _a;
42151
- var nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelectorAll);
41906
+ const nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelectorAll);
42152
41907
  if (mutation.addedNodes.length && nodeHasQuerySelector) {
42153
- var eligiblePolls = mutation.addedNodes[0].querySelectorAll('[class*=-poll-wrapper], [class*=-poll-select-border], [id^=survey-item-wrapper__]');
41908
+ let eligiblePolls = mutation.addedNodes[0].querySelectorAll('[class*=-poll-wrapper], [class*=-poll-select-border], [id^=survey-item-wrapper__]');
42154
41909
  if (eligiblePolls) {
42155
41910
  pendo._.each(eligiblePolls, function (poll) {
42156
- var dataPendoPollId;
41911
+ let dataPendoPollId;
42157
41912
  if (poll.classList.contains('_pendo-open-text-poll-wrapper') ||
42158
41913
  poll.classList.contains('_pendo-number-scale-poll-wrapper')) {
42159
41914
  dataPendoPollId = poll.getAttribute('name');
@@ -42161,31 +41916,31 @@ var RequiredQuestions = {
42161
41916
  else {
42162
41917
  dataPendoPollId = poll.getAttribute('data-pendo-poll-id');
42163
41918
  }
42164
- var questionText;
42165
- var questionElement = pendo.dom("[class*=\"-poll-question\"][data-pendo-poll-id=".concat(dataPendoPollId, "]"))[0] ||
42166
- pendo.dom(".bb-text[data-pendo-poll-id=".concat(dataPendoPollId, "]"))[0];
41919
+ let questionText;
41920
+ const questionElement = pendo.dom(`[class*="-poll-question"][data-pendo-poll-id=${dataPendoPollId}]`)[0] ||
41921
+ pendo.dom(`.bb-text[data-pendo-poll-id=${dataPendoPollId}]`)[0];
42167
41922
  if (questionElement) {
42168
41923
  questionText = questionElement.textContent;
42169
41924
  }
42170
- var requiredSyntaxIndex = questionText ? questionText.indexOf(requiredSyntax) : -1;
41925
+ const requiredSyntaxIndex = questionText ? questionText.indexOf(requiredSyntax) : -1;
42171
41926
  if (requiredSyntaxIndex > -1) {
42172
- pendo._.each(pendo.dom("[data-pendo-poll-id=".concat(dataPendoPollId, "]:not(.pendo-radio)")), function (element) {
42173
- pendo._.each(pendo.dom("#".concat(element.id, " *:not(\".pendo-radio\"), #").concat(element.id, ":not(\".pendo-radio\")")), function (item) {
41927
+ pendo._.each(pendo.dom(`[data-pendo-poll-id=${dataPendoPollId}]:not(.pendo-radio)`), (element) => {
41928
+ pendo._.each(pendo.dom(`#${element.id} *:not(".pendo-radio"), #${element.id}:not(".pendo-radio")`), (item) => {
42174
41929
  guideMarkdownUtil.removeMarkdownSyntax(item, requiredSyntax, '', pendo);
42175
41930
  });
42176
41931
  });
42177
- var pollTextSelector = ".bb-text[data-pendo-poll-id=".concat(dataPendoPollId, "]");
42178
- var pollParagraphSelector = "".concat(pollTextSelector, " p");
42179
- var pollListItemSelector = "".concat(pollTextSelector, " li");
42180
- var pollIndicatorSelector = "".concat(pollTextSelector, " ._pendo-required-indicator");
42181
- pendo._.each(pendo.dom("".concat(pollParagraphSelector, ", ").concat(pollListItemSelector)), function (el) {
42182
- pendo._.each(el.childNodes, function (node) {
41932
+ const pollTextSelector = `.bb-text[data-pendo-poll-id=${dataPendoPollId}]`;
41933
+ const pollParagraphSelector = `${pollTextSelector} p`;
41934
+ const pollListItemSelector = `${pollTextSelector} li`;
41935
+ const pollIndicatorSelector = `${pollTextSelector} ._pendo-required-indicator`;
41936
+ pendo._.each(pendo.dom(`${pollParagraphSelector}, ${pollListItemSelector}`), (el) => {
41937
+ pendo._.each(el.childNodes, (node) => {
42183
41938
  if (node.nodeType === 3 && node.nodeValue.indexOf(requiredSyntax) !== -1) {
42184
41939
  node.nodeValue = node.nodeValue.split(requiredSyntax).join('');
42185
41940
  }
42186
41941
  });
42187
41942
  });
42188
- var hasIndicator = pendo.dom(pollIndicatorSelector).length !== 0;
41943
+ const hasIndicator = pendo.dom(pollIndicatorSelector).length !== 0;
42189
41944
  if (!hasIndicator) {
42190
41945
  if (pendo.dom(pollParagraphSelector).length !== 0 || pendo.dom(pollListItemSelector).length !== 0) {
42191
41946
  pendo.dom(pollParagraphSelector).append(requiredElement);
@@ -42196,7 +41951,7 @@ var RequiredQuestions = {
42196
41951
  }
42197
41952
  }
42198
41953
  if (pendo._.contains(requiredQuestions, dataPendoPollId)) {
42199
- var questionIndex = requiredQuestions.indexOf(dataPendoPollId);
41954
+ let questionIndex = requiredQuestions.indexOf(dataPendoPollId);
42200
41955
  if (questionIndex !== -1) {
42201
41956
  requiredQuestions.splice(questionIndex, 1);
42202
41957
  }
@@ -42207,7 +41962,7 @@ var RequiredQuestions = {
42207
41962
  }
42208
41963
  else {
42209
41964
  if (pendo._.contains(requiredQuestions, dataPendoPollId)) {
42210
- var index = requiredQuestions.indexOf(dataPendoPollId);
41965
+ let index = requiredQuestions.indexOf(dataPendoPollId);
42211
41966
  if (index !== -1) {
42212
41967
  requiredQuestions.splice(index, 1);
42213
41968
  }
@@ -42221,54 +41976,54 @@ var RequiredQuestions = {
42221
41976
  }
42222
41977
  };
42223
41978
 
42224
- var skipStepRegex = new RegExp(guideMarkdownUtil.skipStepString);
42225
- var SkipToEligibleStep = {
42226
- script: function (step, guide, pendo) {
42227
- var isAdvanceIntercepted = false;
42228
- var isPreviousIntercepted = false;
42229
- var guideContainer = step.guideElement.find(guideMarkdownUtil.containerSelector);
42230
- var guideContainerAriaLabel = guideContainer.attr('aria-label');
42231
- var stepNumberOrAuto = skipStepRegex.exec(guideContainerAriaLabel)[1];
41979
+ const skipStepRegex = new RegExp(guideMarkdownUtil.skipStepString);
41980
+ const SkipToEligibleStep = {
41981
+ script(step, guide, pendo) {
41982
+ let isAdvanceIntercepted = false;
41983
+ let isPreviousIntercepted = false;
41984
+ let guideContainer = step.guideElement.find(guideMarkdownUtil.containerSelector);
41985
+ let guideContainerAriaLabel = guideContainer.attr('aria-label');
41986
+ let stepNumberOrAuto = skipStepRegex.exec(guideContainerAriaLabel)[1];
42232
41987
  if (guideContainer) {
42233
41988
  guideContainer.attr({ 'aria-label': guideContainer.attr('aria-label').replace(skipStepRegex, '') });
42234
41989
  }
42235
- this.on('beforeAdvance', function (evt) {
41990
+ this.on('beforeAdvance', (evt) => {
42236
41991
  if (guide.getPositionOfStep(step) === guide.steps.length || pendo._.isUndefined(stepNumberOrAuto))
42237
41992
  return; // exit on the last step of a guide or when we don't have an argument
42238
- var eligibleStep = findEligibleSkipStep(stepNumberOrAuto, 'next');
41993
+ let eligibleStep = findEligibleSkipStep(stepNumberOrAuto, 'next');
42239
41994
  if (!isAdvanceIntercepted && stepNumberOrAuto) {
42240
41995
  isAdvanceIntercepted = true;
42241
- pendo.goToStep({ destinationStepId: eligibleStep.id, step: step });
41996
+ pendo.goToStep({ destinationStepId: eligibleStep.id, step });
42242
41997
  evt.cancel = true;
42243
41998
  }
42244
41999
  });
42245
- this.on('beforePrevious', function (evt) {
42000
+ this.on('beforePrevious', (evt) => {
42246
42001
  if (pendo._.isUndefined(stepNumberOrAuto))
42247
42002
  return;
42248
- var eligibleStep = findEligibleSkipStep(stepNumberOrAuto, 'previous');
42003
+ let eligibleStep = findEligibleSkipStep(stepNumberOrAuto, 'previous');
42249
42004
  if (!isPreviousIntercepted && stepNumberOrAuto) {
42250
42005
  isPreviousIntercepted = true;
42251
- pendo.goToStep({ destinationStepId: eligibleStep.id, step: step });
42006
+ pendo.goToStep({ destinationStepId: eligibleStep.id, step });
42252
42007
  evt.cancel = true;
42253
42008
  }
42254
42009
  });
42255
42010
  function findEligibleSkipStep(stepNumber, direction) {
42256
42011
  // Find the next eligible step by using getPosition of step (1 based)
42257
42012
  // getPosition - 2 gives the previous step
42258
- var skipForwardStep = findStepOnPage(guide.getPositionOfStep(step), 'next', stepNumber);
42259
- var skipPreviousStep = findStepOnPage(guide.getPositionOfStep(step) - 2, 'previous', stepNumber);
42013
+ let skipForwardStep = findStepOnPage(guide.getPositionOfStep(step), 'next', stepNumber);
42014
+ let skipPreviousStep = findStepOnPage(guide.getPositionOfStep(step) - 2, 'previous', stepNumber);
42260
42015
  if (skipForwardStep && direction == 'next') {
42261
- pendo.goToStep({ destinationStepId: skipForwardStep, step: step });
42016
+ pendo.goToStep({ destinationStepId: skipForwardStep, step });
42262
42017
  }
42263
42018
  if (skipPreviousStep && direction == 'previous') {
42264
- pendo.goToStep({ destinationStepId: skipPreviousStep, step: step });
42019
+ pendo.goToStep({ destinationStepId: skipPreviousStep, step });
42265
42020
  }
42266
42021
  return direction === 'next' ? skipForwardStep : skipPreviousStep;
42267
42022
  }
42268
42023
  function findStepOnPage(stepIndex, direction, stepNumber) {
42269
42024
  if (pendo._.isNaN(stepIndex))
42270
42025
  return;
42271
- var $step = guide.steps[stepIndex];
42026
+ let $step = guide.steps[stepIndex];
42272
42027
  if ($step && !$step.canShow()) {
42273
42028
  if (stepNumber !== 'auto') {
42274
42029
  return guide.steps[stepNumber - 1];
@@ -42285,34 +42040,34 @@ var SkipToEligibleStep = {
42285
42040
  }
42286
42041
  }
42287
42042
  },
42288
- test: function (step, guide, pendo) {
42043
+ test(step, guide, pendo) {
42289
42044
  var _a;
42290
- var guideContainerAriaLabel = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find(guideMarkdownUtil.containerSelector).attr('aria-label');
42045
+ const guideContainerAriaLabel = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find(guideMarkdownUtil.containerSelector).attr('aria-label');
42291
42046
  return pendo._.isString(guideContainerAriaLabel) && guideContainerAriaLabel.indexOf('{skipStep') !== -1;
42292
42047
  },
42293
- designerListener: function (pendo) {
42294
- var target = pendo.dom.getBody();
42295
- var config = {
42048
+ designerListener(pendo) {
42049
+ const target = pendo.dom.getBody();
42050
+ const config = {
42296
42051
  attributeFilter: ['data-layout'],
42297
42052
  attributes: true,
42298
42053
  childList: true,
42299
42054
  characterData: true,
42300
42055
  subtree: true
42301
42056
  };
42302
- var MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
42303
- var observer = new MutationObserver(applySkipStepIndicator);
42057
+ const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
42058
+ const observer = new MutationObserver(applySkipStepIndicator);
42304
42059
  observer.observe(target, config);
42305
42060
  // create an observer instance
42306
42061
  function applySkipStepIndicator(mutations) {
42307
42062
  pendo._.each(mutations, function (mutation) {
42308
42063
  var _a, _b;
42309
- var nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelectorAll);
42064
+ const nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelectorAll);
42310
42065
  if (mutation.addedNodes.length && nodeHasQuerySelector) {
42311
- var guideContainer = mutation.addedNodes[0].querySelectorAll(guideMarkdownUtil.containerSelector);
42312
- var guideContainerAriaLabel = (_b = guideContainer[0]) === null || _b === void 0 ? void 0 : _b.getAttribute('aria-label');
42066
+ let guideContainer = mutation.addedNodes[0].querySelectorAll(guideMarkdownUtil.containerSelector);
42067
+ let guideContainerAriaLabel = (_b = guideContainer[0]) === null || _b === void 0 ? void 0 : _b.getAttribute('aria-label');
42313
42068
  if (guideContainerAriaLabel) {
42314
42069
  if (guideContainerAriaLabel.match(skipStepRegex)) {
42315
- var fullSkipStepString = guideContainerAriaLabel.match(skipStepRegex)[0];
42070
+ let fullSkipStepString = guideContainerAriaLabel.match(skipStepRegex)[0];
42316
42071
  guideContainerAriaLabel.replace(fullSkipStepString, '');
42317
42072
  if (!pendo.dom('#_pendoSkipIcon').length) {
42318
42073
  pendo.dom(guideMarkdownUtil.containerSelector).append(skipIcon('#999', '30px').trim());
@@ -42323,30 +42078,48 @@ var SkipToEligibleStep = {
42323
42078
  });
42324
42079
  }
42325
42080
  function skipIcon(color, size) {
42326
- return ("<div title=\"Skip step added\"><svg id=\"_pendoSkipIcon\" version=\"1.0\" xmlns=\"http://www.w3.org/2000/svg\"\n width=\"".concat(size, "\" height=\"").concat(size, "\" viewBox=\"0 0 512.000000 512.000000\"\n preserveAspectRatio=\"xMidYMid meet\" style=\"bottom:5px; right:10px; position: absolute;\">\n <g transform=\"translate(0.000000,512.000000) scale(0.100000,-0.100000)\"\n fill=\"").concat(color, "\" stroke=\"none\">\n <path d=\"M2185 4469 c-363 -38 -739 -186 -1034 -407 -95 -71 -273 -243 -357\n -343 -205 -246 -364 -577 -429 -897 -25 -121 -45 -288 -45 -373 l0 -49 160 0\n 160 0 0 48 c0 26 5 88 10 137 68 593 417 1103 940 1374 1100 570 2418 -137\n 2560 -1374 5 -49 10 -111 10 -137 l0 -47 -155 -3 -155 -3 235 -235 235 -236\n 235 236 235 235 -155 3 -155 3 0 48 c0 27 -5 95 -10 152 -100 989 -878 1767\n -1869 1868 -117 12 -298 12 -416 0z\"/>\n <path d=\"M320 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z\"/>\n <path d=\"M960 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z\"/>\n <path d=\"M1600 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z\"/>\n <path d=\"M2240 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z\"/>\n <path d=\"M2880 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z\"/>\n <path d=\"M3840 1440 l0 -160 480 0 480 0 0 160 0 160 -480 0 -480 0 0 -160z\"/>\n </g></svg></div>\n "));
42081
+ return (`<div title="Skip step added"><svg id="_pendoSkipIcon" version="1.0" xmlns="http://www.w3.org/2000/svg"
42082
+ width="${size}" height="${size}" viewBox="0 0 512.000000 512.000000"
42083
+ preserveAspectRatio="xMidYMid meet" style="bottom:5px; right:10px; position: absolute;">
42084
+ <g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
42085
+ fill="${color}" stroke="none">
42086
+ <path d="M2185 4469 c-363 -38 -739 -186 -1034 -407 -95 -71 -273 -243 -357
42087
+ -343 -205 -246 -364 -577 -429 -897 -25 -121 -45 -288 -45 -373 l0 -49 160 0
42088
+ 160 0 0 48 c0 26 5 88 10 137 68 593 417 1103 940 1374 1100 570 2418 -137
42089
+ 2560 -1374 5 -49 10 -111 10 -137 l0 -47 -155 -3 -155 -3 235 -235 235 -236
42090
+ 235 236 235 235 -155 3 -155 3 0 48 c0 27 -5 95 -10 152 -100 989 -878 1767
42091
+ -1869 1868 -117 12 -298 12 -416 0z"/>
42092
+ <path d="M320 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
42093
+ <path d="M960 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
42094
+ <path d="M1600 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
42095
+ <path d="M2240 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
42096
+ <path d="M2880 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
42097
+ <path d="M3840 1440 l0 -160 480 0 480 0 0 160 0 160 -480 0 -480 0 0 -160z"/>
42098
+ </g></svg></div>
42099
+ `);
42327
42100
  }
42328
42101
  }
42329
42102
  };
42330
42103
 
42331
42104
  function GuideMarkdown() {
42332
- var guideMarkdown;
42333
- var pluginApi;
42334
- var globalPendo;
42105
+ let guideMarkdown;
42106
+ let pluginApi;
42107
+ let globalPendo;
42335
42108
  return {
42336
42109
  name: 'GuideMarkdown',
42337
42110
  initialize: init,
42338
- teardown: teardown
42111
+ teardown
42339
42112
  };
42340
42113
  function init(pendo, PluginAPI) {
42341
42114
  globalPendo = pendo;
42342
42115
  pluginApi = PluginAPI;
42343
- var configReader = PluginAPI.ConfigReader;
42344
- var GUIDEMARKDOWN_CONFIG = 'guideMarkdown';
42116
+ const configReader = PluginAPI.ConfigReader;
42117
+ const GUIDEMARKDOWN_CONFIG = 'guideMarkdown';
42345
42118
  configReader.addOption(GUIDEMARKDOWN_CONFIG, [
42346
42119
  configReader.sources.SNIPPET_SRC,
42347
42120
  configReader.sources.PENDO_CONFIG_SRC
42348
42121
  ], false);
42349
- var markdownScriptsEnabled = configReader.get(GUIDEMARKDOWN_CONFIG);
42122
+ const markdownScriptsEnabled = configReader.get(GUIDEMARKDOWN_CONFIG);
42350
42123
  if (!markdownScriptsEnabled)
42351
42124
  return;
42352
42125
  guideMarkdown = [PollBranching, MetadataSubstitution, RequiredQuestions, SkipToEligibleStep];
@@ -43385,8 +43158,8 @@ function Feedback() {
43385
43158
  var widgetLoaded = false;
43386
43159
  var feedbackAllowedProductId = '';
43387
43160
  var initialized = false;
43388
- var PING_COOKIE = 'feedback_ping_sent';
43389
- var PING_COOKIE_EXPIRATION = 1000 * 60 * 60;
43161
+ const PING_COOKIE = 'feedback_ping_sent';
43162
+ const PING_COOKIE_EXPIRATION = 1000 * 60 * 60;
43390
43163
  var overflowMediaQuery = '@media only screen and (max-device-width:1112px){#feedback-widget{overflow-y:scroll}}';
43391
43164
  var slideIn = '@-webkit-keyframes pendoFeedbackSlideIn{from{opacity:0;transform:translate(145px,0) rotate(270deg) translateY(-50%)}to{opacity:1;transform:translate(50%,0) rotate(270deg) translateY(-50%)}}@keyframes pendoFeedbackSlideIn{from{opacity:0;transform:translate(145px,0) rotate(270deg) translateY(-50%)}to{opacity:1;transform:translate(50%,0) rotate(270deg) translateY(-50%)}}';
43392
43165
  var slideInLeft = '@-webkit-keyframes pendoFeedbackSlideIn-left{from{opacity:0;transform:rotate(270deg) translateX(-55%) translateY(-55%)}to{opacity:1;transform:rotate(270deg) translateX(-55%) translateY(0)}}@keyframes pendoFeedbackSlideIn-left{from{opacity:0;transform:rotate(270deg) translateX(-55%) translateY(-55%)}to{opacity:1;transform:rotate(270deg) translateX(-55%) translateY(0)}}';
@@ -43406,28 +43179,28 @@ function Feedback() {
43406
43179
  feedbackStyles: 'pendo-feedback-styles',
43407
43180
  feedbackFrameStyles: 'pendo-feedback-visible-buttons-styles'
43408
43181
  };
43409
- var globalPendo;
43410
- var pluginApi;
43182
+ let globalPendo;
43183
+ let pluginApi;
43411
43184
  return {
43412
43185
  name: 'Feedback',
43413
- initialize: initialize,
43414
- teardown: teardown,
43415
- validate: validate
43186
+ initialize,
43187
+ teardown,
43188
+ validate
43416
43189
  };
43417
43190
  function initialize(pendo, PluginAPI) {
43418
43191
  globalPendo = pendo;
43419
43192
  pluginApi = PluginAPI;
43420
43193
  var publicFeedback = {
43421
- ping: ping,
43422
- init: init,
43194
+ ping,
43195
+ init,
43423
43196
  initialized: getInitialized,
43424
- loginAndRedirect: loginAndRedirect,
43425
- openFeedback: openFeedback,
43426
- initializeFeedbackOnce: initializeFeedbackOnce,
43427
- isFeedbackLoaded: isFeedbackLoaded,
43428
- convertPendoToFeedbackOptions: convertPendoToFeedbackOptions,
43197
+ loginAndRedirect,
43198
+ openFeedback,
43199
+ initializeFeedbackOnce,
43200
+ isFeedbackLoaded,
43201
+ convertPendoToFeedbackOptions,
43429
43202
  isUnsupportedIE: pendo._.partial(isUnsupportedIE, PluginAPI),
43430
- removeFeedbackWidget: removeFeedbackWidget
43203
+ removeFeedbackWidget
43431
43204
  };
43432
43205
  pendo.feedback = publicFeedback;
43433
43206
  pendo.getFeedbackSettings = getFeedbackSettings;
@@ -43455,7 +43228,7 @@ function Feedback() {
43455
43228
  */
43456
43229
  PluginAPI.agentStorage.registry.addLocal(PING_COOKIE, { duration: PING_COOKIE_EXPIRATION });
43457
43230
  return {
43458
- validate: validate
43231
+ validate
43459
43232
  };
43460
43233
  }
43461
43234
  function teardown() {
@@ -43475,18 +43248,18 @@ function Feedback() {
43475
43248
  return result;
43476
43249
  }
43477
43250
  function pingOrInitialize() {
43478
- var options = getPendoOptions();
43251
+ const options = getPendoOptions();
43479
43252
  if (initialized) {
43480
- var feedbackOptions = convertPendoToFeedbackOptions(options);
43253
+ const feedbackOptions = convertPendoToFeedbackOptions(options);
43481
43254
  ping(feedbackOptions);
43482
43255
  }
43483
43256
  else if (shouldInitializeFeedback() && !globalPendo._.isEmpty(options)) {
43484
- var settings = pluginApi.ConfigReader.get('feedbackSettings');
43485
- init(options, settings)["catch"](globalPendo._.noop);
43257
+ const settings = pluginApi.ConfigReader.get('feedbackSettings');
43258
+ init(options, settings).catch(globalPendo._.noop);
43486
43259
  }
43487
43260
  }
43488
43261
  function handleIdentityChange(event) {
43489
- var visitorId = globalPendo._.get(event, 'data.0.visitor_id') || globalPendo._.get(event, 'data.0.options.visitor.id');
43262
+ const visitorId = globalPendo._.get(event, 'data.0.visitor_id') || globalPendo._.get(event, 'data.0.options.visitor.id');
43490
43263
  if (globalPendo.isAnonymousVisitor(visitorId)) {
43491
43264
  removeFeedbackWidget();
43492
43265
  return;
@@ -43556,9 +43329,9 @@ function Feedback() {
43556
43329
  if (toSend.data && toSend.data !== '{}' && toSend.data !== 'null') {
43557
43330
  return globalPendo.ajax
43558
43331
  .postJSON(getFullUrl('/widget/pendo_ping'), toSend)
43559
- .then(function (response) {
43332
+ .then((response) => {
43560
43333
  onWidgetPingResponse(response);
43561
- })["catch"](function () { onPingFailure(); });
43334
+ }).catch(() => { onPingFailure(); });
43562
43335
  }
43563
43336
  }
43564
43337
  return pluginApi.q.resolve();
@@ -43692,10 +43465,10 @@ function Feedback() {
43692
43465
  return globalPendo.ajax.postJSON(getFullUrl('/analytics'), toSend);
43693
43466
  }
43694
43467
  function addOverlay() {
43695
- var widget = globalPendo.dom("#".concat(elemIds.feedbackWidget));
43468
+ const widget = globalPendo.dom(`#${elemIds.feedbackWidget}`);
43696
43469
  if (!widget)
43697
43470
  return;
43698
- var overlayStyles = {
43471
+ const overlayStyles = {
43699
43472
  'position': 'fixed',
43700
43473
  'top': '0',
43701
43474
  'right': '0',
@@ -43707,7 +43480,7 @@ function Feedback() {
43707
43480
  'animation': 'pendoFeedbackFadeIn 0.5s 0s 1 alternate both',
43708
43481
  '-webkit-animation': 'pendoFeedbackFadeIn 0.5s 0s 1 alternate both'
43709
43482
  };
43710
- var overlayElement = globalPendo.dom(document.createElement('div'));
43483
+ const overlayElement = globalPendo.dom(document.createElement('div'));
43711
43484
  overlayElement.attr('id', 'feedback-overlay');
43712
43485
  overlayElement.css(overlayStyles);
43713
43486
  overlayElement.appendTo(widget.getParent());
@@ -43812,22 +43585,22 @@ function Feedback() {
43812
43585
  }
43813
43586
  }
43814
43587
  function buildOuterTriggerDiv(positionInfo) {
43815
- var horizontalStyles = getHorizontalPositionStyles(positionInfo);
43816
- var verticalStyles = getVerticalPositionStyles(positionInfo);
43817
- var styles = globalPendo._.extend({
43588
+ const horizontalStyles = getHorizontalPositionStyles(positionInfo);
43589
+ const verticalStyles = getVerticalPositionStyles(positionInfo);
43590
+ const styles = globalPendo._.extend({
43818
43591
  'position': 'fixed',
43819
43592
  'height': '43px',
43820
43593
  'opacity': '1 !important',
43821
43594
  'z-index': '9001'
43822
43595
  }, horizontalStyles, verticalStyles);
43823
- var outerTrigger = globalPendo.dom(document.createElement('div'));
43596
+ const outerTrigger = globalPendo.dom(document.createElement('div'));
43824
43597
  outerTrigger.attr('id', elemIds.feedbackTrigger);
43825
43598
  outerTrigger.css(styles);
43826
43599
  outerTrigger.attr('data-turbolinks-permanent', '');
43827
43600
  return outerTrigger;
43828
43601
  }
43829
43602
  function buildNotification() {
43830
- var styles = {
43603
+ const styles = {
43831
43604
  'background-color': '#D85039',
43832
43605
  'color': '#fff',
43833
43606
  'border-radius': '50%',
@@ -43844,20 +43617,20 @@ function Feedback() {
43844
43617
  'animation-delay': '1s',
43845
43618
  'animation-iteration-count': '1'
43846
43619
  };
43847
- var notification = globalPendo.dom(document.createElement('span'));
43620
+ const notification = globalPendo.dom(document.createElement('span'));
43848
43621
  notification.attr('id', 'feedback-trigger-notification');
43849
43622
  notification.css(styles);
43850
43623
  return notification;
43851
43624
  }
43852
43625
  function buildTriggerButton(settings, positionInfo) {
43853
- var borderRadius;
43626
+ let borderRadius;
43854
43627
  if (positionInfo.horizontalPosition === 'left') {
43855
43628
  borderRadius = '0 0 5px 5px';
43856
43629
  }
43857
43630
  else {
43858
43631
  borderRadius = '3px 3px 0 0';
43859
43632
  }
43860
- var styles = {
43633
+ const styles = {
43861
43634
  'border': 'none',
43862
43635
  'padding': '11px 18px 14px 18px',
43863
43636
  'background-color': settings.triggerColor,
@@ -43868,21 +43641,32 @@ function Feedback() {
43868
43641
  'cursor': 'pointer',
43869
43642
  'text-align': 'left'
43870
43643
  };
43871
- var triggerButton = globalPendo.dom(document.createElement('button'));
43644
+ const triggerButton = globalPendo.dom(document.createElement('button'));
43872
43645
  triggerButton.attr('id', elemIds.feedbackTriggerButton);
43873
43646
  triggerButton.css(styles);
43874
43647
  triggerButton.text(settings.triggerText);
43875
43648
  return triggerButton;
43876
43649
  }
43877
43650
  function addTriggerPseudoStyles() {
43878
- var pseudoStyles = "\n #feedback-trigger button:hover {\n box-shadow: 0 -5px 20px rgba(0,0,0,.19) !important;\n outline: none !important;\n background: #3e566f !important;\n }\n #feedback-trigger button:focus {\n box-shadow: 0 -5px 20px rgba(0,0,0,.19) !important;\n outline: none !important;\n background: #3e566f !important;\n }\n ";
43651
+ const pseudoStyles = `
43652
+ #feedback-trigger button:hover {
43653
+ box-shadow: 0 -5px 20px rgba(0,0,0,.19) !important;
43654
+ outline: none !important;
43655
+ background: #3e566f !important;
43656
+ }
43657
+ #feedback-trigger button:focus {
43658
+ box-shadow: 0 -5px 20px rgba(0,0,0,.19) !important;
43659
+ outline: none !important;
43660
+ background: #3e566f !important;
43661
+ }
43662
+ `;
43879
43663
  pluginApi.util.addInlineStyles('pendo-feedback-trigger-styles', pseudoStyles);
43880
43664
  }
43881
43665
  function createTrigger(settings, positionInfo) {
43882
43666
  addTriggerPseudoStyles();
43883
- var triggerElement = buildOuterTriggerDiv(positionInfo);
43884
- var notificationElement = buildNotification();
43885
- var triggerButtonElement = buildTriggerButton(settings, positionInfo);
43667
+ const triggerElement = buildOuterTriggerDiv(positionInfo);
43668
+ const notificationElement = buildNotification();
43669
+ const triggerButtonElement = buildTriggerButton(settings, positionInfo);
43886
43670
  triggerElement.append(notificationElement);
43887
43671
  triggerElement.append(triggerButtonElement);
43888
43672
  triggerElement.appendTo(globalPendo.dom.getBody());
@@ -43906,7 +43690,7 @@ function Feedback() {
43906
43690
  iframeWrapper.css(getWidgetOriginalStyles());
43907
43691
  iframeWrapper.attr('id', elemIds.feedbackWidget);
43908
43692
  iframeWrapper.attr('data-turbolinks-permanent', 'true');
43909
- iframeWrapper.addClass("buttonIs-".concat(horizontalPosition));
43693
+ iframeWrapper.addClass(`buttonIs-${horizontalPosition}`);
43910
43694
  return iframeWrapper;
43911
43695
  }
43912
43696
  function buildIframeContainer() {
@@ -43923,13 +43707,22 @@ function Feedback() {
43923
43707
  return iframeContainer;
43924
43708
  }
43925
43709
  function addWidgetVisibleButtonStyles(buttonStylePosition) {
43926
- var side = buttonStylePosition === 'left' ? 'left' : 'right'; // just in case something was not left or right for some reason
43927
- var styles = "\n .buttonIs-".concat(side, ".visible {\n ").concat(side, ": 0 !important;\n width: 470px !important;\n animation-direction: alternate-reverse !important;\n animation: pendoFeedbackSlideFrom-").concat(side, " 0.5s 0s 1 alternate both !important;\n -webkit-animation: pendoFeedbackSlideFrom-").concat(side, " 0.5s 0s 1 alternate both !important;\n z-index: 9002 !important;\n }\n ");
43710
+ let side = buttonStylePosition === 'left' ? 'left' : 'right'; // just in case something was not left or right for some reason
43711
+ const styles = `
43712
+ .buttonIs-${side}.visible {
43713
+ ${side}: 0 !important;
43714
+ width: 470px !important;
43715
+ animation-direction: alternate-reverse !important;
43716
+ animation: pendoFeedbackSlideFrom-${side} 0.5s 0s 1 alternate both !important;
43717
+ -webkit-animation: pendoFeedbackSlideFrom-${side} 0.5s 0s 1 alternate both !important;
43718
+ z-index: 9002 !important;
43719
+ }
43720
+ `;
43928
43721
  pluginApi.util.addInlineStyles(elemIds.feedbackFrameStyles, styles);
43929
43722
  }
43930
43723
  function initialiseWidgetFrame(horizontalPosition) {
43931
43724
  addWidgetVisibleButtonStyles(horizontalPosition);
43932
- var iframeElement = buildIframeWrapper(horizontalPosition);
43725
+ const iframeElement = buildIframeWrapper(horizontalPosition);
43933
43726
  iframeElement.append(buildIframeContainer());
43934
43727
  iframeElement.appendTo(globalPendo.dom.getBody());
43935
43728
  subscribeToIframeMessages();
@@ -43953,7 +43746,7 @@ function Feedback() {
43953
43746
  return widgetLoaded;
43954
43747
  }
43955
43748
  function getPendoOptions() {
43956
- var options = pluginApi.ConfigReader.getLocalConfig();
43749
+ let options = pluginApi.ConfigReader.getLocalConfig();
43957
43750
  if (!globalPendo._.isObject(options))
43958
43751
  options = {};
43959
43752
  if (!globalPendo._.isObject(options.visitor))
@@ -43981,7 +43774,7 @@ function Feedback() {
43981
43774
  return true;
43982
43775
  }
43983
43776
  function getQueryParam(url, paramName) {
43984
- var results = new RegExp('[?&]' + paramName + '=([^&#]*)').exec(url);
43777
+ const results = new RegExp('[?&]' + paramName + '=([^&#]*)').exec(url);
43985
43778
  if (results == null) {
43986
43779
  return null;
43987
43780
  }
@@ -43998,13 +43791,13 @@ function Feedback() {
43998
43791
  return pluginApi.q.reject();
43999
43792
  if (!canInitFeedback(pendoOptions))
44000
43793
  return pluginApi.q.reject();
44001
- var feedbackOptions = convertPendoToFeedbackOptions(pendoOptions);
43794
+ const feedbackOptions = convertPendoToFeedbackOptions(pendoOptions);
44002
43795
  try {
44003
- var fdbkDst_1 = getQueryParam(globalPendo.url.get(), 'fdbkDst');
44004
- if (fdbkDst_1 && fdbkDst_1.startsWith('case')) {
43796
+ const fdbkDst = getQueryParam(globalPendo.url.get(), 'fdbkDst');
43797
+ if (fdbkDst && fdbkDst.startsWith('case')) {
44005
43798
  initialized = true;
44006
43799
  getFeedbackLoginUrl().then(function (loginUrl) {
44007
- var destinationUrl = loginUrl + '&fdbkDst=' + fdbkDst_1;
43800
+ const destinationUrl = loginUrl + '&fdbkDst=' + fdbkDst;
44008
43801
  window.location.href = destinationUrl;
44009
43802
  });
44010
43803
  return;
@@ -44053,7 +43846,7 @@ function Feedback() {
44053
43846
  function convertPendoToFeedbackOptions(options) {
44054
43847
  var jwtOptions = pluginApi.agent.getJwtInfoCopy();
44055
43848
  if (globalPendo._.isEmpty(jwtOptions)) {
44056
- var feedbackOptions = {};
43849
+ const feedbackOptions = {};
44057
43850
  feedbackOptions.user = globalPendo._.pick(options.visitor, 'id', 'full_name', 'firstName', 'lastName', 'email', 'tags', 'custom_allowed_products');
44058
43851
  globalPendo._.extend(feedbackOptions.user, { allowed_products: [{ id: feedbackAllowedProductId }] });
44059
43852
  feedbackOptions.account = globalPendo._.pick(options.account, 'id', 'name', 'monthly_value', 'is_paying', 'tags');
@@ -49643,17 +49436,6 @@ var SessionRecorderBuffer = /** @class */ (function () {
49643
49436
  return SessionRecorderBuffer;
49644
49437
  }());
49645
49438
 
49646
- var __assign = function() {
49647
- __assign = Object.assign || function __assign(t) {
49648
- for (var s, i = 1, n = arguments.length; i < n; i++) {
49649
- s = arguments[i];
49650
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
49651
- }
49652
- return t;
49653
- };
49654
- return __assign.apply(this, arguments);
49655
- };
49656
-
49657
49439
  function __rest(s, e) {
49658
49440
  var t = {};
49659
49441
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -51818,7 +51600,7 @@ function includes(str, substring) {
51818
51600
  function getResourceType(blockedURI, directive) {
51819
51601
  if (!directive || typeof directive !== 'string')
51820
51602
  return 'resource';
51821
- var d = directive.toLowerCase();
51603
+ const d = directive.toLowerCase();
51822
51604
  if (blockedURI === 'inline') {
51823
51605
  if (includes(d, 'script-src-attr')) {
51824
51606
  return 'inline event handler';
@@ -51877,12 +51659,11 @@ function getResourceType(blockedURI, directive) {
51877
51659
  function getDirective(policy, directiveName) {
51878
51660
  if (!policy || !directiveName)
51879
51661
  return '';
51880
- var needle = directiveName.toLowerCase();
51881
- for (var _i = 0, _a = policy.split(';'); _i < _a.length; _i++) {
51882
- var directive = _a[_i];
51883
- var trimmed = directive.trim();
51884
- var lower = trimmed.toLowerCase();
51885
- if (lower === needle || lower.startsWith("".concat(needle, " "))) {
51662
+ const needle = directiveName.toLowerCase();
51663
+ for (const directive of policy.split(';')) {
51664
+ const trimmed = directive.trim();
51665
+ const lower = trimmed.toLowerCase();
51666
+ if (lower === needle || lower.startsWith(`${needle} `)) {
51886
51667
  return trimmed;
51887
51668
  }
51888
51669
  }
@@ -51904,7 +51685,7 @@ function getDirective(policy, directiveName) {
51904
51685
  function getArticle(phrase) {
51905
51686
  if (!phrase || typeof phrase !== 'string')
51906
51687
  return 'A';
51907
- var c = phrase.trim().charAt(0).toLowerCase();
51688
+ const c = phrase.trim().charAt(0).toLowerCase();
51908
51689
  return includes('aeiou', c) ? 'An' : 'A';
51909
51690
  }
51910
51691
  /**
@@ -51947,47 +51728,46 @@ function createCspViolationMessage(blockedURI, directive, isReportOnly, original
51947
51728
  return 'Content Security Policy: Unknown violation occurred.';
51948
51729
  }
51949
51730
  try {
51950
- var reportOnlyText = isReportOnly ? ' (Report-Only)' : '';
51731
+ const reportOnlyText = isReportOnly ? ' (Report-Only)' : '';
51951
51732
  // special case for frame-ancestors since it doesn't fit our template at all
51952
51733
  if ((directive === null || directive === void 0 ? void 0 : directive.toLowerCase()) === 'frame-ancestors') {
51953
- return "Content Security Policy".concat(reportOnlyText, ": The display of ").concat(blockedURI, " in a frame was blocked because an ancestor violates your site's frame-ancestors policy.\nCurrent CSP: \"").concat(originalPolicy, "\".");
51734
+ return `Content Security Policy${reportOnlyText}: The display of ${blockedURI} in a frame was blocked because an ancestor violates your site's frame-ancestors policy.\nCurrent CSP: "${originalPolicy}".`;
51954
51735
  }
51955
- var resourceType = getResourceType(blockedURI, directive);
51956
- var article = getArticle(resourceType);
51957
- var source = formatBlockedUri(blockedURI);
51958
- var directiveValue = getDirective(originalPolicy, directive);
51959
- var policyDisplay = directiveValue || directive;
51960
- var resourceDescription = "".concat(article, " ").concat(resourceType).concat(source ? " from ".concat(source) : '');
51961
- return "Content Security Policy".concat(reportOnlyText, ": ").concat(resourceDescription, " was blocked by your site's `").concat(policyDisplay, "` policy.\nCurrent CSP: \"").concat(originalPolicy, "\".");
51736
+ const resourceType = getResourceType(blockedURI, directive);
51737
+ const article = getArticle(resourceType);
51738
+ const source = formatBlockedUri(blockedURI);
51739
+ const directiveValue = getDirective(originalPolicy, directive);
51740
+ const policyDisplay = directiveValue || directive;
51741
+ const resourceDescription = `${article} ${resourceType}${source ? ` from ${source}` : ''}`;
51742
+ return `Content Security Policy${reportOnlyText}: ${resourceDescription} was blocked by your site's \`${policyDisplay}\` policy.\nCurrent CSP: "${originalPolicy}".`;
51962
51743
  }
51963
51744
  catch (error) {
51964
- return "Content Security Policy: Error formatting violation message: ".concat(error.message);
51745
+ return `Content Security Policy: Error formatting violation message: ${error.message}`;
51965
51746
  }
51966
51747
  }
51967
51748
 
51968
- var MAX_LENGTH = 1000;
51969
- var PII_PATTERN = {
51749
+ const MAX_LENGTH = 1000;
51750
+ const PII_PATTERN = {
51970
51751
  ip: /\b(?:\d{1,3}\.){3}\d{1,3}\b/g,
51971
51752
  ssn: /\b\d{3}-\d{2}-\d{4}\b/g,
51972
51753
  creditCard: /\b(?:\d[ -]?){12,18}\d\b/g,
51973
51754
  httpsUrls: /https:\/\/[^\s]+/g,
51974
51755
  email: /[\w._+-]+@[\w.-]+\.\w+/g
51975
51756
  };
51976
- var PII_REPLACEMENT = '*'.repeat(10);
51977
- var JSON_PII_KEYS = ['password', 'email', 'key', 'token', 'auth', 'authentication', 'phone', 'address', 'ssn'];
51978
- var UNABLE_TO_DISPLAY_BODY = '[Unable to display body: detected PII could not be redacted]';
51979
- var joinedKeys = JSON_PII_KEYS.join('|');
51980
- var keyPattern = "\"([^\"]*(?:".concat(joinedKeys, ")[^\"]*)\"");
51757
+ const PII_REPLACEMENT = '*'.repeat(10);
51758
+ const JSON_PII_KEYS = ['password', 'email', 'key', 'token', 'auth', 'authentication', 'phone', 'address', 'ssn'];
51759
+ const UNABLE_TO_DISPLAY_BODY = '[Unable to display body: detected PII could not be redacted]';
51760
+ const joinedKeys = JSON_PII_KEYS.join('|');
51761
+ const keyPattern = `"([^"]*(?:${joinedKeys})[^"]*)"`;
51981
51762
  // only scrub strings, numbers, and booleans
51982
- var acceptedValues = '("([^"\\\\]*(?:\\\\.[^"\\\\]*)*")|(\\d+)|(true|false))';
51763
+ const acceptedValues = '("([^"\\\\]*(?:\\\\.[^"\\\\]*)*")|(\\d+)|(true|false))';
51983
51764
  /**
51984
51765
  * Truncates a string to the max length
51985
51766
  * @access private
51986
51767
  * @param {String} string
51987
51768
  * @returns {String}
51988
51769
  */
51989
- function truncate(string, includeEllipsis) {
51990
- if (includeEllipsis === void 0) { includeEllipsis = false; }
51770
+ function truncate(string, includeEllipsis = false) {
51991
51771
  if (string.length <= MAX_LENGTH)
51992
51772
  return string;
51993
51773
  if (includeEllipsis) {
@@ -52004,7 +51784,7 @@ function truncate(string, includeEllipsis) {
52004
51784
  * @returns {String}
52005
51785
  */
52006
51786
  function generateLogKey(methodName, message, stackTrace) {
52007
- return "".concat(methodName, "|").concat(message, "|").concat(stackTrace);
51787
+ return `${methodName}|${message}|${stackTrace}`;
52008
51788
  }
52009
51789
  /**
52010
51790
  * Checks if a string has 2 or more digits, a https URL, or an email address
@@ -52021,13 +51801,12 @@ function mightContainPII(string) {
52021
51801
  * @param {String} string
52022
51802
  * @returns {String}
52023
51803
  */
52024
- function scrubPII(_a) {
52025
- var string = _a.string, _ = _a._;
51804
+ function scrubPII({ string, _ }) {
52026
51805
  if (!string || typeof string !== 'string')
52027
51806
  return string;
52028
51807
  if (!mightContainPII(string))
52029
51808
  return string;
52030
- return _.reduce(_.values(PII_PATTERN), function (str, pattern) { return str.replace(pattern, PII_REPLACEMENT); }, string);
51809
+ return _.reduce(_.values(PII_PATTERN), (str, pattern) => str.replace(pattern, PII_REPLACEMENT), string);
52031
51810
  }
52032
51811
  /**
52033
51812
  * Scrub PII from a stringified JSON object
@@ -52036,14 +51815,12 @@ function scrubPII(_a) {
52036
51815
  * @returns {String}
52037
51816
  */
52038
51817
  function scrubJsonPII(string) {
52039
- var fullScrubRegex = new RegExp("".concat(keyPattern, "\\s*:\\s*[\\{\\[]"), 'i');
51818
+ const fullScrubRegex = new RegExp(`${keyPattern}\\s*:\\s*[\\{\\[]`, 'i');
52040
51819
  if (fullScrubRegex.test(string)) {
52041
51820
  return UNABLE_TO_DISPLAY_BODY;
52042
51821
  }
52043
- var keyValueScrubRegex = new RegExp("".concat(keyPattern, "\\s*:\\s*").concat(acceptedValues), 'gi');
52044
- return string.replace(keyValueScrubRegex, function (match, key) {
52045
- return "\"".concat(key, "\":\"").concat(PII_REPLACEMENT, "\"");
52046
- });
51822
+ const keyValueScrubRegex = new RegExp(`${keyPattern}\\s*:\\s*${acceptedValues}`, 'gi');
51823
+ return string.replace(keyValueScrubRegex, (match, key) => `"${key}":"${PII_REPLACEMENT}"`);
52047
51824
  }
52048
51825
  /**
52049
51826
  * Checks if a string is a JSON object
@@ -52055,7 +51832,7 @@ function scrubJsonPII(string) {
52055
51832
  function mightContainJson(string, contentType) {
52056
51833
  if (!string || typeof string !== 'string')
52057
51834
  return false;
52058
- var firstChar = string.charAt(0);
51835
+ const firstChar = string.charAt(0);
52059
51836
  if (contentType && contentType.indexOf('application/json') !== -1) {
52060
51837
  return true;
52061
51838
  }
@@ -52068,20 +51845,19 @@ function mightContainJson(string, contentType) {
52068
51845
  * @param {String} contentType
52069
51846
  * @returns {String}
52070
51847
  */
52071
- function maskSensitiveFields(_a) {
52072
- var string = _a.string, contentType = _a.contentType, _ = _a._;
51848
+ function maskSensitiveFields({ string, contentType, _ }) {
52073
51849
  if (!string || typeof string !== 'string')
52074
51850
  return string;
52075
51851
  if (mightContainJson(string, contentType)) {
52076
51852
  string = scrubJsonPII(string);
52077
51853
  }
52078
51854
  if (mightContainPII(string)) {
52079
- string = scrubPII({ string: string, _: _ });
51855
+ string = scrubPII({ string, _ });
52080
51856
  }
52081
51857
  return string;
52082
51858
  }
52083
51859
 
52084
- var DEV_LOG_TYPE = 'devlog';
51860
+ const DEV_LOG_TYPE = 'devlog';
52085
51861
  function createDevLogEnvelope(pluginAPI, globalPendo) {
52086
51862
  return {
52087
51863
  browser_time: pluginAPI.util.getNow(),
@@ -52092,12 +51868,12 @@ function createDevLogEnvelope(pluginAPI, globalPendo) {
52092
51868
  };
52093
51869
  }
52094
51870
 
52095
- var TOKEN_MAX_SIZE = 100;
52096
- var TOKEN_REFILL_RATE = 10;
52097
- var TOKEN_REFRESH_INTERVAL = 1000;
52098
- var MAX_UNCOMPRESSED_SIZE = 125000; // 125KB
52099
- var DevlogBuffer = /** @class */ (function () {
52100
- function DevlogBuffer(pendo, pluginAPI) {
51871
+ const TOKEN_MAX_SIZE = 100;
51872
+ const TOKEN_REFILL_RATE = 10;
51873
+ const TOKEN_REFRESH_INTERVAL = 1000;
51874
+ const MAX_UNCOMPRESSED_SIZE = 125000; // 125KB
51875
+ class DevlogBuffer {
51876
+ constructor(pendo, pluginAPI) {
52101
51877
  this.pendo = pendo;
52102
51878
  this.pluginAPI = pluginAPI;
52103
51879
  this.events = [];
@@ -52108,36 +51884,36 @@ var DevlogBuffer = /** @class */ (function () {
52108
51884
  this.lastRefillTime = this.pluginAPI.util.getNow();
52109
51885
  this.nextRefillTime = this.lastRefillTime + TOKEN_REFRESH_INTERVAL;
52110
51886
  }
52111
- DevlogBuffer.prototype.isEmpty = function () {
51887
+ isEmpty() {
52112
51888
  return this.events.length === 0 && this.payloads.length === 0;
52113
- };
52114
- DevlogBuffer.prototype.refillTokens = function () {
52115
- var now = this.pluginAPI.util.getNow();
51889
+ }
51890
+ refillTokens() {
51891
+ const now = this.pluginAPI.util.getNow();
52116
51892
  if (now >= this.nextRefillTime) {
52117
- var timeSinceLastRefill = now - this.lastRefillTime;
52118
- var secondsSinceLastRefill = Math.floor(timeSinceLastRefill / TOKEN_REFRESH_INTERVAL);
52119
- var tokensToRefill = secondsSinceLastRefill * TOKEN_REFILL_RATE;
51893
+ const timeSinceLastRefill = now - this.lastRefillTime;
51894
+ const secondsSinceLastRefill = Math.floor(timeSinceLastRefill / TOKEN_REFRESH_INTERVAL);
51895
+ const tokensToRefill = secondsSinceLastRefill * TOKEN_REFILL_RATE;
52120
51896
  this.tokens = Math.min(this.tokens + tokensToRefill, TOKEN_MAX_SIZE);
52121
51897
  this.lastRefillTime = now;
52122
51898
  this.nextRefillTime = now + TOKEN_REFRESH_INTERVAL;
52123
51899
  }
52124
- };
52125
- DevlogBuffer.prototype.clear = function () {
51900
+ }
51901
+ clear() {
52126
51902
  this.events = [];
52127
51903
  this.lastEvent = null;
52128
51904
  this.uncompressedSize = 0;
52129
- };
52130
- DevlogBuffer.prototype.hasTokenAvailable = function () {
51905
+ }
51906
+ hasTokenAvailable() {
52131
51907
  this.refillTokens();
52132
51908
  return this.tokens > 0;
52133
- };
52134
- DevlogBuffer.prototype.estimateEventSize = function (event) {
51909
+ }
51910
+ estimateEventSize(event) {
52135
51911
  return JSON.stringify(event).length;
52136
- };
52137
- DevlogBuffer.prototype.push = function (event) {
51912
+ }
51913
+ push(event) {
52138
51914
  if (!this.hasTokenAvailable())
52139
51915
  return false;
52140
- var eventSize = this.estimateEventSize(event);
51916
+ const eventSize = this.estimateEventSize(event);
52141
51917
  if (this.uncompressedSize + eventSize > MAX_UNCOMPRESSED_SIZE) {
52142
51918
  this.compressCurrentChunk();
52143
51919
  }
@@ -52146,55 +51922,54 @@ var DevlogBuffer = /** @class */ (function () {
52146
51922
  this.events.push(event);
52147
51923
  this.tokens = Math.max(this.tokens - 1, 0);
52148
51924
  return true;
52149
- };
52150
- DevlogBuffer.prototype.compressCurrentChunk = function () {
51925
+ }
51926
+ compressCurrentChunk() {
52151
51927
  if (this.events.length === 0)
52152
51928
  return;
52153
- var jzb = this.pendo.compress(this.events);
51929
+ const jzb = this.pendo.compress(this.events);
52154
51930
  this.payloads.push(jzb);
52155
51931
  this.clear();
52156
- };
52157
- DevlogBuffer.prototype.generateUrl = function () {
52158
- var queryParams = {
51932
+ }
51933
+ generateUrl() {
51934
+ const queryParams = {
52159
51935
  v: this.pendo.VERSION,
52160
51936
  ct: this.pluginAPI.util.getNow()
52161
51937
  };
52162
51938
  return this.pluginAPI.transmit.buildBaseDataUrl(DEV_LOG_TYPE, this.pendo.apiKey, queryParams);
52163
- };
52164
- DevlogBuffer.prototype.pack = function () {
51939
+ }
51940
+ pack() {
52165
51941
  if (this.isEmpty())
52166
51942
  return;
52167
- var url = this.generateUrl();
51943
+ const url = this.generateUrl();
52168
51944
  this.compressCurrentChunk();
52169
- var payloads = this.pendo._.map(this.payloads, function (jzb) { return ({
52170
- jzb: jzb,
52171
- url: url
52172
- }); });
51945
+ const payloads = this.pendo._.map(this.payloads, (jzb) => ({
51946
+ jzb,
51947
+ url
51948
+ }));
52173
51949
  this.payloads = [];
52174
51950
  return payloads;
52175
- };
52176
- return DevlogBuffer;
52177
- }());
51951
+ }
51952
+ }
52178
51953
 
52179
- var DevlogTransport = /** @class */ (function () {
52180
- function DevlogTransport(globalPendo, pluginAPI) {
51954
+ class DevlogTransport {
51955
+ constructor(globalPendo, pluginAPI) {
52181
51956
  this.pendo = globalPendo;
52182
51957
  this.pluginAPI = pluginAPI;
52183
51958
  }
52184
- DevlogTransport.prototype.buildGetUrl = function (baseUrl, jzb) {
52185
- var params = {};
51959
+ buildGetUrl(baseUrl, jzb) {
51960
+ const params = {};
52186
51961
  if (this.pluginAPI.agent.treatAsAdoptPartner()) {
52187
51962
  this.pluginAPI.agent.addAccountIdParams(params, this.pendo.get_account_id(), this.pluginAPI.ConfigReader.get('oemAccountId'));
52188
51963
  }
52189
- var jwtOptions = this.pluginAPI.agent.getJwtInfoCopy();
51964
+ const jwtOptions = this.pluginAPI.agent.getJwtInfoCopy();
52190
51965
  if (!this.pendo._.isEmpty(jwtOptions)) {
52191
51966
  this.pendo._.extend(params, jwtOptions);
52192
51967
  }
52193
51968
  params.jzb = jzb;
52194
- var queryString = this.pendo._.map(params, function (value, key) { return "".concat(key, "=").concat(value); }).join('&');
52195
- return "".concat(baseUrl).concat(baseUrl.indexOf('?') !== -1 ? '&' : '?').concat(queryString);
52196
- };
52197
- DevlogTransport.prototype.get = function (url, options) {
51969
+ const queryString = this.pendo._.map(params, (value, key) => `${key}=${value}`).join('&');
51970
+ return `${baseUrl}${baseUrl.indexOf('?') !== -1 ? '&' : '?'}${queryString}`;
51971
+ }
51972
+ get(url, options) {
52198
51973
  options.method = 'GET';
52199
51974
  if (this.pluginAPI.transmit.fetchKeepalive.supported()) {
52200
51975
  return this.pluginAPI.transmit.fetchKeepalive(url, options);
@@ -52202,90 +51977,86 @@ var DevlogTransport = /** @class */ (function () {
52202
51977
  else {
52203
51978
  return this.pendo.ajax.get(url);
52204
51979
  }
52205
- };
52206
- DevlogTransport.prototype.sendRequestWithGet = function (_a) {
52207
- var url = _a.url, jzb = _a.jzb;
52208
- var getUrl = this.buildGetUrl(url, jzb);
51980
+ }
51981
+ sendRequestWithGet({ url, jzb }) {
51982
+ const getUrl = this.buildGetUrl(url, jzb);
52209
51983
  return this.get(getUrl, {
52210
51984
  headers: {
52211
51985
  'Content-Type': 'application/octet-stream'
52212
51986
  }
52213
51987
  });
52214
- };
52215
- DevlogTransport.prototype.post = function (url, options) {
51988
+ }
51989
+ post(url, options) {
52216
51990
  options.method = 'POST';
52217
51991
  if (options.keepalive && this.pluginAPI.transmit.fetchKeepalive.supported()) {
52218
51992
  return this.pluginAPI.transmit.fetchKeepalive(url, options);
52219
51993
  }
52220
51994
  else if (options.keepalive && this.pluginAPI.transmit.sendBeacon.supported()) {
52221
- var result = this.pluginAPI.transmit.sendBeacon(url, new Blob([options.body]));
51995
+ const result = this.pluginAPI.transmit.sendBeacon(url, new Blob([options.body]));
52222
51996
  return result ? Promise$2.resolve() : Promise$2.reject(new Error('sendBeacon failed to send devlog data'));
52223
51997
  }
52224
51998
  else {
52225
51999
  return this.pendo.ajax.post(url, options.body);
52226
52000
  }
52227
- };
52228
- DevlogTransport.prototype.sendRequestWithPost = function (_a, isUnload) {
52229
- var url = _a.url, jzb = _a.jzb;
52230
- var jwtOptions = this.pluginAPI.agent.getJwtInfoCopy();
52231
- var bodyPayload = {
52001
+ }
52002
+ sendRequestWithPost({ url, jzb }, isUnload) {
52003
+ const jwtOptions = this.pluginAPI.agent.getJwtInfoCopy();
52004
+ const bodyPayload = {
52232
52005
  events: jzb,
52233
52006
  browser_time: this.pluginAPI.util.getNow()
52234
52007
  };
52235
52008
  if (this.pluginAPI.agent.treatAsAdoptPartner()) {
52236
52009
  this.pluginAPI.agent.addAccountIdParams(bodyPayload, this.pendo.get_account_id(), this.pluginAPI.ConfigReader.get('oemAccountId'));
52237
52010
  }
52238
- var body = JSON.stringify(this.pendo._.extend(bodyPayload, jwtOptions));
52011
+ const body = JSON.stringify(this.pendo._.extend(bodyPayload, jwtOptions));
52239
52012
  return this.post(url, {
52240
- body: body,
52013
+ body,
52241
52014
  headers: {
52242
52015
  'Content-Type': 'application/json'
52243
52016
  },
52244
52017
  keepalive: isUnload
52245
52018
  });
52246
- };
52247
- DevlogTransport.prototype.sendRequest = function (_a, isUnload) {
52248
- var url = _a.url, jzb = _a.jzb;
52249
- var compressedLength = jzb.length;
52019
+ }
52020
+ sendRequest({ url, jzb }, isUnload) {
52021
+ const compressedLength = jzb.length;
52250
52022
  if (compressedLength <= this.pluginAPI.constants.ENCODED_EVENT_MAX_LENGTH && !this.pluginAPI.ConfigReader.get('sendEventsWithPostOnly')) {
52251
- return this.sendRequestWithGet({ url: url, jzb: jzb });
52023
+ return this.sendRequestWithGet({ url, jzb });
52252
52024
  }
52253
- return this.sendRequestWithPost({ url: url, jzb: jzb }, isUnload);
52254
- };
52255
- return DevlogTransport;
52256
- }());
52025
+ return this.sendRequestWithPost({ url, jzb }, isUnload);
52026
+ }
52027
+ }
52257
52028
 
52258
52029
  function ConsoleCapture() {
52259
- var pluginAPI;
52260
- var _;
52261
- var globalPendo;
52262
- var buffer;
52263
- var sendQueue;
52264
- var sendInterval;
52265
- var transport;
52266
- var isPtmPaused;
52267
- var isCapturingConsoleLogs = false;
52268
- var CAPTURE_CONSOLE_CONFIG = 'captureConsoleLogs';
52269
- var CONSOLE_METHODS = ['log', 'warn', 'error', 'info'];
52270
- var DEV_LOG_SUB_TYPE = 'console';
52030
+ let pluginAPI;
52031
+ let _;
52032
+ let globalPendo;
52033
+ let buffer;
52034
+ let sendQueue;
52035
+ let sendInterval;
52036
+ let transport;
52037
+ let isPtmPaused;
52038
+ let isCapturingConsoleLogs = false;
52039
+ const CAPTURE_CONSOLE_CONFIG = 'captureConsoleLogs';
52040
+ const CONSOLE_METHODS = ['log', 'warn', 'error', 'info'];
52041
+ const DEV_LOG_SUB_TYPE = 'console';
52271
52042
  // deduplicate logs
52272
- var lastLogKey = '';
52043
+ let lastLogKey = '';
52273
52044
  return {
52274
52045
  name: 'ConsoleCapture',
52275
- initialize: initialize,
52276
- teardown: teardown,
52277
- addIntercepts: addIntercepts,
52278
- createConsoleEvent: createConsoleEvent,
52279
- captureStackTrace: captureStackTrace,
52280
- send: send,
52281
- setCaptureState: setCaptureState,
52282
- recordingStarted: recordingStarted,
52283
- recordingStopped: recordingStopped,
52284
- onAppHidden: onAppHidden,
52285
- onAppUnloaded: onAppUnloaded,
52286
- onPtmPaused: onPtmPaused,
52287
- onPtmUnpaused: onPtmUnpaused,
52288
- securityPolicyViolationFn: securityPolicyViolationFn,
52046
+ initialize,
52047
+ teardown,
52048
+ addIntercepts,
52049
+ createConsoleEvent,
52050
+ captureStackTrace,
52051
+ send,
52052
+ setCaptureState,
52053
+ recordingStarted,
52054
+ recordingStopped,
52055
+ onAppHidden,
52056
+ onAppUnloaded,
52057
+ onPtmPaused,
52058
+ onPtmUnpaused,
52059
+ securityPolicyViolationFn,
52289
52060
  get isCapturingConsoleLogs() {
52290
52061
  return isCapturingConsoleLogs;
52291
52062
  },
@@ -52302,16 +52073,16 @@ function ConsoleCapture() {
52302
52073
  function initialize(pendo, PluginAPI) {
52303
52074
  _ = pendo._;
52304
52075
  pluginAPI = PluginAPI;
52305
- var ConfigReader = pluginAPI.ConfigReader;
52076
+ const { ConfigReader } = pluginAPI;
52306
52077
  ConfigReader.addOption(CAPTURE_CONSOLE_CONFIG, [ConfigReader.sources.PENDO_CONFIG_SRC], false);
52307
- var captureConsoleEnabled = ConfigReader.get(CAPTURE_CONSOLE_CONFIG);
52078
+ const captureConsoleEnabled = ConfigReader.get(CAPTURE_CONSOLE_CONFIG);
52308
52079
  if (!captureConsoleEnabled)
52309
52080
  return;
52310
52081
  globalPendo = pendo;
52311
52082
  buffer = new DevlogBuffer(pendo, pluginAPI);
52312
52083
  transport = new DevlogTransport(pendo, pluginAPI);
52313
52084
  sendQueue = new pluginAPI.SendQueue(transport.sendRequest.bind(transport));
52314
- sendInterval = setInterval(function () {
52085
+ sendInterval = setInterval(() => {
52315
52086
  if (!sendQueue.failed()) {
52316
52087
  send();
52317
52088
  }
@@ -52337,19 +52108,17 @@ function ConsoleCapture() {
52337
52108
  function onPtmUnpaused() {
52338
52109
  isPtmPaused = false;
52339
52110
  if (!buffer.isEmpty()) {
52340
- for (var _i = 0, _a = buffer.events; _i < _a.length; _i++) {
52341
- var event_1 = _a[_i];
52342
- pluginAPI.Events.eventCaptured.trigger(event_1);
52111
+ for (const event of buffer.events) {
52112
+ pluginAPI.Events.eventCaptured.trigger(event);
52343
52113
  }
52344
52114
  send();
52345
52115
  }
52346
52116
  }
52347
- function setCaptureState(_a) {
52348
- var _b = _a === void 0 ? {} : _a, _c = _b.shouldCapture, shouldCapture = _c === void 0 ? false : _c, _d = _b.reason, reason = _d === void 0 ? '' : _d;
52117
+ function setCaptureState({ shouldCapture = false, reason = '' } = {}) {
52349
52118
  if (shouldCapture === isCapturingConsoleLogs)
52350
52119
  return;
52351
52120
  isCapturingConsoleLogs = shouldCapture;
52352
- pluginAPI.log.info("[ConsoleCapture] Console log capture ".concat(shouldCapture ? 'started' : 'stopped').concat(reason ? ": ".concat(reason) : ''));
52121
+ pluginAPI.log.info(`[ConsoleCapture] Console log capture ${shouldCapture ? 'started' : 'stopped'}${reason ? `: ${reason}` : ''}`);
52353
52122
  }
52354
52123
  function recordingStarted() {
52355
52124
  setCaptureState({ shouldCapture: true, reason: 'recording started' });
@@ -52369,12 +52138,12 @@ function ConsoleCapture() {
52369
52138
  }
52370
52139
  function addIntercepts() {
52371
52140
  _.each(CONSOLE_METHODS, function (methodName) {
52372
- var originalMethod = console[methodName];
52141
+ const originalMethod = console[methodName];
52373
52142
  if (!originalMethod)
52374
52143
  return;
52375
52144
  console[methodName] = _.wrap(originalMethod, function (originalFn) {
52376
52145
  // slice 1 to omit originalFn
52377
- var args = _.toArray(arguments).slice(1);
52146
+ const args = _.toArray(arguments).slice(1);
52378
52147
  originalFn.apply(console, args);
52379
52148
  createConsoleEvent(args, methodName);
52380
52149
  });
@@ -52386,10 +52155,10 @@ function ConsoleCapture() {
52386
52155
  function securityPolicyViolationFn(evt) {
52387
52156
  if (!evt || typeof evt !== 'object')
52388
52157
  return;
52389
- var blockedURI = evt.blockedURI, violatedDirective = evt.violatedDirective, effectiveDirective = evt.effectiveDirective, disposition = evt.disposition, originalPolicy = evt.originalPolicy;
52390
- var directive = violatedDirective || effectiveDirective;
52391
- var isReportOnly = disposition === 'report';
52392
- var message = createCspViolationMessage(blockedURI, directive, isReportOnly, originalPolicy);
52158
+ const { blockedURI, violatedDirective, effectiveDirective, disposition, originalPolicy } = evt;
52159
+ const directive = violatedDirective || effectiveDirective;
52160
+ const isReportOnly = disposition === 'report';
52161
+ const message = createCspViolationMessage(blockedURI, directive, isReportOnly, originalPolicy);
52393
52162
  if (isReportOnly) {
52394
52163
  createConsoleEvent([message], 'warn', { skipStackTrace: true, skipScrubPII: true });
52395
52164
  }
@@ -52397,13 +52166,12 @@ function ConsoleCapture() {
52397
52166
  createConsoleEvent([message], 'error', { skipStackTrace: true, skipScrubPII: true });
52398
52167
  }
52399
52168
  }
52400
- function createConsoleEvent(args, methodName, _a) {
52401
- var _b = _a === void 0 ? {} : _a, _c = _b.skipStackTrace, skipStackTrace = _c === void 0 ? false : _c, _d = _b.skipScrubPII, skipScrubPII = _d === void 0 ? false : _d;
52169
+ function createConsoleEvent(args, methodName, { skipStackTrace = false, skipScrubPII = false } = {}) {
52402
52170
  if (!isCapturingConsoleLogs || !args || args.length === 0 || !_.contains(CONSOLE_METHODS, methodName))
52403
52171
  return;
52404
52172
  // stringify args
52405
- var message = _.compact(_.map(args, function (arg) {
52406
- var stringifiedArg;
52173
+ let message = _.compact(_.map(args, arg => {
52174
+ let stringifiedArg;
52407
52175
  try {
52408
52176
  stringifiedArg = stringify(arg);
52409
52177
  }
@@ -52415,22 +52183,22 @@ function ConsoleCapture() {
52415
52183
  if (!message)
52416
52184
  return;
52417
52185
  // capture stack trace
52418
- var stackTrace = '';
52186
+ let stackTrace = '';
52419
52187
  if (!skipStackTrace) {
52420
- var maxStackFrames = methodName === 'error' ? 4 : 1;
52188
+ const maxStackFrames = methodName === 'error' ? 4 : 1;
52421
52189
  stackTrace = captureStackTrace(maxStackFrames);
52422
52190
  }
52423
52191
  // truncate message and stack trace
52424
52192
  message = truncate(message);
52425
52193
  stackTrace = truncate(stackTrace);
52426
52194
  // de-duplicate log
52427
- var logKey = generateLogKey(methodName, message, stackTrace);
52195
+ const logKey = generateLogKey(methodName, message, stackTrace);
52428
52196
  if (isExistingDuplicateLog(logKey)) {
52429
52197
  buffer.lastEvent.devLogCount++;
52430
52198
  return;
52431
52199
  }
52432
- var devLogEnvelope = createDevLogEnvelope(pluginAPI, globalPendo);
52433
- var consoleEvent = __assign(__assign({}, devLogEnvelope), { subType: DEV_LOG_SUB_TYPE, devLogLevel: methodName === 'log' ? 'info' : methodName, devLogMessage: skipScrubPII ? message : scrubPII({ string: message, _: _ }), devLogTrace: stackTrace, devLogCount: 1 });
52200
+ const devLogEnvelope = createDevLogEnvelope(pluginAPI, globalPendo);
52201
+ const consoleEvent = Object.assign(Object.assign({}, devLogEnvelope), { subType: DEV_LOG_SUB_TYPE, devLogLevel: methodName === 'log' ? 'info' : methodName, devLogMessage: skipScrubPII ? message : scrubPII({ string: message, _ }), devLogTrace: stackTrace, devLogCount: 1 });
52434
52202
  if (!buffer.hasTokenAvailable())
52435
52203
  return consoleEvent;
52436
52204
  if (!isPtmPaused) {
@@ -52442,8 +52210,8 @@ function ConsoleCapture() {
52442
52210
  }
52443
52211
  function captureStackTrace(maxStackFrames) {
52444
52212
  try {
52445
- var stackFrames = ErrorStackParser.parse(new Error(), maxStackFrames);
52446
- return _.map(stackFrames, function (frame) { return frame.toString(); }).join('\n');
52213
+ const stackFrames = ErrorStackParser.parse(new Error(), maxStackFrames);
52214
+ return _.map(stackFrames, frame => frame.toString()).join('\n');
52447
52215
  }
52448
52216
  catch (error) {
52449
52217
  return '';
@@ -52455,22 +52223,21 @@ function ConsoleCapture() {
52455
52223
  function updateLastLog(logKey) {
52456
52224
  lastLogKey = logKey;
52457
52225
  }
52458
- function send(_a) {
52459
- var _b = _a === void 0 ? {} : _a, _c = _b.unload, unload = _c === void 0 ? false : _c, _d = _b.hidden, hidden = _d === void 0 ? false : _d;
52226
+ function send({ unload = false, hidden = false } = {}) {
52460
52227
  if (!buffer || buffer.isEmpty())
52461
52228
  return;
52462
52229
  if (!globalPendo.isSendingEvents()) {
52463
52230
  buffer.clear();
52464
52231
  return;
52465
52232
  }
52466
- var payloads = buffer.pack();
52233
+ const payloads = buffer.pack();
52467
52234
  if (!payloads || payloads.length === 0)
52468
52235
  return;
52469
52236
  if (unload || hidden) {
52470
52237
  sendQueue.drain(payloads, unload);
52471
52238
  }
52472
52239
  else {
52473
- sendQueue.push.apply(sendQueue, payloads);
52240
+ sendQueue.push(...payloads);
52474
52241
  }
52475
52242
  }
52476
52243
  function teardown() {
@@ -52494,7 +52261,7 @@ function ConsoleCapture() {
52494
52261
  _.each(CONSOLE_METHODS, function (methodName) {
52495
52262
  if (!console[methodName])
52496
52263
  return _.noop;
52497
- var unwrap = console[methodName]._pendoUnwrap;
52264
+ const unwrap = console[methodName]._pendoUnwrap;
52498
52265
  if (_.isFunction(unwrap)) {
52499
52266
  unwrap();
52500
52267
  }
@@ -53285,4 +53052,500 @@ const PredictGuides = () => {
53285
53052
  };
53286
53053
  };
53287
53054
 
53288
- export { ConsoleCapture, Feedback, GuideMarkdown, NetworkCapture, PredictGuides, createReplayPlugin as Replay, TextCapture, VocPortal, loadAgent };
53055
+ const ASSISTANT_MESSAGE = 'assistantMessage';
53056
+ const CONVERSATION_ID_URL_PATTERN = 'conversationIdUrlPattern';
53057
+ const MESSAGE_ID_ATTR = 'messageIdAttr';
53058
+ const MODEL_USED_ATTR = 'modelUsedAttr';
53059
+ const REACTION_ACTIVE = 'reactionActive';
53060
+ const STREAMING_ACTIVE = 'streamingActive';
53061
+ const STREAMING_ACTIVE_ATTR = 'streamingActiveAttr';
53062
+ const THUMB_DOWN = 'thumbDown';
53063
+ const THUMB_UP = 'thumbUp';
53064
+ const TURN_CONTAINER = 'turnContainer';
53065
+ const TURN_ATTR = 'turnAttr';
53066
+ const USER_MESSAGE = 'userMessage';
53067
+ const CUSTOM_AGENT_ID_URL_PATTERN = 'customAgentIdUrlPattern';
53068
+ const CUSTOM_AGENT_NAME = 'customAgentName';
53069
+ const REQUIRED_SELECTORS = [
53070
+ ASSISTANT_MESSAGE,
53071
+ CONVERSATION_ID_URL_PATTERN,
53072
+ MESSAGE_ID_ATTR,
53073
+ STREAMING_ACTIVE,
53074
+ TURN_CONTAINER,
53075
+ TURN_ATTR,
53076
+ USER_MESSAGE
53077
+ ];
53078
+ const STREAMING_END_SETTLE_MS = 500;
53079
+ const SUBMISSION_START_RETRY_MS = 1000;
53080
+ const SUBMISSION_START_MAX_ATTEMPTS = 4;
53081
+ class DOMConversation {
53082
+ // Returns the list of required selector types that are missing or empty
53083
+ // in the given cssSelectors config. An empty array means the config is
53084
+ // valid for instantiation.
53085
+ static validateConfig(cssSelectors) {
53086
+ if (!Array.isArray(cssSelectors)) {
53087
+ return REQUIRED_SELECTORS.slice();
53088
+ }
53089
+ const present = new Set();
53090
+ for (const cfg of cssSelectors) {
53091
+ if (!cfg || !cfg.type || !cfg.cssSelector)
53092
+ continue;
53093
+ if (cfg.type === CONVERSATION_ID_URL_PATTERN) {
53094
+ try {
53095
+ RegExp(cfg.cssSelector);
53096
+ }
53097
+ catch (e) {
53098
+ continue;
53099
+ }
53100
+ }
53101
+ present.add(cfg.type);
53102
+ }
53103
+ return REQUIRED_SELECTORS.filter((r) => !present.has(r));
53104
+ }
53105
+ static supportedPreset(preset) {
53106
+ return preset === 'chatgpt-full';
53107
+ }
53108
+ constructor(pendo, PluginAPI, id, privacyFilters, cssSelectors) {
53109
+ this.selectors = {};
53110
+ this.listeners = [];
53111
+ this.isActive = true;
53112
+ this.observers = [];
53113
+ this.wasStreaming = false;
53114
+ this.streamingEndTimer = null;
53115
+ this.submissionStartRetryTimer = null;
53116
+ this.requestNode = null;
53117
+ this.conversationIdRegex = null;
53118
+ this.customAgentIdRegex = null;
53119
+ this.lastReturnedMessageId = null;
53120
+ this.dom = pendo.dom;
53121
+ this._ = pendo._;
53122
+ this.api = PluginAPI;
53123
+ this.Sizzle = pendo.Sizzle;
53124
+ this.id = id;
53125
+ this.setFilters(privacyFilters);
53126
+ if (!this._.isArray(cssSelectors)) {
53127
+ this.api.log.error(`cssSelectors must be an array, received: ${typeof cssSelectors}`);
53128
+ cssSelectors = [];
53129
+ }
53130
+ this._.each(cssSelectors, (cfg) => {
53131
+ if (cfg && cfg.type) {
53132
+ this.selectors[cfg.type] = cfg.cssSelector;
53133
+ }
53134
+ });
53135
+ this.conversationIdRegex = new RegExp(this.selectors[CONVERSATION_ID_URL_PATTERN]);
53136
+ const customAgentIdUrlPattern = this.selectors[CUSTOM_AGENT_ID_URL_PATTERN];
53137
+ if (customAgentIdUrlPattern) { // this is optional
53138
+ try {
53139
+ this.customAgentIdRegex = new RegExp(customAgentIdUrlPattern);
53140
+ }
53141
+ catch (error) {
53142
+ this.api.log.error(`bad customAgentIdUrlPattern ${customAgentIdUrlPattern}`, { error });
53143
+ }
53144
+ }
53145
+ this.root = document.body;
53146
+ this.setupReactionListener();
53147
+ this.setupStreamingObserver();
53148
+ }
53149
+ setupReactionListener() {
53150
+ if (!this.findSelector(THUMB_UP) && !this.findSelector(THUMB_DOWN))
53151
+ return;
53152
+ this.reactionClickHandler = this.handleReactionClick.bind(this);
53153
+ this.root.addEventListener('click', this.reactionClickHandler, true);
53154
+ }
53155
+ handleReactionClick(evt) {
53156
+ const target = evt.target;
53157
+ if (!target || target.nodeType !== 1)
53158
+ return;
53159
+ const upSelector = this.findSelector(THUMB_UP);
53160
+ const downSelector = this.findSelector(THUMB_DOWN);
53161
+ const thumb = this.dom(target).closest(`${upSelector}, ${downSelector}`);
53162
+ if (!thumb.length)
53163
+ return;
53164
+ const isUp = this.Sizzle.matchesSelector(thumb[0], upSelector);
53165
+ const activeSelector = this.findSelector(REACTION_ACTIVE);
53166
+ const wasPressed = activeSelector && this.Sizzle.matchesSelector(thumb[0], activeSelector);
53167
+ const direction = isUp ? 'positive' : 'negative';
53168
+ const content = wasPressed ? 'unreact' : direction;
53169
+ const assistantNode = thumb.closest(this.findSelector(TURN_CONTAINER))
53170
+ .find(this.findSelector(ASSISTANT_MESSAGE));
53171
+ this.emit('user_reaction', {
53172
+ agentId: this.id,
53173
+ messageId: this.getMessageId(assistantNode),
53174
+ content,
53175
+ privacyFilterApplied: false
53176
+ });
53177
+ }
53178
+ // observe the streaming indicator
53179
+ setupStreamingObserver() {
53180
+ this.wasStreaming = this.select(STREAMING_ACTIVE).length > 0;
53181
+ this.stopStreamingEndTimer();
53182
+ const MutationObserver = getZoneSafeMethod(this._, 'MutationObserver');
53183
+ const observer = new MutationObserver(this.handleMutation.bind(this));
53184
+ const attrName = this.findSelector(STREAMING_ACTIVE_ATTR);
53185
+ observer.observe(this.root, {
53186
+ childList: true,
53187
+ subtree: true,
53188
+ attributes: true,
53189
+ attributeFilter: attrName ? [attrName] : undefined
53190
+ });
53191
+ this.observers.push(observer);
53192
+ }
53193
+ // look for changes in the state of the streaming indicator.
53194
+ // streaming started -> a prompt has been submitted
53195
+ // streaming ended -> got a response
53196
+ // we don't send the prompt immediately when it's submitted because it might not have a
53197
+ // conversation id yet.
53198
+ // we don't send the agent_response immediately when the streaming indicator is cleared
53199
+ // because it clears slightly before the final text chunk is committed to the DOM so the
53200
+ // end-handling is deferred by a short settle window
53201
+ handleMutation() {
53202
+ const isStreaming = this.select(STREAMING_ACTIVE).length > 0;
53203
+ if (isStreaming === this.wasStreaming)
53204
+ return;
53205
+ if (isStreaming) { // started streaming
53206
+ if (!this.streamingEndTimer) {
53207
+ this.onSubmissionStart();
53208
+ }
53209
+ else {
53210
+ // stream restarted during the settle window (multi-phase response).
53211
+ // treat as a continuation of the prior request, not a new submission.
53212
+ // we'll handle it next time streaming stops
53213
+ this.stopStreamingEndTimer();
53214
+ }
53215
+ }
53216
+ else { // finished streaming
53217
+ this.startStreamingEndTimer();
53218
+ }
53219
+ this.wasStreaming = isStreaming;
53220
+ }
53221
+ onSubmissionStart(attempt = 1) {
53222
+ this.requestNode = this.findLastRequestNode();
53223
+ if (this.requestNode) {
53224
+ this.handleUserMessage(this.requestNode);
53225
+ return;
53226
+ }
53227
+ // URL hasn't flipped yet to include the conversation id on a fresh chat
53228
+ // retry, if that still fails, onSubmissionEnd handles it
53229
+ if (attempt < SUBMISSION_START_MAX_ATTEMPTS) {
53230
+ this.startSubmissionStartRetryTimer(attempt + 1);
53231
+ }
53232
+ }
53233
+ onSubmissionEnd() {
53234
+ this.stopSubmissionStartRetryTimer();
53235
+ let requestNode = this.requestNode;
53236
+ this.requestNode = null;
53237
+ if (!requestNode) {
53238
+ // onSubmissionStart didn't send, send it now
53239
+ requestNode = this.findLastRequestNode();
53240
+ if (!requestNode)
53241
+ return;
53242
+ this.handleUserMessage(requestNode);
53243
+ }
53244
+ const requestTurn = this.findTurnNumber(requestNode);
53245
+ if (requestTurn === null)
53246
+ return;
53247
+ const assistantNodes = this.select(ASSISTANT_MESSAGE);
53248
+ const toEmit = [];
53249
+ for (let i = assistantNodes.length - 1; i >= 0; i--) {
53250
+ const n = this.findTurnNumber(this.dom(assistantNodes[i]));
53251
+ if (n === null)
53252
+ continue;
53253
+ if (n <= requestTurn)
53254
+ break;
53255
+ toEmit.push(assistantNodes[i]);
53256
+ }
53257
+ // emit in chronological order (reverse of collection order)
53258
+ for (let i = toEmit.length - 1; i >= 0; i--) {
53259
+ this.handleAssistantMessage(this.dom(toEmit[i]));
53260
+ }
53261
+ }
53262
+ extractContent(node) {
53263
+ const rawContent = node.text().trim();
53264
+ const content = this.applyPrivacyFilter(rawContent);
53265
+ return { content, privacyFilterApplied: content !== rawContent };
53266
+ }
53267
+ getMessageId(node) {
53268
+ return node.attr(this.findSelector(MESSAGE_ID_ATTR));
53269
+ }
53270
+ handleUserMessage(node) {
53271
+ this.emit('prompt', Object.assign({ agentId: this.id, messageId: this.getMessageId(node) }, this.extractContent(node)));
53272
+ }
53273
+ handleAssistantMessage(node) {
53274
+ const modelUsedAttr = this.findSelector(MODEL_USED_ATTR);
53275
+ const modelUsed = modelUsedAttr && node.attr(modelUsedAttr);
53276
+ this.emit('agent_response', Object.assign({ agentId: this.id, messageId: this.getMessageId(node), agentModelsUsed: modelUsed ? [modelUsed] : [] }, this.extractContent(node)));
53277
+ }
53278
+ findLastRequestNode() {
53279
+ if (!this.getConversationId())
53280
+ return null;
53281
+ const node = this._.last(this.select(USER_MESSAGE));
53282
+ if (!node)
53283
+ return null;
53284
+ const $node = this.dom(node);
53285
+ const messageId = this.getMessageId($node);
53286
+ if (!messageId)
53287
+ return null;
53288
+ if (messageId === this.lastReturnedMessageId)
53289
+ return null;
53290
+ this.lastReturnedMessageId = messageId;
53291
+ return $node;
53292
+ }
53293
+ findTurnNumber(node) {
53294
+ const turnSelector = this.findSelector(TURN_CONTAINER);
53295
+ const turnAttr = this.findSelector(TURN_ATTR);
53296
+ const turn = node.closest(turnSelector).attr(turnAttr);
53297
+ if (!turn)
53298
+ return null;
53299
+ const seqMatch = String(turn).match(/\d+/);
53300
+ return seqMatch ? parseInt(seqMatch[0], 10) : null;
53301
+ }
53302
+ findSelector(type) {
53303
+ return this.selectors[type];
53304
+ }
53305
+ select(type) {
53306
+ return this.dom(this.findSelector(type), this.root);
53307
+ }
53308
+ getConversationId() {
53309
+ const m = location.href.match(this.conversationIdRegex);
53310
+ if (!m)
53311
+ return null;
53312
+ return m[1] !== undefined ? m[1] : m[0];
53313
+ }
53314
+ getCustomAgentId() {
53315
+ if (!this.customAgentIdRegex)
53316
+ return undefined;
53317
+ const m = location.href.match(this.customAgentIdRegex);
53318
+ if (!m)
53319
+ return undefined;
53320
+ return m[1] !== undefined ? m[1] : m[0];
53321
+ }
53322
+ getCustomAgentName() {
53323
+ if (!this.findSelector(CUSTOM_AGENT_NAME))
53324
+ return '';
53325
+ const node = this.select(CUSTOM_AGENT_NAME);
53326
+ if (!node.length)
53327
+ return '';
53328
+ return node.text().trim();
53329
+ }
53330
+ addCustomAgentInfo(eventPayload) {
53331
+ const customAgentId = this.getCustomAgentId();
53332
+ if (!customAgentId)
53333
+ return;
53334
+ eventPayload.customAgentId = customAgentId;
53335
+ const customAgentName = this.getCustomAgentName();
53336
+ if (customAgentName) {
53337
+ eventPayload.customAgentName = customAgentName;
53338
+ }
53339
+ }
53340
+ setFilters(candidateFilter) {
53341
+ if (!candidateFilter) {
53342
+ this.privacyFilters = null;
53343
+ return null;
53344
+ }
53345
+ try {
53346
+ this.privacyFilters = new RegExp(candidateFilter, 'gmi');
53347
+ }
53348
+ catch (e) {
53349
+ this.privacyFilters = null;
53350
+ this.api.log.error(e);
53351
+ }
53352
+ return this.privacyFilters;
53353
+ }
53354
+ applyPrivacyFilter(candidateValue, filters = null) {
53355
+ const filtersToUse = filters || this.privacyFilters;
53356
+ if (!filtersToUse || !this._.isRegExp(filtersToUse))
53357
+ return candidateValue;
53358
+ return candidateValue.replace(filtersToUse, 'redacted');
53359
+ }
53360
+ onSubmit(callback) {
53361
+ this.listeners.push(callback);
53362
+ }
53363
+ emit(eventType, eventPayload) {
53364
+ eventPayload.conversationId = this.getConversationId();
53365
+ this.addCustomAgentInfo(eventPayload);
53366
+ this._.each(this.listeners, (cb) => cb(eventType, eventPayload));
53367
+ }
53368
+ startStreamingEndTimer() {
53369
+ this.stopStreamingEndTimer();
53370
+ this.streamingEndTimer = setTimeout$1(() => {
53371
+ this.streamingEndTimer = null;
53372
+ this.onSubmissionEnd();
53373
+ }, STREAMING_END_SETTLE_MS);
53374
+ }
53375
+ stopStreamingEndTimer() {
53376
+ if (!this.streamingEndTimer)
53377
+ return;
53378
+ clearTimeout(this.streamingEndTimer);
53379
+ this.streamingEndTimer = null;
53380
+ }
53381
+ startSubmissionStartRetryTimer(attempt) {
53382
+ this.stopSubmissionStartRetryTimer();
53383
+ this.submissionStartRetryTimer = setTimeout$1(() => {
53384
+ this.submissionStartRetryTimer = null;
53385
+ this.onSubmissionStart(attempt);
53386
+ }, SUBMISSION_START_RETRY_MS);
53387
+ }
53388
+ stopSubmissionStartRetryTimer() {
53389
+ if (!this.submissionStartRetryTimer)
53390
+ return;
53391
+ clearTimeout(this.submissionStartRetryTimer);
53392
+ this.submissionStartRetryTimer = null;
53393
+ }
53394
+ suspend() {
53395
+ this.isActive = false;
53396
+ }
53397
+ resume() {
53398
+ this.isActive = true;
53399
+ }
53400
+ teardown() {
53401
+ this._.each(this.observers, (o) => o && o.disconnect && o.disconnect());
53402
+ this.observers = [];
53403
+ if (this.reactionClickHandler && this.root) {
53404
+ this.root.removeEventListener('click', this.reactionClickHandler, true);
53405
+ this.reactionClickHandler = null;
53406
+ }
53407
+ this.stopStreamingEndTimer();
53408
+ this.stopSubmissionStartRetryTimer();
53409
+ this.listeners = [];
53410
+ }
53411
+ }
53412
+
53413
+ /*
53414
+ * Conversation Analytics Plugin
53415
+ *
53416
+ * Independent plugin that tracks AI-agent conversations rendered in the DOM.
53417
+ *
53418
+ * The sibling built-in PromptAnalytics plugin owns the network + DOMPrompt AI-agents
53419
+ */
53420
+ function ConversationAnalytics() {
53421
+ let pendo;
53422
+ let api;
53423
+ let _;
53424
+ let log;
53425
+ let conversations = [];
53426
+ let agentsCache = new Map();
53427
+ const CONFIG_NAME = 'aiAgents';
53428
+ return {
53429
+ name: 'ConversationAnalytics',
53430
+ initialize,
53431
+ teardown,
53432
+ onConfigLoaded,
53433
+ observeConversation,
53434
+ sendConversationEvent,
53435
+ reEvaluatePageRules
53436
+ };
53437
+ function initialize(pendoGlobal, PluginAPI) {
53438
+ var _a;
53439
+ pendo = pendoGlobal;
53440
+ api = PluginAPI;
53441
+ _ = pendo._;
53442
+ log = api.log;
53443
+ const { ConfigReader } = api;
53444
+ ConfigReader.addOption(CONFIG_NAME, [
53445
+ ConfigReader.sources.PENDO_CONFIG_SRC,
53446
+ ConfigReader.sources.SNIPPET_SRC
53447
+ ]);
53448
+ onConfigLoaded(ConfigReader.get(CONFIG_NAME));
53449
+ // Listen for URL changes to re-evaluate page rules
53450
+ // Listening on guidesLoaded since normalizedUrl comes back from the guides playload
53451
+ (_a = api.Events.guidesLoaded) === null || _a === void 0 ? void 0 : _a.on(reEvaluatePageRules);
53452
+ }
53453
+ // Test if the current URL matches the page rule for an agent. The raw matcher lives in core
53454
+ // and is reached through PluginAPI (independent plugins cannot import it directly); it falls
53455
+ // back to the normalized URL internally when no URL is passed.
53456
+ function testPageRule(pageRule, agentId = 'unknown') {
53457
+ // Convert //*/agent pattern to work with full URLs
53458
+ let fixedPageRule = pageRule;
53459
+ if (Array.isArray(pageRule)) {
53460
+ const validRules = _.filter(pageRule, rule => rule && rule.trim() !== '');
53461
+ fixedPageRule = _.map(validRules, rule => rule.startsWith('//*/') ? rule.substring(1) : rule);
53462
+ }
53463
+ else if (typeof pageRule === 'string' && pageRule.startsWith('//*/')) {
53464
+ fixedPageRule = pageRule.substring(1);
53465
+ }
53466
+ return api.util.testPageRule(fixedPageRule, undefined, {
53467
+ logger: log,
53468
+ context: 'agent',
53469
+ id: agentId
53470
+ });
53471
+ }
53472
+ function reEvaluatePageRules() {
53473
+ _.each(conversations, conversation => {
53474
+ const agent = findAgentById(conversation.id);
53475
+ const shouldBeActive = agent && testPageRule(agent.pageRule, agent.id);
53476
+ if (shouldBeActive) {
53477
+ conversation.resume();
53478
+ }
53479
+ else {
53480
+ conversation.suspend();
53481
+ }
53482
+ });
53483
+ const currentlyActiveIds = _.map(_.filter(conversations, conversation => conversation.isActive), conversation => conversation.id);
53484
+ const allAgents = api.ConfigReader.get(CONFIG_NAME) || [];
53485
+ _.each(allAgents, aiAgent => {
53486
+ if (!isConversationAgent(aiAgent)) {
53487
+ return;
53488
+ }
53489
+ const isCurrentlyActive = _.contains(currentlyActiveIds, aiAgent.id);
53490
+ const shouldBeActive = testPageRule(aiAgent.pageRule, aiAgent.id);
53491
+ if (shouldBeActive && !isCurrentlyActive) {
53492
+ observeConversation(aiAgent);
53493
+ }
53494
+ });
53495
+ }
53496
+ function findAgentById(agentId) {
53497
+ return agentsCache.get(agentId);
53498
+ }
53499
+ // Only conversation agents belong to this plugin; the rest are owned
53500
+ // by the built-in PromptAnalytics plugin.
53501
+ function isConversationAgent(agent) {
53502
+ return DOMConversation.supportedPreset(agent.preset);
53503
+ }
53504
+ function onConfigLoaded(aiAgents = []) {
53505
+ if (!aiAgents || !_.isArray(aiAgents) || aiAgents.length === 0) {
53506
+ return;
53507
+ }
53508
+ agentsCache.clear();
53509
+ _.each(aiAgents, aiAgent => {
53510
+ if (!isConversationAgent(aiAgent)) {
53511
+ return;
53512
+ }
53513
+ agentsCache.set(aiAgent.id, aiAgent);
53514
+ if (testPageRule(aiAgent.pageRule, aiAgent.id)) {
53515
+ observeConversation(aiAgent);
53516
+ }
53517
+ });
53518
+ }
53519
+ function observeConversation(config) {
53520
+ const { id, cssSelectors, privacyFilters } = config;
53521
+ // Check if this agent is already being tracked
53522
+ const existing = _.find(conversations, conversation => conversation.id === id);
53523
+ if (existing) {
53524
+ return;
53525
+ }
53526
+ const missing = DOMConversation.validateConfig(cssSelectors);
53527
+ if (missing.length) {
53528
+ log.error('aiAgent config missing required selectors', { agentId: id, missing });
53529
+ return;
53530
+ }
53531
+ const conversation = new DOMConversation(pendo, api, id, privacyFilters, cssSelectors);
53532
+ conversation.onSubmit(sendConversationEvent);
53533
+ conversations.push(conversation);
53534
+ }
53535
+ function sendConversationEvent(eventType, eventPayload) {
53536
+ // Block event if the conversation is suspended
53537
+ const conversation = _.find(conversations, c => c.id === eventPayload.agentId);
53538
+ if (conversation && !conversation.isActive) {
53539
+ return;
53540
+ }
53541
+ eventPayload = _.extend({ agentType: 'conversation' }, eventPayload);
53542
+ api.analytics.collectEvent(eventType, eventPayload, undefined, 'agentic');
53543
+ }
53544
+ function teardown() {
53545
+ _.each(conversations, conversation => conversation.teardown());
53546
+ conversations = [];
53547
+ agentsCache.clear();
53548
+ }
53549
+ }
53550
+
53551
+ export { ConsoleCapture, ConversationAnalytics, Feedback, GuideMarkdown, NetworkCapture, PredictGuides, createReplayPlugin as Replay, TextCapture, VocPortal, loadAgent };