@guidelytech/shared 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -21,9 +21,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  ADVANCE_ON: () => ADVANCE_ON,
24
+ AGENT_METADATA_MAX_BYTES: () => AGENT_METADATA_MAX_BYTES,
25
+ AGENT_METADATA_MAX_KEYS: () => AGENT_METADATA_MAX_KEYS,
26
+ AGENT_OUTCOMES: () => AGENT_OUTCOMES,
27
+ AGENT_TOOL_CALLS_PER_TURN: () => AGENT_TOOL_CALLS_PER_TURN,
28
+ AGENT_TOOL_STATUSES: () => AGENT_TOOL_STATUSES,
29
+ AGENT_TURNS_PER_BATCH: () => AGENT_TURNS_PER_BATCH,
30
+ AGENT_TURN_MAX_TEXT: () => AGENT_TURN_MAX_TEXT,
31
+ AGENT_TURN_ROLES: () => AGENT_TURN_ROLES,
24
32
  ANNOTATION_COLORS: () => ANNOTATION_COLORS,
33
+ APP_LIFECYCLE_EVENTS: () => APP_LIFECYCLE_EVENTS,
25
34
  ARTICLE_VISIBILITIES: () => ARTICLE_VISIBILITIES,
26
35
  AUTOCAPTURE_EVENTS: () => AUTOCAPTURE_EVENTS,
36
+ AgentEventsRequestSchema: () => AgentEventsRequestSchema,
37
+ AgentMetadataSchema: () => AgentMetadataSchema,
38
+ AgentToolCallSchema: () => AgentToolCallSchema,
39
+ AgentTurnInputSchema: () => AgentTurnInputSchema,
27
40
  AppearanceSchema: () => AppearanceSchema,
28
41
  AuthoringPickSchema: () => AuthoringPickSchema,
29
42
  AutocaptureSettingsSchema: () => AutocaptureSettingsSchema,
@@ -31,9 +44,11 @@ __export(index_exports, {
31
44
  ButtonSchema: () => ButtonSchema,
32
45
  CAPTURE_PARAM: () => CAPTURE_PARAM,
33
46
  CAPTURE_SCREENSHOT_MAX_BYTES: () => CAPTURE_SCREENSHOT_MAX_BYTES,
47
+ COMMON_LOCALES: () => COMMON_LOCALES,
34
48
  COMPLAINT_EVENTS: () => COMPLAINT_EVENTS,
35
49
  COMPLAINT_FIELD_TYPES: () => COMPLAINT_FIELD_TYPES,
36
50
  COMPLAINT_STATUSES: () => COMPLAINT_STATUSES,
51
+ CONTROL_VARIANT_ID: () => CONTROL_VARIANT_ID,
37
52
  CaptureStepSchema: () => CaptureStepSchema,
38
53
  CapturedElementSchema: () => CapturedElementSchema,
39
54
  ChecklistConfigSchema: () => ChecklistConfigSchema,
@@ -42,28 +57,54 @@ __export(index_exports, {
42
57
  ConversationLookupSchema: () => ConversationLookupSchema,
43
58
  ConversationRatingSchema: () => ConversationRatingSchema,
44
59
  DEFAULT_CAPTURE_SETTINGS: () => DEFAULT_CAPTURE_SETTINGS,
60
+ DEFAULT_FEATURE_ATTRIBUTE: () => DEFAULT_FEATURE_ATTRIBUTE,
61
+ DEFAULT_LOCALE: () => DEFAULT_LOCALE,
45
62
  DEFAULT_PLATFORMS: () => DEFAULT_PLATFORMS,
46
63
  EMBED_IFRAME_ATTRS: () => EMBED_IFRAME_ATTRS,
47
64
  EVENT_NAMES: () => EVENT_NAMES,
48
65
  ErrorTrackingSettingsSchema: () => ErrorTrackingSettingsSchema,
49
66
  EventBatchSchema: () => EventBatchSchema,
67
+ FEATURE_ATTRIBUTE_PATTERN: () => FEATURE_ATTRIBUTE_PATTERN,
68
+ FEATURE_RULE_LIMITS: () => FEATURE_RULE_LIMITS,
69
+ FEEDBACK_EVENTS: () => FEEDBACK_EVENTS,
70
+ FEEDBACK_PRIORITIES: () => FEEDBACK_PRIORITIES,
71
+ FEEDBACK_PRIORITY_LABEL: () => FEEDBACK_PRIORITY_LABEL,
72
+ FEEDBACK_PRIORITY_WEIGHT: () => FEEDBACK_PRIORITY_WEIGHT,
73
+ FEEDBACK_STATUSES: () => FEEDBACK_STATUSES,
74
+ FEEDBACK_STATUS_LABEL: () => FEEDBACK_STATUS_LABEL,
50
75
  FILE_LINK_CLASS: () => FILE_LINK_CLASS,
76
+ FeedbackCommentSchema: () => FeedbackCommentSchema,
77
+ FeedbackFollowSchema: () => FeedbackFollowSchema,
78
+ FeedbackListRequestSchema: () => FeedbackListRequestSchema,
79
+ FeedbackSimilarSchema: () => FeedbackSimilarSchema,
80
+ FeedbackUpdatesReadSchema: () => FeedbackUpdatesReadSchema,
81
+ FeedbackVisitorSchema: () => FeedbackVisitorSchema,
82
+ FeedbackVoteSchema: () => FeedbackVoteSchema,
51
83
  FileComplaintSchema: () => FileComplaintSchema,
52
84
  FrequencySchema: () => FrequencySchema,
53
85
  GUIDELY_ID_ATTRIBUTE: () => GUIDELY_ID_ATTRIBUTE,
86
+ GUIDE_EXPERIMENT_GOALS: () => GUIDE_EXPERIMENT_GOALS,
87
+ GUIDE_EXPERIMENT_GOAL_LABELS: () => GUIDE_EXPERIMENT_GOAL_LABELS,
88
+ GUIDE_EXPERIMENT_STATUSES: () => GUIDE_EXPERIMENT_STATUSES,
54
89
  GUIDE_KINDS: () => GUIDE_KINDS,
55
90
  GUIDE_LIFECYCLE_EVENTS: () => GUIDE_LIFECYCLE_EVENTS,
56
91
  GUIDE_STATUSES: () => GUIDE_STATUSES,
57
92
  GUIDE_TEMPLATES: () => GUIDE_TEMPLATES,
58
93
  GUIDE_VISIBILITIES: () => GUIDE_VISIBILITIES,
59
94
  GuideConfigSchema: () => GuideConfigSchema,
95
+ GuideLocalizationSchema: () => GuideLocalizationSchema,
96
+ GuideScheduleSchema: () => GuideScheduleSchema,
60
97
  GuideStateUpdateSchema: () => GuideStateUpdateSchema,
98
+ GuideThrottlingSchema: () => GuideThrottlingSchema,
61
99
  HEATMAP_VIEWPORTS: () => HEATMAP_VIEWPORTS,
62
100
  HOWTO_ACTIONS: () => HOWTO_ACTIONS,
63
101
  HOWTO_STEP_KINDS: () => HOWTO_STEP_KINDS,
64
102
  HowToAnnotationSchema: () => HowToAnnotationSchema,
65
103
  IdentifyRequestSchema: () => IdentifyRequestSchema,
104
+ LOCALE_PATTERN: () => LOCALE_PATTERN,
66
105
  LOGGED_IN_AUDIENCE: () => LOGGED_IN_AUDIENCE,
106
+ LocaleSchema: () => LocaleSchema,
107
+ LocalizationSettingsSchema: () => LocalizationSettingsSchema,
67
108
  MAX_ANNOTATIONS: () => MAX_ANNOTATIONS,
68
109
  MAX_COLLECTION_DEPTH: () => MAX_COLLECTION_DEPTH,
69
110
  MAX_COMPLAINT_ANSWER_LENGTH: () => MAX_COMPLAINT_ANSWER_LENGTH,
@@ -71,6 +112,11 @@ __export(index_exports, {
71
112
  MAX_COMPLAINT_CHOICES: () => MAX_COMPLAINT_CHOICES,
72
113
  MAX_COMPLAINT_FIELDS: () => MAX_COMPLAINT_FIELDS,
73
114
  MAX_COMPLAINT_LENGTH: () => MAX_COMPLAINT_LENGTH,
115
+ MAX_CUSTOM_CSS: () => MAX_CUSTOM_CSS,
116
+ MAX_FEEDBACK_COMMENT: () => MAX_FEEDBACK_COMMENT,
117
+ MAX_FEEDBACK_DESCRIPTION: () => MAX_FEEDBACK_DESCRIPTION,
118
+ MAX_FEEDBACK_NOTE: () => MAX_FEEDBACK_NOTE,
119
+ MAX_FEEDBACK_TITLE: () => MAX_FEEDBACK_TITLE,
74
120
  MAX_MESSAGE_LENGTH: () => MAX_MESSAGE_LENGTH,
75
121
  MAX_PROPERTY_BYTES: () => MAX_PROPERTY_BYTES,
76
122
  MAX_STACK_FRAMES: () => MAX_STACK_FRAMES,
@@ -84,8 +130,10 @@ __export(index_exports, {
84
130
  MESSAGE_AUTHORS: () => MESSAGE_AUTHORS,
85
131
  MessengerPageRequestSchema: () => MessengerPageRequestSchema,
86
132
  NETWORK_PLUGIN: () => NETWORK_PLUGIN,
133
+ NOISY_DATA_ATTR: () => NOISY_DATA_ATTR,
87
134
  NormalizedPointSchema: () => NormalizedPointSchema,
88
135
  NormalizedRectSchema: () => NormalizedRectSchema,
136
+ PAGE_RULE_LIMITS: () => PAGE_RULE_LIMITS,
89
137
  PATH_ID_PATTERN: () => PATH_ID_PATTERN,
90
138
  PDF_BLOCK_CLASS: () => PDF_BLOCK_CLASS,
91
139
  PDF_MAX_PAGES: () => PDF_MAX_PAGES,
@@ -95,6 +143,8 @@ __export(index_exports, {
95
143
  PostMessageSchema: () => PostMessageSchema,
96
144
  ProjectThemeSchema: () => ProjectThemeSchema,
97
145
  PublishedGuideSchema: () => PublishedGuideSchema,
146
+ RC_MODULE_IDS: () => RC_MODULE_IDS,
147
+ RC_MODULE_LABELS: () => RC_MODULE_LABELS,
98
148
  REPLAY_MAX_COMPRESSED_BYTES: () => REPLAY_MAX_COMPRESSED_BYTES,
99
149
  REPLAY_MAX_RAW_BYTES: () => REPLAY_MAX_RAW_BYTES,
100
150
  REPLY_TIMES: () => REPLY_TIMES,
@@ -104,6 +154,9 @@ __export(index_exports, {
104
154
  ReplaySettingsSchema: () => ReplaySettingsSchema,
105
155
  RuleGroupSchema: () => RuleGroupSchema,
106
156
  RuleSchema: () => RuleSchema,
157
+ SCOUT_AGENT_ID: () => SCOUT_AGENT_ID,
158
+ SCRIPT_STUB: () => SCRIPT_STUB,
159
+ SCRIPT_STUB_METHODS: () => SCRIPT_STUB_METHODS,
107
160
  SDK_API_VERSION: () => SDK_API_VERSION,
108
161
  SELECTOR_KINDS: () => SELECTOR_KINDS,
109
162
  SENSITIVE_HEADER_PATTERN: () => SENSITIVE_HEADER_PATTERN,
@@ -113,30 +166,46 @@ __export(index_exports, {
113
166
  SHARED_VERSION: () => SHARED_VERSION,
114
167
  SHOW_ME_CLASS: () => SHOW_ME_CLASS,
115
168
  SHOW_ME_HREF_PREFIX: () => SHOW_ME_HREF_PREFIX,
169
+ SNAPSHOT_ATTRS: () => SNAPSHOT_ATTRS,
170
+ SNAPSHOT_LIMITS: () => SNAPSHOT_LIMITS,
116
171
  SOURCEMAP_MAX_FILES_PER_UPLOAD: () => SOURCEMAP_MAX_FILES_PER_UPLOAD,
117
172
  SOURCEMAP_MAX_FILE_BYTES: () => SOURCEMAP_MAX_FILE_BYTES,
118
173
  STATUS_LEVELS: () => STATUS_LEVELS,
119
174
  STEP_TYPES: () => STEP_TYPES,
120
175
  SURVEY_QUESTION_TYPES: () => SURVEY_QUESTION_TYPES,
176
+ SdkAgentEventsSchema: () => SdkAgentEventsSchema,
121
177
  SdkEventSchema: () => SdkEventSchema,
122
178
  SelectorStrategySchema: () => SelectorStrategySchema,
179
+ SelectorSyntaxError: () => SelectorSyntaxError,
123
180
  StartConversationSchema: () => StartConversationSchema,
124
181
  StepBranchSchema: () => StepBranchSchema,
125
182
  StepSchema: () => StepSchema,
183
+ SubmitFeedbackSchema: () => SubmitFeedbackSchema,
126
184
  SurveyConfigSchema: () => SurveyConfigSchema,
127
185
  SurveyQuestionSchema: () => SurveyQuestionSchema,
128
186
  SurveyResponseRequestSchema: () => SurveyResponseRequestSchema,
187
+ TAG_PROPERTY_LIMITS: () => TAG_PROPERTY_LIMITS,
129
188
  TRIGGER_TYPES: () => TRIGGER_TYPES,
130
189
  TargetSchema: () => TargetSchema,
131
190
  TriggerSchema: () => TriggerSchema,
132
191
  VIDEO_ATTRS: () => VIDEO_ATTRS,
192
+ WCAG_AA_LARGE: () => WCAG_AA_LARGE,
193
+ WCAG_AA_TEXT: () => WCAG_AA_TEXT,
133
194
  WS_MAX_MESSAGES_PER_SOCKET: () => WS_MAX_MESSAGES_PER_SOCKET,
134
195
  WS_MAX_MESSAGE_BYTES: () => WS_MAX_MESSAGE_BYTES,
196
+ applyGuideTranslations: () => applyGuideTranslations,
197
+ articleTextEntries: () => articleTextEntries,
198
+ assignGuideVariant: () => assignGuideVariant,
199
+ baseLanguage: () => baseLanguage,
135
200
  clamp: () => clamp,
136
201
  cleanLabel: () => cleanLabel,
137
202
  compare: () => compare,
138
203
  compareVersions: () => compareVersions,
139
204
  complaintReference: () => complaintReference,
205
+ compoundMatches: () => compoundMatches,
206
+ contrastIssues: () => contrastIssues,
207
+ contrastRatio: () => contrastRatio,
208
+ cssSelectorError: () => cssSelectorError,
140
209
  defaultGuideConfig: () => defaultGuideConfig,
141
210
  defaultStep: () => defaultStep,
142
211
  describeCaptureStep: () => describeCaptureStep,
@@ -144,12 +213,21 @@ __export(index_exports, {
144
213
  emptyRuleGroup: () => emptyRuleGroup,
145
214
  evaluateRule: () => evaluateRule,
146
215
  evaluateRules: () => evaluateRules,
216
+ evenWeights: () => evenWeights,
217
+ experimentBucketRules: () => experimentBucketRules,
218
+ experimentSalt: () => experimentSalt,
219
+ featureCssSelectors: () => featureCssSelectors,
220
+ featureRuleError: () => featureRuleError,
221
+ featureRuleMatchesClick: () => featureRuleMatchesClick,
222
+ feedbackReference: () => feedbackReference,
147
223
  fingerprintError: () => fingerprintError,
148
224
  firstNameFromTraits: () => firstNameFromTraits,
149
225
  fnv1a: () => fnv1a,
150
226
  foldPathIds: () => foldPathIds,
151
227
  getPath: () => getPath,
228
+ guideLocales: () => guideLocales,
152
229
  guidePlatforms: () => guidePlatforms,
230
+ guideTextEntries: () => guideTextEntries,
153
231
  guidelyIdFromSelector: () => guidelyIdFromSelector,
154
232
  hasVideoMedia: () => hasVideoMedia,
155
233
  isAllowedEmbedSrc: () => isAllowedEmbedSrc,
@@ -162,6 +240,12 @@ __export(index_exports, {
162
240
  isRuleGroup: () => isRuleGroup,
163
241
  isSafeMediaUrl: () => isSafeMediaUrl,
164
242
  isVideoContentType: () => isVideoContentType,
243
+ localeName: () => localeName,
244
+ localizeAnnouncement: () => localizeAnnouncement,
245
+ localizeArticle: () => localizeArticle,
246
+ localizeGuide: () => localizeGuide,
247
+ localizeResourceCenter: () => localizeResourceCenter,
248
+ matchCssSelector: () => matchCssSelector,
165
249
  matchUrlPattern: () => matchUrlPattern,
166
250
  matchesAudiences: () => matchesAudiences,
167
251
  matchesHelpQuery: () => matchesHelpQuery,
@@ -169,30 +253,63 @@ __export(index_exports, {
169
253
  mediaMaxBytes: () => mediaMaxBytes,
170
254
  normalizeErrorMessage: () => normalizeErrorMessage,
171
255
  normalizeFrameFile: () => normalizeFrameFile,
256
+ normalizeLocale: () => normalizeLocale,
257
+ normalizeSnapshot: () => normalizeSnapshot,
258
+ orderedModules: () => orderedModules,
172
259
  pageLabel: () => pageLabel,
173
260
  pageName: () => pageName,
261
+ pagePattern: () => pagePattern,
262
+ pageRuleError: () => pageRuleError,
263
+ pageRuleMatches: () => pageRuleMatches,
264
+ pageRulesMatch: () => pageRulesMatch,
174
265
  pageTerms: () => pageTerms,
266
+ parseCssSelector: () => parseCssSelector,
267
+ parseCsvRows: () => parseCsvRows,
268
+ parseHexColor: () => parseHexColor,
175
269
  parseStack: () => parseStack,
270
+ parseTranslationCsv: () => parseTranslationCsv,
271
+ parseXliff: () => parseXliff,
272
+ propertyAttributeAllowed: () => propertyAttributeAllowed,
273
+ queryConditionRegex: () => queryConditionRegex,
176
274
  randomId: () => randomId,
275
+ readableTextOn: () => readableTextOn,
276
+ relativeLuminance: () => relativeLuminance,
177
277
  resolveCaptureSettings: () => resolveCaptureSettings,
278
+ resolveLocale: () => resolveLocale,
279
+ resourceCenterLocales: () => resourceCenterLocales,
178
280
  resourceCenterSections: () => resourceCenterSections,
281
+ resourceCenterTextEntries: () => resourceCenterTextEntries,
179
282
  rolloutBucket: () => rolloutBucket,
180
283
  safeRegExp: () => safeRegExp,
284
+ sanitizeCustomCss: () => sanitizeCustomCss,
181
285
  sanitizeProperties: () => sanitizeProperties,
286
+ scopeCustomCss: () => scopeCustomCss,
182
287
  screenPath: () => screenPath,
288
+ scriptSnippet: () => scriptSnippet,
183
289
  servedArticleAudiences: () => servedArticleAudiences,
184
290
  showMeHref: () => showMeHref,
185
291
  showMeKeyFromHref: () => showMeKeyFromHref,
186
292
  showMeKeys: () => showMeKeys,
187
293
  slugify: () => slugify,
294
+ snapshotFromSelector: () => snapshotFromSelector,
295
+ stableStringify: () => stableStringify,
188
296
  stripOrigin: () => stripOrigin,
189
297
  supportsPlatform: () => supportsPlatform,
190
298
  templateConfig: () => templateConfig,
191
299
  toEmbedUrl: () => toEmbedUrl,
300
+ toTranslationCsv: () => toTranslationCsv,
301
+ toXliff: () => toXliff,
302
+ translationCoverage: () => translationCoverage,
303
+ unreadAnnouncements: () => unreadAnnouncements,
192
304
  validateGuideConfig: () => validateGuideConfig,
305
+ variantProblems: () => variantProblems,
306
+ variantRanges: () => variantRanges,
307
+ visibleAnnouncements: () => visibleAnnouncements,
193
308
  visibleArticleIds: () => visibleArticleIds,
194
309
  visibleButtons: () => visibleButtons,
195
310
  visitorAudiences: () => visitorAudiences,
311
+ visitorLocales: () => visitorLocales,
312
+ withExperimentBucket: () => withExperimentBucket,
196
313
  withVisibility: () => withVisibility
197
314
  });
198
315
  module.exports = __toCommonJS(index_exports);
@@ -387,17 +504,21 @@ var RULE_FIELDS = [
387
504
  "datetime.dayOfWeek",
388
505
  "datetime.hour",
389
506
  "rollout.percentage",
507
+ /** Guide A/B tests: the visitor's 0-99 bucket for the salt in `key` (see guide-experiments.ts). */
508
+ "experiment.bucket",
390
509
  "environment",
391
510
  "locale",
392
511
  "app.platform",
393
512
  "app.screen",
394
- "app.version"
513
+ "app.version",
514
+ "page.views",
515
+ "feature.clicks"
395
516
  ];
396
517
  function isRuleGroup(r) {
397
518
  return r.rules !== void 0;
398
519
  }
399
- function emptyRuleGroup(id = "root") {
400
- return { id, op: "and", rules: [] };
520
+ function emptyRuleGroup(id2 = "root") {
521
+ return { id: id2, op: "and", rules: [] };
401
522
  }
402
523
  function has(set, v) {
403
524
  if (!set) return false;
@@ -451,6 +572,8 @@ function resolveField(rule, ctx) {
451
572
  return ctx.now.getHours();
452
573
  case "rollout.percentage":
453
574
  return rolloutBucket(ctx.userId || ctx.anonymousId, ctx.rolloutSalt || "guidely");
575
+ case "experiment.bucket":
576
+ return rule.key ? rolloutBucket(ctx.userId || ctx.anonymousId, rule.key) : void 0;
454
577
  case "environment":
455
578
  return ctx.environment;
456
579
  case "locale":
@@ -461,6 +584,9 @@ function resolveField(rule, ctx) {
461
584
  return ctx.screen;
462
585
  case "app.version":
463
586
  return ctx.appVersion;
587
+ case "page.views":
588
+ case "feature.clicks":
589
+ return rule.key ? ctx.tagUsage?.[rule.key] ?? 0 : 0;
464
590
  default:
465
591
  return void 0;
466
592
  }
@@ -560,7 +686,7 @@ function evaluateRules(group, ctx) {
560
686
  const value = group.op === "and" ? results.every(Boolean) : results.some(Boolean);
561
687
  return group.negate ? !value : value;
562
688
  }
563
- var SERVER_ASSISTED_FIELDS = ["audience.member", "guide.completed", "guide.dismissed", "guide.seen", "checklist.completed"];
689
+ var SERVER_ASSISTED_FIELDS = ["audience.member", "guide.completed", "guide.dismissed", "guide.seen", "checklist.completed", "page.views", "feature.clicks"];
564
690
  var GUIDE_VISIBILITIES = ["everyone", "identified", "anonymous"];
565
691
  function withVisibility(targeting, visibility) {
566
692
  if (!visibility || visibility === "everyone") return targeting;
@@ -592,6 +718,57 @@ var RuleGroupSchema = import_zod.z.lazy(
592
718
 
593
719
  // src/guide.ts
594
720
  var import_zod2 = require("zod");
721
+
722
+ // src/contrast.ts
723
+ var WCAG_AA_TEXT = 4.5;
724
+ var WCAG_AA_LARGE = 3;
725
+ function channel(c) {
726
+ const s = c / 255;
727
+ return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
728
+ }
729
+ function parseHexColor(hex) {
730
+ if (!hex) return null;
731
+ const m = hex.trim().match(/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i);
732
+ if (!m) return null;
733
+ const h = m[1].length === 3 ? m[1].split("").map((c) => c + c).join("") : m[1];
734
+ return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)];
735
+ }
736
+ function relativeLuminance(hex) {
737
+ const rgb = parseHexColor(hex);
738
+ if (!rgb) return null;
739
+ return 0.2126 * channel(rgb[0]) + 0.7152 * channel(rgb[1]) + 0.0722 * channel(rgb[2]);
740
+ }
741
+ function contrastRatio(a, b) {
742
+ const la = relativeLuminance(a);
743
+ const lb = relativeLuminance(b);
744
+ if (la === null || lb === null) return null;
745
+ const [hi, lo] = la > lb ? [la, lb] : [lb, la];
746
+ return Math.round((hi + 0.05) / (lo + 0.05) * 100) / 100;
747
+ }
748
+ function readableTextOn(background) {
749
+ const white = contrastRatio(background, "#ffffff") ?? 0;
750
+ const dark = contrastRatio(background, "#111827") ?? 0;
751
+ return white >= dark ? "#ffffff" : "#111827";
752
+ }
753
+ function contrastIssues(colors) {
754
+ const issues = [];
755
+ const { primaryColor, backgroundColor, textColor } = colors;
756
+ if (textColor && backgroundColor) {
757
+ const r = contrastRatio(textColor, backgroundColor);
758
+ if (r !== null && r < WCAG_AA_TEXT) issues.push({ pair: "text", ratio: r, required: WCAG_AA_TEXT, message: `Text on the background has a contrast of ${r}:1; WCAG AA needs ${WCAG_AA_TEXT}:1.` });
759
+ }
760
+ if (primaryColor) {
761
+ const label = contrastRatio(primaryColor, readableTextOn(primaryColor));
762
+ if (label !== null && label < WCAG_AA_TEXT) issues.push({ pair: "button", ratio: label, required: WCAG_AA_TEXT, message: `Button labels on the primary colour have a contrast of ${label}:1; WCAG AA needs ${WCAG_AA_TEXT}:1.` });
763
+ if (backgroundColor) {
764
+ const link = contrastRatio(primaryColor, backgroundColor);
765
+ if (link !== null && link < WCAG_AA_LARGE) issues.push({ pair: "link", ratio: link, required: WCAG_AA_LARGE, message: `The primary colour on the background (links, outlined buttons) has a contrast of ${link}:1; WCAG AA needs ${WCAG_AA_LARGE}:1.` });
766
+ }
767
+ }
768
+ return issues;
769
+ }
770
+
771
+ // src/guide.ts
595
772
  var GUIDE_KINDS = ["flow", "modal", "tooltip", "banner", "checklist", "survey", "announcement"];
596
773
  var GUIDE_STATUSES = ["draft", "published", "paused", "archived"];
597
774
  var STEP_TYPES = ["modal", "tooltip", "popover", "spotlight", "hotspot", "banner", "slideout", "checklist", "custom", "survey"];
@@ -640,6 +817,8 @@ var StepSchema = import_zod2.z.object({
640
817
  /** Sanitized HTML body (links, images, lists, formatting). */
641
818
  body: import_zod2.z.string().max(2e4).default(""),
642
819
  imageUrl: import_zod2.z.string().url().max(2e3).optional().or(import_zod2.z.literal("")),
820
+ /** Alternative text for `imageUrl` (screen readers); empty = decorative. */
821
+ imageAlt: import_zod2.z.string().max(300).optional(),
643
822
  buttons: import_zod2.z.array(ButtonSchema).max(6).default([]),
644
823
  target: TargetSchema.optional(),
645
824
  placement: import_zod2.z.enum(PLACEMENTS).default("auto"),
@@ -666,7 +845,12 @@ var StepSchema = import_zod2.z.object({
666
845
  /** Hotspot pulse dot settings. */
667
846
  hotspot: import_zod2.z.object({ size: import_zod2.z.number().int().min(8).max(40).default(14), pulse: import_zod2.z.boolean().default(true), openOn: import_zod2.z.enum(["click", "hover"]).default("click") }).optional(),
668
847
  /** Custom step: arbitrary sanitized HTML with no chrome. */
669
- customHtml: import_zod2.z.string().max(5e4).optional()
848
+ customHtml: import_zod2.z.string().max(5e4).optional(),
849
+ /**
850
+ * Code block (custom steps only): JavaScript run on the web when the step shows, only while the
851
+ * workspace allows code blocks (an admin setting, off by default). Mobile SDKs never receive it.
852
+ */
853
+ code: import_zod2.z.string().max(2e4).optional()
670
854
  });
671
855
  var TRIGGER_TYPES = ["page_load", "url_match", "event", "element_click", "element_visible", "manual", "delay", "after_guide", "segment_enter"];
672
856
  var TriggerSchema = import_zod2.z.object({
@@ -688,7 +872,9 @@ var FrequencySchema = import_zod2.z.object({
688
872
  /** Guide ids that must not be active at the same time. */
689
873
  mutuallyExclusiveWith: import_zod2.z.array(import_zod2.z.string()).max(50).default([]),
690
874
  /** Re-show if dismissed (otherwise dismissal counts as completion for frequency). */
691
- reshowAfterDismiss: import_zod2.z.boolean().default(false)
875
+ reshowAfterDismiss: import_zod2.z.boolean().default(false),
876
+ /** Bypass the project's guide throttling (always eligible as far as throttling goes). */
877
+ ignoreThrottling: import_zod2.z.boolean().optional()
692
878
  });
693
879
  var AppearanceSchema = import_zod2.z.object({
694
880
  theme: import_zod2.z.enum(["light", "dark", "auto"]).default("auto"),
@@ -700,7 +886,9 @@ var AppearanceSchema = import_zod2.z.object({
700
886
  overlayOpacity: import_zod2.z.number().min(0).max(1).optional(),
701
887
  zIndex: import_zod2.z.number().int().min(1).max(2147483647).optional(),
702
888
  preset: import_zod2.z.string().max(50).optional(),
703
- animation: import_zod2.z.enum(["fade", "slide", "none"]).default("fade")
889
+ animation: import_zod2.z.enum(["fade", "slide", "none"]).default("fade"),
890
+ /** Custom CSS scoped to this guide's container (sanitized; see custom-css.ts). Web only. */
891
+ customCss: import_zod2.z.string().max(2e4).optional()
704
892
  });
705
893
  var ChecklistTaskSchema = import_zod2.z.object({
706
894
  id: import_zod2.z.string().min(1),
@@ -747,6 +935,26 @@ var SurveyConfigSchema = import_zod2.z.object({
747
935
  startAt: import_zod2.z.string().datetime().optional(),
748
936
  endAt: import_zod2.z.string().datetime().optional()
749
937
  });
938
+ var GuideScheduleSchema = import_zod2.z.object({
939
+ startAt: import_zod2.z.string().datetime().optional(),
940
+ endAt: import_zod2.z.string().datetime().optional(),
941
+ timezone: import_zod2.z.string().max(64).optional()
942
+ });
943
+ var LOCALE_PATTERN = /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{2,8}){0,2}$/;
944
+ var LocaleSchema = import_zod2.z.string().regex(LOCALE_PATTERN, "Use a language code such as fr or pt-BR").max(20);
945
+ var GuideLocalizationSchema = import_zod2.z.object({
946
+ translations: import_zod2.z.record(LocaleSchema, import_zod2.z.record(import_zod2.z.string().max(200), import_zod2.z.string().max(5e4))).default({})
947
+ });
948
+ var LocalizationSettingsSchema = import_zod2.z.object({
949
+ defaultLocale: LocaleSchema.default("en"),
950
+ locales: import_zod2.z.array(LocaleSchema).max(50).default([])
951
+ });
952
+ var GuideThrottlingSchema = import_zod2.z.object({
953
+ enabled: import_zod2.z.boolean().default(false),
954
+ maxGuides: import_zod2.z.number().int().min(1).max(50).default(1),
955
+ windowHours: import_zod2.z.number().int().min(1).max(720).default(24),
956
+ minGapMinutes: import_zod2.z.number().int().min(0).max(10080).default(0)
957
+ });
750
958
  var GuideConfigSchema = import_zod2.z.object({
751
959
  steps: import_zod2.z.array(StepSchema).max(50).default([]),
752
960
  /** Everyone, only identified (logged-in) users, or only anonymous visitors; applied on top of `targeting`. */
@@ -760,7 +968,11 @@ var GuideConfigSchema = import_zod2.z.object({
760
968
  /** Restrict guide to url pattern(s) (applied before trigger). On mobile these match the screen path `/<Screen>`. */
761
969
  urlPatterns: import_zod2.z.array(import_zod2.z.string().max(500)).max(20).default([]),
762
970
  /** Platforms that receive this guide. Guides created before mobile support are web-only. */
763
- platforms: import_zod2.z.array(import_zod2.z.enum(PLATFORMS)).max(PLATFORMS.length).default(["web"])
971
+ platforms: import_zod2.z.array(import_zod2.z.enum(PLATFORMS)).max(PLATFORMS.length).default(["web"]),
972
+ /** Start / end window for any guide kind (surveys also honour `survey.startAt` / `endAt`). */
973
+ schedule: GuideScheduleSchema.optional(),
974
+ /** Translations (see localization.ts). */
975
+ localization: GuideLocalizationSchema.optional()
764
976
  });
765
977
  function defaultGuideConfig(kind) {
766
978
  return GuideConfigSchema.parse({
@@ -794,7 +1006,7 @@ function defaultStep(type, overrides = {}) {
794
1006
  function visibleButtons(step, canGoBack) {
795
1007
  return canGoBack ? step.buttons : step.buttons.filter((b) => b.action !== "back");
796
1008
  }
797
- function validateGuideConfig(kind, config) {
1009
+ function validateGuideConfig(kind, config, theme) {
798
1010
  const issues = [];
799
1011
  if (kind === "checklist") {
800
1012
  if (!config.checklist || config.checklist.tasks.length === 0) issues.push({ level: "error", message: "Checklist needs at least one task." });
@@ -831,6 +1043,15 @@ function validateGuideConfig(kind, config) {
831
1043
  if (config.trigger.type === "element_click" && !config.trigger.value) issues.push({ level: "error", message: "Element click trigger needs a selector." });
832
1044
  if (config.trigger.type === "url_match" && !config.trigger.value) issues.push({ level: "error", message: "URL trigger needs a pattern." });
833
1045
  if (config.frequency.mode === "interval" && !config.frequency.intervalHours) issues.push({ level: "error", message: "Interval frequency needs an interval in hours." });
1046
+ const sched = config.schedule;
1047
+ if (sched?.startAt && sched.endAt && Date.parse(sched.endAt) <= Date.parse(sched.startAt)) issues.push({ level: "error", message: "The schedule ends before it starts." });
1048
+ if (sched?.endAt && Date.parse(sched.endAt) < Date.now()) issues.push({ level: "warning", message: "The schedule has already ended, so nobody will see this guide." });
1049
+ config.steps.forEach((step, i) => {
1050
+ if (step.code && step.type !== "custom") issues.push({ level: "error", stepId: step.id, message: `Step ${i + 1}: code blocks can only run in custom steps.` });
1051
+ if (step.code && mobile) issues.push({ level: "warning", stepId: step.id, message: `Step ${i + 1} runs a code block; mobile apps skip it.` });
1052
+ });
1053
+ const colors = { primaryColor: config.appearance.primaryColor ?? theme?.primaryColor, backgroundColor: config.appearance.backgroundColor ?? theme?.backgroundColor, textColor: config.appearance.textColor ?? theme?.textColor };
1054
+ for (const c of contrastIssues(colors)) issues.push({ level: "warning", message: `Low contrast: ${c.message}` });
834
1055
  return issues;
835
1056
  }
836
1057
  var ProjectThemeSchema = import_zod2.z.object({
@@ -840,7 +1061,9 @@ var ProjectThemeSchema = import_zod2.z.object({
840
1061
  borderRadius: import_zod2.z.number().int().min(0).max(32).default(12),
841
1062
  fontFamily: import_zod2.z.string().max(200).default("Inter, system-ui, -apple-system, sans-serif"),
842
1063
  logoUrl: import_zod2.z.string().max(2e3).optional(),
843
- brandName: import_zod2.z.string().max(100).optional()
1064
+ brandName: import_zod2.z.string().max(100).optional(),
1065
+ /** Custom CSS applied to every guide's container (sanitized and scoped like guide CSS). Web only. */
1066
+ customCss: import_zod2.z.string().max(2e4).optional()
844
1067
  });
845
1068
 
846
1069
  // src/events.ts
@@ -856,8 +1079,8 @@ function sanitizeProperties(props) {
856
1079
  for (const [k, v] of Object.entries(props)) {
857
1080
  if (SENSITIVE_PROPERTY_PATTERN.test(k)) continue;
858
1081
  if (typeof v === "function" || typeof v === "symbol") continue;
859
- const str = typeof v === "string" ? v : JSON.stringify(v ?? null);
860
- size += k.length + (str?.length ?? 0);
1082
+ const str2 = typeof v === "string" ? v : JSON.stringify(v ?? null);
1083
+ size += k.length + (str2?.length ?? 0);
861
1084
  if (size > MAX_PROPERTY_BYTES) break;
862
1085
  out[k.slice(0, 100)] = typeof v === "string" ? v.slice(0, 1e3) : v;
863
1086
  }
@@ -937,9 +1160,15 @@ var EVENT_NAMES = [
937
1160
  "exception",
938
1161
  "heatmap",
939
1162
  // Feature flags: a user was bucketed into an experiment variation (properties: experimentKey, variationId, flagKey).
940
- "experiment_viewed"
1163
+ "experiment_viewed",
1164
+ // Mobile app lifecycle (mobile/SPEC.md "Product analytics"): installs, updates, opens and backgrounding.
1165
+ "app_install",
1166
+ "app_update",
1167
+ "app_open",
1168
+ "app_background"
941
1169
  ];
942
- var AUTOCAPTURE_EVENTS = ["page_view", "page_leave", "click", "rage_click", "exception", "heatmap"];
1170
+ var AUTOCAPTURE_EVENTS = ["page_view", "page_leave", "click", "rage_click", "exception", "heatmap", "app_install", "app_update", "app_open", "app_background"];
1171
+ var APP_LIFECYCLE_EVENTS = ["app_install", "app_update", "app_open", "app_background"];
943
1172
  var GUIDE_LIFECYCLE_EVENTS = ["guide_viewed", "guide_started", "step_viewed", "step_completed", "guide_completed", "guide_skipped", "guide_dismissed", "guide_abandoned"];
944
1173
  var SdkEventSchema = import_zod3.z.object({
945
1174
  eventId: import_zod3.z.string().min(8).max(64),
@@ -1007,7 +1236,9 @@ var AuthoringPickSchema = import_zod4.z.object({
1007
1236
  selectors: import_zod4.z.array(import_zod4.z.object({ kind: import_zod4.z.string(), value: import_zod4.z.string().max(1e3), label: import_zod4.z.string().max(200).optional() })).max(10),
1008
1237
  textSnapshot: import_zod4.z.string().max(200).optional(),
1009
1238
  url: import_zod4.z.string().max(2e3).optional(),
1010
- rect: import_zod4.z.object({ x: import_zod4.z.number(), y: import_zod4.z.number(), width: import_zod4.z.number(), height: import_zod4.z.number() }).optional()
1239
+ rect: import_zod4.z.object({ x: import_zod4.z.number(), y: import_zod4.z.number(), width: import_zod4.z.number(), height: import_zod4.z.number() }).optional(),
1240
+ /** Compact snapshot of the picked element (tag mode: feature rules are proposed from it). */
1241
+ elementSnapshot: import_zod4.z.record(import_zod4.z.unknown()).optional()
1011
1242
  });
1012
1243
  var PublishedGuideSchema = import_zod4.z.object({
1013
1244
  id: import_zod4.z.string(),
@@ -1085,22 +1316,153 @@ var FileComplaintSchema = import_zod6.z.object({
1085
1316
  }).optional().nullable()
1086
1317
  });
1087
1318
 
1088
- // src/capture.ts
1319
+ // src/agents.ts
1089
1320
  var import_zod7 = require("zod");
1090
- var AutocaptureSettingsSchema = import_zod7.z.object({ pageviews: import_zod7.z.boolean(), pageLeave: import_zod7.z.boolean(), clicks: import_zod7.z.boolean(), rageClicks: import_zod7.z.boolean(), heatmaps: import_zod7.z.boolean(), mouseMovement: import_zod7.z.boolean() }).partial();
1091
- var ErrorTrackingSettingsSchema = import_zod7.z.object({ enabled: import_zod7.z.boolean() }).partial();
1092
- var ReplaySettingsSchema = import_zod7.z.object({
1093
- enabled: import_zod7.z.boolean(),
1094
- sampleRate: import_zod7.z.number().int().min(0).max(100),
1095
- recordConsole: import_zod7.z.boolean(),
1096
- recordNetwork: import_zod7.z.boolean(),
1097
- recordNetworkPayloads: import_zod7.z.boolean(),
1098
- maskAllText: import_zod7.z.boolean(),
1099
- blockSelectors: import_zod7.z.array(import_zod7.z.string().min(1).max(200)).max(50),
1100
- retentionDays: import_zod7.z.number().int().min(1).max(365)
1321
+
1322
+ // src/agents-limits.ts
1323
+ var AGENT_TURN_ROLES = ["user", "assistant", "tool", "system"];
1324
+ var AGENT_OUTCOMES = ["success", "failure", "escalated", "abandoned"];
1325
+ var AGENT_TOOL_STATUSES = ["ok", "error"];
1326
+ var AGENT_TURN_MAX_TEXT = 2e4;
1327
+ var AGENT_TURNS_PER_BATCH = 100;
1328
+ var AGENT_TOOL_CALLS_PER_TURN = 50;
1329
+ var AGENT_METADATA_MAX_KEYS = 30;
1330
+ var AGENT_METADATA_MAX_BYTES = 4096;
1331
+ var SCOUT_AGENT_ID = "scout";
1332
+
1333
+ // src/agents.ts
1334
+ var ENVIRONMENTS = ["development", "staging", "production"];
1335
+ var AgentToolCallSchema = import_zod7.z.object({
1336
+ name: import_zod7.z.string().trim().min(1).max(100),
1337
+ status: import_zod7.z.enum(AGENT_TOOL_STATUSES).optional(),
1338
+ latencyMs: import_zod7.z.number().int().min(0).max(36e5).optional()
1339
+ }).strip();
1340
+ var AgentMetadataSchema = import_zod7.z.record(import_zod7.z.string().max(100), import_zod7.z.unknown()).transform((m) => {
1341
+ const out = {};
1342
+ let size = 0;
1343
+ for (const [k, v] of Object.entries(m)) {
1344
+ const key = k.trim();
1345
+ if (!key || key.startsWith("$") || SENSITIVE_PROPERTY_PATTERN.test(key)) continue;
1346
+ if (!(typeof v === "string" || typeof v === "boolean" || v === null || typeof v === "number" && Number.isFinite(v))) continue;
1347
+ const value = typeof v === "string" ? v.slice(0, 500) : v;
1348
+ size += key.length + String(value).length;
1349
+ if (size > AGENT_METADATA_MAX_BYTES || Object.keys(out).length >= AGENT_METADATA_MAX_KEYS) break;
1350
+ out[key] = value;
1351
+ }
1352
+ return out;
1353
+ });
1354
+ var id = (max) => import_zod7.z.string().trim().min(1).max(max);
1355
+ var optionalId = (max) => import_zod7.z.string().trim().max(max).optional().nullable().transform((v) => v || null);
1356
+ var AgentTurnInputSchema = import_zod7.z.object({
1357
+ type: import_zod7.z.literal("agent.conversation").optional(),
1358
+ conversationId: id(128),
1359
+ agentId: id(64).refine((v) => v.toLowerCase() !== SCOUT_AGENT_ID, { message: `"${SCOUT_AGENT_ID}" is reserved for Guidely's built-in Scout agent` }),
1360
+ agentName: import_zod7.z.string().trim().max(100).optional(),
1361
+ turnId: import_zod7.z.string().trim().min(1).max(128).optional(),
1362
+ role: import_zod7.z.enum(AGENT_TURN_ROLES),
1363
+ text: import_zod7.z.string().max(AGENT_TURN_MAX_TEXT).default(""),
1364
+ toolCalls: import_zod7.z.array(AgentToolCallSchema).max(AGENT_TOOL_CALLS_PER_TURN).default([]),
1365
+ latencyMs: import_zod7.z.number().int().min(0).max(36e5).optional(),
1366
+ outcome: import_zod7.z.enum(AGENT_OUTCOMES).optional(),
1367
+ taskSuccess: import_zod7.z.boolean().optional(),
1368
+ occurredAt: import_zod7.z.string().datetime({ offset: true }).optional(),
1369
+ userId: optionalId(256),
1370
+ anonymousId: optionalId(128),
1371
+ accountId: optionalId(256),
1372
+ sessionId: optionalId(128),
1373
+ metadata: AgentMetadataSchema.default({})
1374
+ });
1375
+ var turns = import_zod7.z.array(AgentTurnInputSchema).min(1).max(AGENT_TURNS_PER_BATCH);
1376
+ var sdkInfo = import_zod7.z.object({ name: import_zod7.z.string().max(60), version: import_zod7.z.string().max(30) }).optional();
1377
+ var SdkAgentEventsSchema = import_zod7.z.object({ turns, sdk: sdkInfo });
1378
+ var AgentEventsRequestSchema = import_zod7.z.preprocess(
1379
+ (v) => {
1380
+ if (Array.isArray(v)) return { turns: v };
1381
+ if (v && typeof v === "object" && !("turns" in v)) {
1382
+ const { environment, ...turn } = v;
1383
+ return { turns: [turn], environment };
1384
+ }
1385
+ return v;
1386
+ },
1387
+ import_zod7.z.object({ turns, environment: import_zod7.z.enum(ENVIRONMENTS).default("production"), sdk: sdkInfo })
1388
+ );
1389
+
1390
+ // src/feedback.ts
1391
+ var import_zod8 = require("zod");
1392
+
1393
+ // src/feedback-limits.ts
1394
+ var FEEDBACK_STATUSES = ["new", "under_review", "planned", "in_progress", "released", "declined"];
1395
+ var FEEDBACK_STATUS_LABEL = {
1396
+ new: "New",
1397
+ under_review: "Under review",
1398
+ planned: "Planned",
1399
+ in_progress: "In progress",
1400
+ released: "Released",
1401
+ declined: "Declined"
1402
+ };
1403
+ var FEEDBACK_PRIORITIES = ["nice_to_have", "important", "critical"];
1404
+ var FEEDBACK_PRIORITY_LABEL = { nice_to_have: "Nice to have", important: "Important", critical: "Critical" };
1405
+ var FEEDBACK_PRIORITY_WEIGHT = { nice_to_have: 1, important: 2, critical: 3 };
1406
+ var FEEDBACK_EVENTS = ["request.created", "request.status_changed", "request.voted"];
1407
+ var MAX_FEEDBACK_TITLE = 140;
1408
+ var MAX_FEEDBACK_DESCRIPTION = 4e3;
1409
+ var MAX_FEEDBACK_COMMENT = 2e3;
1410
+ var MAX_FEEDBACK_NOTE = 500;
1411
+ var feedbackReference = (number) => `#${number}`;
1412
+
1413
+ // src/feedback.ts
1414
+ var visitor = {
1415
+ anonymousId: import_zod8.z.string().min(1).max(128),
1416
+ userId: import_zod8.z.string().max(256).optional().nullable()
1417
+ };
1418
+ var FeedbackListRequestSchema = import_zod8.z.object({
1419
+ ...visitor,
1420
+ q: import_zod8.z.string().trim().max(200).optional(),
1421
+ sort: import_zod8.z.enum(["top", "new", "trending"]).default("top"),
1422
+ status: import_zod8.z.enum(FEEDBACK_STATUSES).optional(),
1423
+ /** "open" = not released or declined. */
1424
+ filter: import_zod8.z.enum(["open", "all", "mine", "following"]).default("open"),
1425
+ productArea: import_zod8.z.string().trim().max(60).optional(),
1426
+ page: import_zod8.z.number().int().min(1).max(100).default(1)
1427
+ });
1428
+ var FeedbackVisitorSchema = import_zod8.z.object(visitor);
1429
+ var SubmitFeedbackSchema = import_zod8.z.object({
1430
+ ...visitor,
1431
+ title: import_zod8.z.string().trim().min(3, "Give your idea a short title").max(MAX_FEEDBACK_TITLE),
1432
+ description: import_zod8.z.string().trim().max(MAX_FEEDBACK_DESCRIPTION).default(""),
1433
+ productArea: import_zod8.z.string().trim().max(60).optional().nullable(),
1434
+ priority: import_zod8.z.enum(FEEDBACK_PRIORITIES).default("nice_to_have"),
1435
+ /** Filed from this Scout conversation (Scout offered it). */
1436
+ conversationId: import_zod8.z.string().min(1).max(64).optional().nullable(),
1437
+ pageUrl: import_zod8.z.string().max(2e3).optional()
1438
+ });
1439
+ var FeedbackVoteSchema = import_zod8.z.object({
1440
+ ...visitor,
1441
+ priority: import_zod8.z.enum(FEEDBACK_PRIORITIES).default("nice_to_have"),
1442
+ note: import_zod8.z.string().trim().max(MAX_FEEDBACK_NOTE).optional(),
1443
+ conversationId: import_zod8.z.string().min(1).max(64).optional().nullable()
1444
+ });
1445
+ var FeedbackFollowSchema = import_zod8.z.object({ ...visitor, follow: import_zod8.z.boolean() });
1446
+ var FeedbackCommentSchema = import_zod8.z.object({ ...visitor, body: import_zod8.z.string().trim().min(1).max(MAX_FEEDBACK_COMMENT) });
1447
+ var FeedbackSimilarSchema = import_zod8.z.object({ ...visitor, title: import_zod8.z.string().trim().min(3).max(MAX_FEEDBACK_TITLE) });
1448
+ var FeedbackUpdatesReadSchema = import_zod8.z.object({ ...visitor, ids: import_zod8.z.array(import_zod8.z.string().min(1).max(64)).max(100).optional() });
1449
+
1450
+ // src/capture.ts
1451
+ var import_zod9 = require("zod");
1452
+ var AutocaptureSettingsSchema = import_zod9.z.object({ pageviews: import_zod9.z.boolean(), pageLeave: import_zod9.z.boolean(), clicks: import_zod9.z.boolean(), rageClicks: import_zod9.z.boolean(), heatmaps: import_zod9.z.boolean(), mouseMovement: import_zod9.z.boolean(), appLifecycle: import_zod9.z.boolean() }).partial();
1453
+ var ErrorTrackingSettingsSchema = import_zod9.z.object({ enabled: import_zod9.z.boolean() }).partial();
1454
+ var ReplaySettingsSchema = import_zod9.z.object({
1455
+ enabled: import_zod9.z.boolean(),
1456
+ sampleRate: import_zod9.z.number().int().min(0).max(100),
1457
+ recordConsole: import_zod9.z.boolean(),
1458
+ recordNetwork: import_zod9.z.boolean(),
1459
+ recordNetworkPayloads: import_zod9.z.boolean(),
1460
+ maskAllText: import_zod9.z.boolean(),
1461
+ blockSelectors: import_zod9.z.array(import_zod9.z.string().min(1).max(200)).max(50),
1462
+ retentionDays: import_zod9.z.number().int().min(1).max(365)
1101
1463
  }).partial();
1102
1464
  var DEFAULT_CAPTURE_SETTINGS = {
1103
- autocapture: { pageviews: true, pageLeave: true, clicks: true, rageClicks: true, heatmaps: true, mouseMovement: true },
1465
+ autocapture: { pageviews: true, pageLeave: true, clicks: true, rageClicks: true, heatmaps: true, mouseMovement: true, appLifecycle: true },
1104
1466
  errorTracking: { enabled: true },
1105
1467
  replay: { enabled: false, sampleRate: 100, recordConsole: true, recordNetwork: true, recordNetworkPayloads: false, maskAllText: false, blockSelectors: [], retentionDays: 30 }
1106
1468
  };
@@ -1118,18 +1480,18 @@ function resolveCaptureSettings(settings) {
1118
1480
  };
1119
1481
  }
1120
1482
  var HEATMAP_VIEWPORTS = { mobile: [0, 767], tablet: [768, 1279], desktop: [1280, 1e5] };
1121
- var ReplayChunkSchema = import_zod7.z.object({
1122
- sessionId: import_zod7.z.string().min(1).max(128),
1123
- windowId: import_zod7.z.string().min(1).max(64),
1124
- seq: import_zod7.z.number().int().min(0).max(1e6),
1125
- anonymousId: import_zod7.z.string().min(1).max(128),
1126
- userId: import_zod7.z.string().max(256).optional().nullable(),
1483
+ var ReplayChunkSchema = import_zod9.z.object({
1484
+ sessionId: import_zod9.z.string().min(1).max(128),
1485
+ windowId: import_zod9.z.string().min(1).max(64),
1486
+ seq: import_zod9.z.number().int().min(0).max(1e6),
1487
+ anonymousId: import_zod9.z.string().min(1).max(128),
1488
+ userId: import_zod9.z.string().max(256).optional().nullable(),
1127
1489
  /** rrweb `eventWithTime` objects, in order. */
1128
- events: import_zod7.z.array(import_zod7.z.object({ type: import_zod7.z.number().int(), timestamp: import_zod7.z.number() }).passthrough()).min(1).max(5e4),
1129
- url: import_zod7.z.string().max(2e3).optional(),
1130
- device: import_zod7.z.object({ type: import_zod7.z.string().max(20), browser: import_zod7.z.string().max(40).optional(), os: import_zod7.z.string().max(40).optional() }).optional(),
1131
- viewport: import_zod7.z.object({ width: import_zod7.z.number().int().min(0).max(1e5), height: import_zod7.z.number().int().min(0).max(1e5) }).optional(),
1132
- sdk: import_zod7.z.object({ name: import_zod7.z.string().max(60), version: import_zod7.z.string().max(30) }).optional()
1490
+ events: import_zod9.z.array(import_zod9.z.object({ type: import_zod9.z.number().int(), timestamp: import_zod9.z.number() }).passthrough()).min(1).max(5e4),
1491
+ url: import_zod9.z.string().max(2e3).optional(),
1492
+ device: import_zod9.z.object({ type: import_zod9.z.string().max(20), browser: import_zod9.z.string().max(40).optional(), os: import_zod9.z.string().max(40).optional() }).optional(),
1493
+ viewport: import_zod9.z.object({ width: import_zod9.z.number().int().min(0).max(1e5), height: import_zod9.z.number().int().min(0).max(1e5) }).optional(),
1494
+ sdk: import_zod9.z.object({ name: import_zod9.z.string().max(60), version: import_zod9.z.string().max(30) }).optional()
1133
1495
  });
1134
1496
  var REPLAY_MAX_COMPRESSED_BYTES = 2 * 1024 * 1024;
1135
1497
  var REPLAY_MAX_RAW_BYTES = 16 * 1024 * 1024;
@@ -1313,8 +1675,8 @@ var GUIDE_TEMPLATES = [
1313
1675
  }
1314
1676
  }
1315
1677
  ];
1316
- function templateConfig(id) {
1317
- const t = GUIDE_TEMPLATES.find((x) => x.id === id);
1678
+ function templateConfig(id2) {
1679
+ const t = GUIDE_TEMPLATES.find((x) => x.id === id2);
1318
1680
  if (!t) return null;
1319
1681
  return { template: t, config: GuideConfigSchema.parse(t.config) };
1320
1682
  }
@@ -1374,19 +1736,19 @@ function parseStart(v) {
1374
1736
  if (!m || !m[0]) return 0;
1375
1737
  return Math.min(Number(m[1] ?? 0) * 3600 + Number(m[2] ?? 0) * 60 + Number(m[3] ?? 0), 86400);
1376
1738
  }
1377
- function youtube(id, start) {
1378
- if (!YOUTUBE_ID.test(id)) return null;
1739
+ function youtube(id2, start) {
1740
+ if (!YOUTUBE_ID.test(id2)) return null;
1379
1741
  return {
1380
1742
  provider: "youtube",
1381
- src: `https://www.youtube-nocookie.com/embed/${id}${start ? `?start=${start}` : ""}`,
1382
- watchUrl: `https://www.youtube.com/watch?v=${id}${start ? `&t=${start}s` : ""}`,
1743
+ src: `https://www.youtube-nocookie.com/embed/${id2}${start ? `?start=${start}` : ""}`,
1744
+ watchUrl: `https://www.youtube.com/watch?v=${id2}${start ? `&t=${start}s` : ""}`,
1383
1745
  title: "YouTube video"
1384
1746
  };
1385
1747
  }
1386
- function vimeo(id, hash) {
1387
- if (!VIMEO_ID.test(id) || hash !== null && !VIMEO_HASH.test(hash)) return null;
1748
+ function vimeo(id2, hash) {
1749
+ if (!VIMEO_ID.test(id2) || hash !== null && !VIMEO_HASH.test(hash)) return null;
1388
1750
  const h = hash ? hash.toLowerCase() : null;
1389
- return { provider: "vimeo", src: `https://player.vimeo.com/video/${id}${h ? `?h=${h}` : ""}`, watchUrl: `https://vimeo.com/${id}${h ? `/${h}` : ""}`, title: "Vimeo video" };
1751
+ return { provider: "vimeo", src: `https://player.vimeo.com/video/${id2}${h ? `?h=${h}` : ""}`, watchUrl: `https://vimeo.com/${id2}${h ? `/${h}` : ""}`, title: "Vimeo video" };
1390
1752
  }
1391
1753
  function toEmbedUrl(input) {
1392
1754
  const u = parseUrl(input);
@@ -1412,16 +1774,16 @@ function toEmbedUrl(input) {
1412
1774
  return parts[0] === "video" && parts.length === 2 ? vimeo(parts[1], u.searchParams.get("h")) : null;
1413
1775
  case "loom.com":
1414
1776
  if ((parts[0] === "share" || parts[0] === "embed") && parts.length === 2 && LOOM_ID.test(parts[1])) {
1415
- const id = parts[1].toLowerCase();
1416
- return { provider: "loom", src: `https://www.loom.com/embed/${id}`, watchUrl: `https://www.loom.com/share/${id}`, title: "Loom video" };
1777
+ const id2 = parts[1].toLowerCase();
1778
+ return { provider: "loom", src: `https://www.loom.com/embed/${id2}`, watchUrl: `https://www.loom.com/share/${id2}`, title: "Loom video" };
1417
1779
  }
1418
1780
  return null;
1419
1781
  default: {
1420
- let id;
1421
- if (host === "fast.wistia.net" || host === "fast.wistia.com") id = parts[0] === "embed" && parts[1] === "iframe" && parts.length === 3 ? parts[2] : void 0;
1422
- else if (host === "wi.st" || host === "wistia.com" || /^[a-z0-9-]+\.wistia\.com$/.test(host)) id = parts[0] === "medias" && parts.length === 2 ? parts[1] : void 0;
1423
- if (!id || !WISTIA_ID.test(id)) return null;
1424
- return { provider: "wistia", src: `https://fast.wistia.net/embed/iframe/${id}`, watchUrl: `https://fast.wistia.net/embed/iframe/${id}`, title: "Wistia video" };
1782
+ let id2;
1783
+ if (host === "fast.wistia.net" || host === "fast.wistia.com") id2 = parts[0] === "embed" && parts[1] === "iframe" && parts.length === 3 ? parts[2] : void 0;
1784
+ else if (host === "wi.st" || host === "wistia.com" || /^[a-z0-9-]+\.wistia\.com$/.test(host)) id2 = parts[0] === "medias" && parts.length === 2 ? parts[1] : void 0;
1785
+ if (!id2 || !WISTIA_ID.test(id2)) return null;
1786
+ return { provider: "wistia", src: `https://fast.wistia.net/embed/iframe/${id2}`, watchUrl: `https://fast.wistia.net/embed/iframe/${id2}`, title: "Wistia video" };
1425
1787
  }
1426
1788
  }
1427
1789
  }
@@ -1452,7 +1814,7 @@ var MAX_COLLECTION_DEPTH = 3;
1452
1814
  function matchesAudiences(required, member) {
1453
1815
  if (!required || required.length === 0) return true;
1454
1816
  if (!member) return false;
1455
- const has2 = member instanceof Set ? (id) => member.has(id) : (id) => member.includes(id);
1817
+ const has2 = member instanceof Set ? (id2) => member.has(id2) : (id2) => member.includes(id2);
1456
1818
  return required.some(has2);
1457
1819
  }
1458
1820
  function resourceCenterSections(collections, articles, member) {
@@ -1506,7 +1868,7 @@ function servedArticleAudiences(audienceIds, visibility) {
1506
1868
  return visibility === "identified" && audienceIds.length === 0 ? [LOGGED_IN_AUDIENCE] : [...audienceIds];
1507
1869
  }
1508
1870
  function visitorAudiences(audienceIds, identified) {
1509
- const ids = audienceIds.filter((id) => id !== LOGGED_IN_AUDIENCE);
1871
+ const ids = audienceIds.filter((id2) => id2 !== LOGGED_IN_AUDIENCE);
1510
1872
  return identified ? [...ids, LOGGED_IN_AUDIENCE] : ids;
1511
1873
  }
1512
1874
  function visibleArticleIds(collections, articles, member) {
@@ -1542,9 +1904,35 @@ function matchesHelpQuery(text, query) {
1542
1904
  const have = words(hay);
1543
1905
  return terms.every((t) => have.some((w) => w.startsWith(t) || t.length > 3 && t.endsWith("s") && w.startsWith(t.slice(0, -1))));
1544
1906
  }
1907
+ var RC_MODULE_IDS = ["announcements", "search", "checklists", "guides", "articles", "links", "faqs"];
1908
+ var RC_MODULE_LABELS = {
1909
+ announcements: "What's new",
1910
+ search: "Search",
1911
+ checklists: "Checklists",
1912
+ guides: "Guides & tours",
1913
+ articles: "Articles",
1914
+ links: "Links",
1915
+ faqs: "FAQs"
1916
+ };
1917
+ function orderedModules(modules) {
1918
+ const known = (modules ?? []).filter((m, i, all) => RC_MODULE_IDS.includes(m.id) && all.findIndex((x) => x.id === m.id) === i);
1919
+ const missing = RC_MODULE_IDS.filter((id2) => !known.some((m) => m.id === id2)).map((id2) => ({ id: id2, enabled: true }));
1920
+ return [...known, ...missing];
1921
+ }
1922
+ function visibleAnnouncements(items, member, now = Date.now()) {
1923
+ return (items ?? []).filter((a) => {
1924
+ const t = Date.parse(a.publishedAt);
1925
+ return !Number.isNaN(t) && t <= now && matchesAudiences(a.audienceIds, member);
1926
+ }).sort((a, b) => Date.parse(b.publishedAt) - Date.parse(a.publishedAt));
1927
+ }
1928
+ function unreadAnnouncements(items, lastSeenAt) {
1929
+ const seen = lastSeenAt ? Date.parse(lastSeenAt) : NaN;
1930
+ if (Number.isNaN(seen)) return items.length;
1931
+ return items.filter((a) => Date.parse(a.publishedAt) > seen).length;
1932
+ }
1545
1933
 
1546
1934
  // src/howto.ts
1547
- var import_zod8 = require("zod");
1935
+ var import_zod10 = require("zod");
1548
1936
 
1549
1937
  // src/howto-limits.ts
1550
1938
  var CAPTURE_PARAM = "guidely_capture";
@@ -1553,36 +1941,36 @@ var CAPTURE_SCREENSHOT_MAX_BYTES = 8 * 1024 * 1024;
1553
1941
  // src/howto.ts
1554
1942
  var HOWTO_STEP_KINDS = ["action", "text", "heading", "tip", "alert"];
1555
1943
  var HOWTO_ACTIONS = ["click", "type", "select", "navigate"];
1556
- var NormalizedRectSchema = import_zod8.z.object({
1557
- x: import_zod8.z.number().min(0).max(1),
1558
- y: import_zod8.z.number().min(0).max(1),
1559
- width: import_zod8.z.number().min(0).max(1),
1560
- height: import_zod8.z.number().min(0).max(1)
1944
+ var NormalizedRectSchema = import_zod10.z.object({
1945
+ x: import_zod10.z.number().min(0).max(1),
1946
+ y: import_zod10.z.number().min(0).max(1),
1947
+ width: import_zod10.z.number().min(0).max(1),
1948
+ height: import_zod10.z.number().min(0).max(1)
1561
1949
  });
1562
- var CapturedElementSchema = import_zod8.z.object({
1950
+ var CapturedElementSchema = import_zod10.z.object({
1563
1951
  /** Visible name: aria-label, associated label, text, placeholder, alt or title. */
1564
- label: import_zod8.z.string().max(200).default(""),
1952
+ label: import_zod10.z.string().max(200).default(""),
1565
1953
  /** button, link, tab, menuitem, checkbox, radio, field, dropdown, option, element… */
1566
- role: import_zod8.z.string().max(40).default("element"),
1567
- tag: import_zod8.z.string().max(40).default("")
1954
+ role: import_zod10.z.string().max(40).default("element"),
1955
+ tag: import_zod10.z.string().max(40).default("")
1568
1956
  });
1569
- var CaptureStepSchema = import_zod8.z.object({
1957
+ var CaptureStepSchema = import_zod10.z.object({
1570
1958
  /** Random id from the SDK; a retried upload with the same id is stored once. */
1571
- clientId: import_zod8.z.string().min(1).max(64),
1572
- action: import_zod8.z.enum(HOWTO_ACTIONS),
1573
- url: import_zod8.z.string().max(2e3),
1574
- pageTitle: import_zod8.z.string().max(300).default(""),
1959
+ clientId: import_zod10.z.string().min(1).max(64),
1960
+ action: import_zod10.z.enum(HOWTO_ACTIONS),
1961
+ url: import_zod10.z.string().max(2e3),
1962
+ pageTitle: import_zod10.z.string().max(300).default(""),
1575
1963
  element: CapturedElementSchema.optional(),
1576
1964
  /** Typed text or chosen option; absent when it was sensitive (`valueRedacted`). */
1577
- value: import_zod8.z.string().max(200).optional(),
1578
- valueRedacted: import_zod8.z.boolean().default(false),
1965
+ value: import_zod10.z.string().max(200).optional(),
1966
+ valueRedacted: import_zod10.z.boolean().default(false),
1579
1967
  /** Selectors for the element, so the step can later become an interactive tour step. */
1580
- selectors: import_zod8.z.array(SelectorStrategySchema).max(10).default([]),
1968
+ selectors: import_zod10.z.array(SelectorStrategySchema).max(10).default([]),
1581
1969
  /** Where the element sits in the screenshot. */
1582
1970
  highlight: NormalizedRectSchema.optional(),
1583
1971
  /** Number of regions the SDK blurred in the screenshot before upload. */
1584
- redactions: import_zod8.z.number().int().min(0).max(1e3).default(0),
1585
- occurredAt: import_zod8.z.string().datetime().optional()
1972
+ redactions: import_zod10.z.number().int().min(0).max(1e3).default(0),
1973
+ occurredAt: import_zod10.z.string().datetime().optional()
1586
1974
  });
1587
1975
  function quoted(s) {
1588
1976
  const t = (s ?? "").replace(/\s+/g, " ").trim();
@@ -1653,12 +2041,12 @@ function hostAndPath(url) {
1653
2041
  return url.slice(0, 80);
1654
2042
  }
1655
2043
  }
1656
- var NormalizedPointSchema = import_zod8.z.object({ x: import_zod8.z.number().min(0).max(1), y: import_zod8.z.number().min(0).max(1) });
2044
+ var NormalizedPointSchema = import_zod10.z.object({ x: import_zod10.z.number().min(0).max(1), y: import_zod10.z.number().min(0).max(1) });
1657
2045
  var ANNOTATION_COLORS = ["brand", "red", "amber", "green", "black", "white"];
1658
- var HowToAnnotationSchema = import_zod8.z.discriminatedUnion("type", [
1659
- import_zod8.z.object({ id: import_zod8.z.string().min(1).max(32), type: import_zod8.z.literal("arrow"), from: NormalizedPointSchema, to: NormalizedPointSchema, color: import_zod8.z.enum(ANNOTATION_COLORS).default("brand") }),
1660
- import_zod8.z.object({ id: import_zod8.z.string().min(1).max(32), type: import_zod8.z.literal("text"), at: NormalizedPointSchema, text: import_zod8.z.string().trim().min(1).max(120), color: import_zod8.z.enum(ANNOTATION_COLORS).default("brand") }),
1661
- import_zod8.z.object({ id: import_zod8.z.string().min(1).max(32), type: import_zod8.z.literal("box"), rect: NormalizedRectSchema, color: import_zod8.z.enum(ANNOTATION_COLORS).default("brand") })
2046
+ var HowToAnnotationSchema = import_zod10.z.discriminatedUnion("type", [
2047
+ import_zod10.z.object({ id: import_zod10.z.string().min(1).max(32), type: import_zod10.z.literal("arrow"), from: NormalizedPointSchema, to: NormalizedPointSchema, color: import_zod10.z.enum(ANNOTATION_COLORS).default("brand") }),
2048
+ import_zod10.z.object({ id: import_zod10.z.string().min(1).max(32), type: import_zod10.z.literal("text"), at: NormalizedPointSchema, text: import_zod10.z.string().trim().min(1).max(120), color: import_zod10.z.enum(ANNOTATION_COLORS).default("brand") }),
2049
+ import_zod10.z.object({ id: import_zod10.z.string().min(1).max(32), type: import_zod10.z.literal("box"), rect: NormalizedRectSchema, color: import_zod10.z.enum(ANNOTATION_COLORS).default("brand") })
1662
2050
  ]);
1663
2051
  var MAX_ANNOTATIONS = 30;
1664
2052
 
@@ -1686,21 +2074,1128 @@ function pageLabel(path) {
1686
2074
  }
1687
2075
  function firstNameFromTraits(traits) {
1688
2076
  if (!traits) return null;
1689
- const pick = (v) => typeof v === "string" ? v.trim() : "";
1690
- const first = pick(traits.firstName) || pick(traits.first_name) || pick(traits.firstname) || pick(traits.name).split(/\s+/)[0] || "";
2077
+ const pick2 = (v) => typeof v === "string" ? v.trim() : "";
2078
+ const first = pick2(traits.firstName) || pick2(traits.first_name) || pick2(traits.firstname) || pick2(traits.name).split(/\s+/)[0] || "";
1691
2079
  if (!first || first.length > 40 || first.includes("@") || !/\p{L}/u.test(first)) return null;
1692
2080
  return first;
1693
2081
  }
1694
2082
 
2083
+ // src/tagging.ts
2084
+ var SNAPSHOT_LIMITS = { classes: 8, className: 60, attrs: 6, attrValue: 100, ancestors: 5, hosts: 3, tag: 40, id: 80 };
2085
+ var SNAPSHOT_ATTRS = ["role", "name", "type", "aria-label", "title", "alt", "for", "href"];
2086
+ var NOISY_DATA_ATTR = /^data-(state|v-|react|radix|headlessui|svelte|orientation|highlighted|focus|key|index|side|align|disabled|selected|active|open|rbd|dnd|sveltekit|guidely-(mask|ignore|block))/i;
2087
+ var DEFAULT_FEATURE_ATTRIBUTE = "data-guidely-feature";
2088
+ var FEATURE_ATTRIBUTE_PATTERN = /^data-[a-z0-9][a-z0-9_.-]{0,60}$/;
2089
+ function str(v, max) {
2090
+ return typeof v === "string" && v ? v.slice(0, max) : void 0;
2091
+ }
2092
+ function cleanNode(raw) {
2093
+ if (!raw || typeof raw !== "object") return null;
2094
+ const r = raw;
2095
+ const t = str(r.t, SNAPSHOT_LIMITS.tag)?.toLowerCase();
2096
+ if (!t || !/^[a-z][a-z0-9-]*$/.test(t)) return null;
2097
+ const node = { t };
2098
+ const id2 = str(r.id, SNAPSHOT_LIMITS.id);
2099
+ if (id2) node.id = id2;
2100
+ if (Array.isArray(r.c)) {
2101
+ const c = r.c.filter((x) => typeof x === "string" && !!x && x.length <= SNAPSHOT_LIMITS.className && !/\s/.test(x)).slice(0, SNAPSHOT_LIMITS.classes);
2102
+ if (c.length) node.c = c;
2103
+ }
2104
+ if (r.a && typeof r.a === "object" && !Array.isArray(r.a)) {
2105
+ const a = {};
2106
+ for (const [k, v] of Object.entries(r.a)) {
2107
+ if (Object.keys(a).length >= SNAPSHOT_LIMITS.attrs) break;
2108
+ const key = k.toLowerCase();
2109
+ if (typeof v !== "string" || !(key.startsWith("data-") || SNAPSHOT_ATTRS.includes(key)) || key === "value" || key.length > 60) continue;
2110
+ a[key] = v.slice(0, SNAPSHOT_LIMITS.attrValue);
2111
+ }
2112
+ if (Object.keys(a).length) node.a = a;
2113
+ }
2114
+ if (typeof r.n === "number" && Number.isInteger(r.n) && r.n >= 1 && r.n <= 1e4) node.n = r.n;
2115
+ return node;
2116
+ }
2117
+ function normalizeSnapshot(raw) {
2118
+ const el = cleanNode(raw);
2119
+ if (!el) return null;
2120
+ const r = raw;
2121
+ const out = el;
2122
+ if (Array.isArray(r.p)) {
2123
+ const p = r.p.slice(0, SNAPSHOT_LIMITS.ancestors).map(cleanNode);
2124
+ const cut = p.indexOf(null);
2125
+ const list = cut === -1 ? p : p.slice(0, cut);
2126
+ if (list.length) out.p = list;
2127
+ }
2128
+ if (Array.isArray(r.h)) {
2129
+ const h = r.h.slice(0, SNAPSHOT_LIMITS.hosts).map(cleanNode).filter((x) => !!x);
2130
+ if (h.length) out.h = h;
2131
+ }
2132
+ return out;
2133
+ }
2134
+ function stableStringify(v) {
2135
+ if (Array.isArray(v)) return `[${v.map(stableStringify).join(",")}]`;
2136
+ if (v && typeof v === "object") {
2137
+ const o = v;
2138
+ return `{${Object.keys(o).filter((k) => o[k] !== void 0).sort().map((k) => `${JSON.stringify(k)}:${stableStringify(o[k])}`).join(",")}}`;
2139
+ }
2140
+ return JSON.stringify(v ?? null);
2141
+ }
2142
+ var SelectorSyntaxError = class extends Error {
2143
+ };
2144
+ var IDENT_START = /[A-Za-z_\u00a0-\uffff-]/;
2145
+ var IDENT_CHAR = /[A-Za-z0-9_\u00a0-\uffff-]/;
2146
+ function parseCssSelector(input) {
2147
+ const s = input.trim();
2148
+ if (!s) throw new SelectorSyntaxError("Empty selector");
2149
+ if (s.length > 1e3) throw new SelectorSyntaxError("Selector is too long");
2150
+ let i = 0;
2151
+ const peek = () => s[i];
2152
+ const eof = () => i >= s.length;
2153
+ const fail = (msg) => {
2154
+ throw new SelectorSyntaxError(`${msg} at position ${i + 1}`);
2155
+ };
2156
+ const ws = () => {
2157
+ let any = false;
2158
+ while (!eof() && /\s/.test(s[i])) {
2159
+ i++;
2160
+ any = true;
2161
+ }
2162
+ return any;
2163
+ };
2164
+ const escape = () => {
2165
+ i++;
2166
+ const hex = /^[0-9a-fA-F]{1,6}/.exec(s.slice(i));
2167
+ if (hex) {
2168
+ i += hex[0].length;
2169
+ if (s[i] === " ") i++;
2170
+ return String.fromCodePoint(parseInt(hex[0], 16));
2171
+ }
2172
+ if (eof()) fail("Unfinished escape");
2173
+ return s[i++];
2174
+ };
2175
+ const ident = () => {
2176
+ let out = "";
2177
+ if (s[i] === "\\") out += escape();
2178
+ else if (!eof() && IDENT_START.test(s[i])) out += s[i++];
2179
+ else fail("Expected a name");
2180
+ while (!eof()) {
2181
+ if (s[i] === "\\") out += escape();
2182
+ else if (IDENT_CHAR.test(s[i])) out += s[i++];
2183
+ else break;
2184
+ }
2185
+ return out;
2186
+ };
2187
+ const quoted2 = () => {
2188
+ const q = s[i++];
2189
+ let out = "";
2190
+ while (!eof() && s[i] !== q) {
2191
+ if (s[i] === "\\") out += escape();
2192
+ else out += s[i++];
2193
+ }
2194
+ if (eof()) fail("Unterminated string");
2195
+ i++;
2196
+ return out;
2197
+ };
2198
+ const compound = () => {
2199
+ const c = { classes: [], attrs: [] };
2200
+ let any = false;
2201
+ if (peek() === "*") {
2202
+ i++;
2203
+ any = true;
2204
+ } else if (!eof() && (IDENT_START.test(peek()) || peek() === "\\")) {
2205
+ c.tag = ident().toLowerCase();
2206
+ any = true;
2207
+ }
2208
+ for (; ; ) {
2209
+ const ch = peek();
2210
+ if (ch === "#") {
2211
+ i++;
2212
+ c.id = ident();
2213
+ } else if (ch === ".") {
2214
+ i++;
2215
+ c.classes.push(ident());
2216
+ } else if (ch === "[") {
2217
+ i++;
2218
+ ws();
2219
+ const name = ident().toLowerCase();
2220
+ ws();
2221
+ let op = "exists";
2222
+ let value;
2223
+ let insensitive = false;
2224
+ if (peek() !== "]") {
2225
+ const m = /^(=|\^=|\$=|\*=|~=|\|=)/.exec(s.slice(i));
2226
+ if (!m) fail("Unsupported attribute operator");
2227
+ op = m[1];
2228
+ i += m[1].length;
2229
+ ws();
2230
+ value = peek() === '"' || peek() === "'" ? quoted2() : ident();
2231
+ ws();
2232
+ if (peek() === "i" || peek() === "I") {
2233
+ i++;
2234
+ insensitive = true;
2235
+ ws();
2236
+ } else if (peek() === "s" || peek() === "S") {
2237
+ i++;
2238
+ ws();
2239
+ }
2240
+ }
2241
+ if (peek() !== "]") fail("Expected ]");
2242
+ i++;
2243
+ c.attrs.push({ name, op, ...value !== void 0 ? { value } : {}, ...insensitive ? { insensitive } : {} });
2244
+ } else if (ch === ":") {
2245
+ i++;
2246
+ if (peek() === ":") fail("Pseudo-elements are not supported");
2247
+ const name = ident().toLowerCase();
2248
+ if (name === "first-of-type") c.nth = { a: 0, b: 1 };
2249
+ else if (name === "nth-of-type") {
2250
+ if (peek() !== "(") fail("Expected (");
2251
+ i++;
2252
+ ws();
2253
+ const m = /^(odd|even|\d+)/i.exec(s.slice(i));
2254
+ if (!m) fail("Only :nth-of-type(n), odd or even are supported");
2255
+ i += m[0].length;
2256
+ ws();
2257
+ if (peek() !== ")") fail("Expected )");
2258
+ i++;
2259
+ const v = m[0].toLowerCase();
2260
+ c.nth = v === "odd" ? { a: 2, b: 1 } : v === "even" ? { a: 2, b: 0 } : { a: 0, b: Number(v) };
2261
+ } else fail(`Unsupported pseudo-class :${name}`);
2262
+ } else break;
2263
+ any = true;
2264
+ }
2265
+ return any ? c : null;
2266
+ };
2267
+ const list = [];
2268
+ for (; ; ) {
2269
+ ws();
2270
+ const sel = { compounds: [], combinators: [] };
2271
+ const first = compound();
2272
+ if (!first) fail("Expected a selector");
2273
+ sel.compounds.push(first);
2274
+ for (; ; ) {
2275
+ const hadWs = ws();
2276
+ if (eof() || peek() === ",") break;
2277
+ let comb = " ";
2278
+ if (s.startsWith(">>>", i)) {
2279
+ comb = ">>>";
2280
+ i += 3;
2281
+ ws();
2282
+ } else if (peek() === ">") {
2283
+ comb = ">";
2284
+ i++;
2285
+ ws();
2286
+ } else if (peek() === "+" || peek() === "~") fail("Sibling combinators are not supported");
2287
+ else if (!hadWs) fail("Unexpected character");
2288
+ const next = compound();
2289
+ if (!next) fail("Expected a selector after the combinator");
2290
+ sel.compounds.push(next);
2291
+ sel.combinators.push(comb);
2292
+ }
2293
+ list.push(sel);
2294
+ if (eof()) break;
2295
+ i++;
2296
+ }
2297
+ return list;
2298
+ }
2299
+ function cssSelectorError(selector) {
2300
+ try {
2301
+ parseCssSelector(selector);
2302
+ return null;
2303
+ } catch (e) {
2304
+ return e instanceof Error ? e.message : "Invalid selector";
2305
+ }
2306
+ }
2307
+ function attrMatches(test, node) {
2308
+ let actual;
2309
+ if (test.name === "id") actual = node.id;
2310
+ else if (test.name === "class") actual = node.c?.join(" ");
2311
+ else actual = node.a?.[test.name];
2312
+ if (actual === void 0) return false;
2313
+ if (test.op === "exists") return true;
2314
+ let v = test.value ?? "";
2315
+ if (test.insensitive) {
2316
+ actual = actual.toLowerCase();
2317
+ v = v.toLowerCase();
2318
+ }
2319
+ switch (test.op) {
2320
+ case "=":
2321
+ return actual === v;
2322
+ case "^=":
2323
+ return !!v && actual.startsWith(v);
2324
+ case "$=":
2325
+ return !!v && actual.endsWith(v);
2326
+ case "*=":
2327
+ return !!v && actual.includes(v);
2328
+ case "~=":
2329
+ return !!v && actual.split(/\s+/).includes(v);
2330
+ case "|=":
2331
+ return actual === v || actual.startsWith(`${v}-`);
2332
+ default:
2333
+ return false;
2334
+ }
2335
+ }
2336
+ function compoundMatches(c, node) {
2337
+ if (c.tag && c.tag !== node.t) return false;
2338
+ if (c.id !== void 0 && node.id !== c.id) return false;
2339
+ for (const cls of c.classes) if (!node.c?.includes(cls)) return false;
2340
+ for (const a of c.attrs) if (!attrMatches(a, node)) return false;
2341
+ if (c.nth) {
2342
+ if (!node.n) return false;
2343
+ const { a, b } = c.nth;
2344
+ if (a === 0 ? node.n !== b : (node.n - b) % a !== 0 || (node.n - b) / a < 0) return false;
2345
+ }
2346
+ return true;
2347
+ }
2348
+ function chainMatches(compounds, combinators, nodes, ci = compounds.length - 1, ni = 0) {
2349
+ if (!compoundMatches(compounds[ci], nodes[ni])) return false;
2350
+ if (ci === 0) return true;
2351
+ const comb = combinators[ci - 1];
2352
+ if (comb === ">") return ni + 1 < nodes.length && chainMatches(compounds, combinators, nodes, ci - 1, ni + 1);
2353
+ for (let k = ni + 1; k < nodes.length; k++) if (chainMatches(compounds, combinators, nodes, ci - 1, k)) return true;
2354
+ return false;
2355
+ }
2356
+ function complexMatches(sel, snap) {
2357
+ const segments = [{ compounds: [sel.compounds[0]], combinators: [] }];
2358
+ sel.combinators.forEach((comb, k) => {
2359
+ const next = sel.compounds[k + 1];
2360
+ if (comb === ">>>") segments.push({ compounds: [next], combinators: [] });
2361
+ else {
2362
+ const seg = segments[segments.length - 1];
2363
+ seg.compounds.push(next);
2364
+ seg.combinators.push(comb);
2365
+ }
2366
+ });
2367
+ const last = segments.pop();
2368
+ const nodes = [snap, ...snap.p ?? []];
2369
+ if (!chainMatches(last.compounds, last.combinators, nodes)) return false;
2370
+ const hosts = snap.h ?? [];
2371
+ let from = 0;
2372
+ for (let k = segments.length - 1; k >= 0; k--) {
2373
+ const target = segments[k].compounds[segments[k].compounds.length - 1];
2374
+ let found = -1;
2375
+ for (let j = from; j < hosts.length; j++) {
2376
+ if (compoundMatches(target, hosts[j])) {
2377
+ found = j;
2378
+ break;
2379
+ }
2380
+ }
2381
+ if (found === -1) return false;
2382
+ from = found + 1;
2383
+ }
2384
+ return true;
2385
+ }
2386
+ var parsedCache = /* @__PURE__ */ new Map();
2387
+ function matchCssSelector(selector, snap) {
2388
+ let list;
2389
+ if (typeof selector === "string") {
2390
+ if (!parsedCache.has(selector)) {
2391
+ if (parsedCache.size > 500) parsedCache.clear();
2392
+ try {
2393
+ parsedCache.set(selector, parseCssSelector(selector));
2394
+ } catch {
2395
+ parsedCache.set(selector, null);
2396
+ }
2397
+ }
2398
+ list = parsedCache.get(selector);
2399
+ } else list = selector;
2400
+ return !!list && list.some((sel) => complexMatches(sel, snap));
2401
+ }
2402
+ function nodeOfCompound(c) {
2403
+ const node = { t: c.tag ?? "*" };
2404
+ if (c.id) node.id = c.id;
2405
+ if (c.classes.length) node.c = c.classes.slice(0, SNAPSHOT_LIMITS.classes);
2406
+ const a = {};
2407
+ for (const t of c.attrs) if (t.op === "=" && t.value !== void 0) a[t.name] = t.value;
2408
+ if (Object.keys(a).length) node.a = a;
2409
+ if (c.nth && c.nth.a === 0) node.n = c.nth.b;
2410
+ return node;
2411
+ }
2412
+ function snapshotFromSelector(selector, tag) {
2413
+ let list;
2414
+ try {
2415
+ list = parseCssSelector(selector);
2416
+ } catch {
2417
+ return null;
2418
+ }
2419
+ if (list.length !== 1) return null;
2420
+ const sel = list[0];
2421
+ const segments = [[sel.compounds[0]]];
2422
+ sel.combinators.forEach((comb, k) => {
2423
+ if (comb === ">>>") segments.push([sel.compounds[k + 1]]);
2424
+ else segments[segments.length - 1].push(sel.compounds[k + 1]);
2425
+ });
2426
+ const own = segments.pop();
2427
+ const el = nodeOfCompound(own[own.length - 1]);
2428
+ if (el.t === "*" && tag && /^[a-z][a-z0-9-]*$/i.test(tag)) el.t = tag.toLowerCase();
2429
+ const snap = el;
2430
+ const p = own.slice(0, -1).reverse().map(nodeOfCompound);
2431
+ if (p.length) snap.p = p.slice(0, SNAPSHOT_LIMITS.ancestors);
2432
+ const h = segments.reverse().map((seg) => nodeOfCompound(seg[seg.length - 1]));
2433
+ if (h.length) snap.h = h.slice(0, SNAPSHOT_LIMITS.hosts);
2434
+ return snap;
2435
+ }
2436
+ var PAGE_RULE_LIMITS = { rules: 20, value: 500, query: 5 };
2437
+ var escapeRe = (s) => s.replace(/[.+?^${}()|[\]\\*]/g, "\\$&");
2438
+ function globToRegex(pattern) {
2439
+ let out = "";
2440
+ for (let k = 0; k < pattern.length; k++) {
2441
+ const ch = pattern[k];
2442
+ if (ch === "*") {
2443
+ if (pattern[k + 1] === "*") {
2444
+ out += ".*";
2445
+ k++;
2446
+ } else out += "[^/]*";
2447
+ } else if (ch === ":" && (k === 0 || pattern[k - 1] === "/") && /[A-Za-z_]/.test(pattern[k + 1] ?? "")) {
2448
+ let j = k + 1;
2449
+ while (j < pattern.length && /[\w]/.test(pattern[j])) j++;
2450
+ out += "[^/]+";
2451
+ k = j - 1;
2452
+ } else out += escapeRe(ch);
2453
+ }
2454
+ return out;
2455
+ }
2456
+ function pagePattern(raw) {
2457
+ let p = raw.trim();
2458
+ const query = [];
2459
+ const hash = p.indexOf("#");
2460
+ if (hash !== -1) p = p.slice(0, hash);
2461
+ const q = p.indexOf("?");
2462
+ if (q !== -1) {
2463
+ for (const part of p.slice(q + 1).split("&")) {
2464
+ if (!part) continue;
2465
+ const eq = part.indexOf("=");
2466
+ const name = decodeSafe(eq === -1 ? part : part.slice(0, eq));
2467
+ const value = eq === -1 ? void 0 : decodeSafe(part.slice(eq + 1));
2468
+ if (!name) continue;
2469
+ query.push(value === void 0 || value === "*" ? { name, op: "exists" } : { name, op: "equals", value });
2470
+ }
2471
+ p = p.slice(0, q);
2472
+ }
2473
+ let target = "path";
2474
+ if (p.startsWith("//*")) p = p.slice(3);
2475
+ let prefix = "";
2476
+ const abs = /^(https?:)?\/\/([^/]+)(.*)$/i.exec(p);
2477
+ if (abs) {
2478
+ target = "url";
2479
+ prefix = `https?://${globToRegex(abs[2].toLowerCase())}`;
2480
+ p = abs[3] || "/";
2481
+ }
2482
+ if (!p.startsWith("/")) p = `/${p}`;
2483
+ const body = p.length > 1 && p.endsWith("/") ? p.slice(0, -1) : p;
2484
+ const src = body === "/" ? "/?" : `${globToRegex(body)}/?`;
2485
+ return { source: `^${prefix}${src}$`, target, query: query.slice(0, PAGE_RULE_LIMITS.query) };
2486
+ }
2487
+ function decodeSafe(s) {
2488
+ try {
2489
+ return decodeURIComponent(s.replace(/\+/g, " "));
2490
+ } catch {
2491
+ return s;
2492
+ }
2493
+ }
2494
+ function queryConditionRegex(c) {
2495
+ const name = escapeRe(c.name);
2496
+ switch (c.op) {
2497
+ case "equals":
2498
+ return `[?&]${name}=${escapeRe(encodeLoose(c.value ?? ""))}(&|#|$)`;
2499
+ case "contains":
2500
+ return `[?&]${name}=[^&#]*${escapeRe(encodeLoose(c.value ?? ""))}`;
2501
+ default:
2502
+ return `[?&]${name}(=|&|#|$)`;
2503
+ }
2504
+ }
2505
+ function encodeLoose(v) {
2506
+ return encodeURIComponent(v).replace(/%2F/gi, "/").replace(/%3A/gi, ":").replace(/%2C/gi, ",").replace(/%40/gi, "@");
2507
+ }
2508
+ function pathOnly(ctx) {
2509
+ if (ctx.path) return ctx.path.split("?")[0] || "/";
2510
+ if (!ctx.url) return null;
2511
+ try {
2512
+ return new URL(ctx.url, "http://x.invalid").pathname;
2513
+ } catch {
2514
+ return null;
2515
+ }
2516
+ }
2517
+ function regexOrNull(source) {
2518
+ try {
2519
+ return new RegExp(source, "i");
2520
+ } catch {
2521
+ return null;
2522
+ }
2523
+ }
2524
+ function pageRuleMatches(rule, ctx) {
2525
+ const path = pathOnly(ctx);
2526
+ if (rule.type === "title") {
2527
+ const t = (ctx.title ?? "").toLowerCase();
2528
+ const v = rule.value.toLowerCase();
2529
+ return !!t && (rule.op === "contains" ? t.includes(v) : t === v);
2530
+ }
2531
+ if (rule.type === "regex") {
2532
+ const re2 = regexOrNull(rule.value);
2533
+ return !!re2 && path !== null && re2.test(path);
2534
+ }
2535
+ const pat = pagePattern(rule.value);
2536
+ const re = regexOrNull(pat.source);
2537
+ if (!re) return false;
2538
+ let subject = path;
2539
+ if (pat.target === "url") {
2540
+ if (!ctx.url) return false;
2541
+ subject = ctx.url.split(/[?#]/)[0];
2542
+ }
2543
+ if (subject === null || !re.test(subject)) return false;
2544
+ const conds = [...pat.query, ...rule.query ?? []];
2545
+ for (const c of conds) {
2546
+ const hit = !!ctx.url && new RegExp(queryConditionRegex(c), "i").test(ctx.url);
2547
+ if (c.op === "absent" ? hit : !hit) return false;
2548
+ }
2549
+ return true;
2550
+ }
2551
+ function pageRulesMatch(rules, ctx) {
2552
+ const include = rules.filter((r) => !r.exclude);
2553
+ if (!include.length || !include.some((r) => pageRuleMatches(r, ctx))) return false;
2554
+ return !rules.some((r) => r.exclude && pageRuleMatches(r, ctx));
2555
+ }
2556
+ function pageRuleError(rule) {
2557
+ const v = rule.value?.trim();
2558
+ if (!v) return "A rule needs a value";
2559
+ if (v.length > PAGE_RULE_LIMITS.value) return "The rule is too long";
2560
+ if (rule.type === "regex") {
2561
+ if (!regexOrNull(v)) return `"${v}" is not a valid regular expression`;
2562
+ if (/\(\?[<=!]/.test(v) || /\\[1-9]/.test(v)) return "Look-arounds and back-references are not supported";
2563
+ }
2564
+ if (rule.type === "url" && !regexOrNull(pagePattern(v).source)) return `"${v}" is not a valid URL rule`;
2565
+ for (const q of rule.query ?? []) if (!/^[A-Za-z0-9_.\-[\]]{1,60}$/.test(q.name)) return `"${q.name}" is not a query parameter name`;
2566
+ return null;
2567
+ }
2568
+ var FEATURE_RULE_LIMITS = { rules: 20, value: 1e3 };
2569
+ function globMatch(pattern, value) {
2570
+ const re = new RegExp(`^${pattern.split("*").map(escapeRe).join(".*")}$`, "s");
2571
+ return re.test(value);
2572
+ }
2573
+ function featureRuleMatchesClick(rule, click, css) {
2574
+ if (!rule.selector && !rule.text && !rule.tag && !rule.href) return false;
2575
+ if (rule.selector) {
2576
+ const sel = click.selector ?? "";
2577
+ const v = rule.selector.value;
2578
+ const ok = rule.selector.op === "css" ? css(v) : rule.selector.op === "exact" ? sel === v : rule.selector.op === "prefix" ? sel.startsWith(v) : rule.selector.op === "contains" ? sel.includes(v) : globMatch(v, sel);
2579
+ if (!ok) return false;
2580
+ }
2581
+ if (rule.text) {
2582
+ const t = (click.text ?? "").toLowerCase();
2583
+ const v = rule.text.value.toLowerCase();
2584
+ if (rule.text.op === "contains" ? !t.includes(v) : t !== v) return false;
2585
+ }
2586
+ if (rule.tag && (click.tag ?? "").toLowerCase() !== rule.tag.toLowerCase()) return false;
2587
+ if (rule.href) {
2588
+ const h = click.href ?? "";
2589
+ const v = rule.href.value;
2590
+ if (rule.href.op === "equals" ? h !== v : rule.href.op === "prefix" ? !h.startsWith(v) : !h.includes(v)) return false;
2591
+ }
2592
+ if (rule.platform && (click.platform ?? "web") !== rule.platform) return false;
2593
+ return true;
2594
+ }
2595
+ function featureRuleError(rule) {
2596
+ if (!rule.selector && !rule.text && !rule.tag && !rule.href) return "A feature rule needs a selector, text, tag or link condition";
2597
+ if (rule.selector) {
2598
+ const v = rule.selector.value?.trim();
2599
+ if (!v) return "The selector is empty";
2600
+ if (v.length > FEATURE_RULE_LIMITS.value) return "The selector is too long";
2601
+ if (rule.selector.op === "css") {
2602
+ const err = cssSelectorError(v);
2603
+ if (err) return `Unsupported CSS selector: ${err}`;
2604
+ }
2605
+ }
2606
+ if (rule.text && !rule.text.value.trim()) return "The text condition is empty";
2607
+ if (rule.href && !rule.href.value.trim()) return "The link condition is empty";
2608
+ if (rule.tag && !/^[a-z][a-z0-9-]{0,40}$/i.test(rule.tag)) return "The tag is not an element name";
2609
+ if (rule.page?.pattern) return pageRuleError({ type: "url", value: rule.page.pattern });
2610
+ return null;
2611
+ }
2612
+ function featureCssSelectors(rules) {
2613
+ const out = [];
2614
+ for (const r of rules) {
2615
+ if (r.exclude || !r.selector) continue;
2616
+ if ((r.selector.op === "css" || r.selector.op === "exact") && !cssSelectorError(r.selector.value)) out.push(r.selector.value);
2617
+ }
2618
+ return out;
2619
+ }
2620
+ var TAG_PROPERTY_LIMITS = { perTag: 10, total: 50, value: 100 };
2621
+ function propertyAttributeAllowed(name) {
2622
+ const n = name.toLowerCase();
2623
+ if (n === "value" || n.startsWith("on") || n === "style" || n === "srcdoc") return false;
2624
+ return /^[a-z][a-z0-9_:.-]{0,60}$/.test(n);
2625
+ }
2626
+
2627
+ // src/snippet.ts
2628
+ var SCRIPT_STUB_METHODS = [
2629
+ "identify",
2630
+ "track",
2631
+ "page",
2632
+ "reset",
2633
+ "setAccount",
2634
+ "updateTraits",
2635
+ "setConsent",
2636
+ "setLocale",
2637
+ "startGuide",
2638
+ "stopGuide",
2639
+ "dismissGuide",
2640
+ "openMessenger",
2641
+ "closeMessenger",
2642
+ "showNewMessage",
2643
+ "openResourceCenter",
2644
+ "closeResourceCenter",
2645
+ "openChecklist",
2646
+ "closeChecklist",
2647
+ "completeChecklistTask",
2648
+ "openComplaint",
2649
+ "openIdeas",
2650
+ "captureException",
2651
+ "agentConversation",
2652
+ "trackAgentTurn",
2653
+ "on"
2654
+ ];
2655
+ var SCRIPT_STUB = `!function(w){if(w.Guidely)return;var g=w.Guidely={_q:[]},c=g._c={};function q(o,k){o[k]=function(){g._q.push([o===c?1:0,k,[].slice.call(arguments)])}}q(g,"init");"${SCRIPT_STUB_METHODS.join(" ")}".split(" ").forEach(function(k){q(c,k)});c.isFeatureEnabled=function(k,f){return!!f};c.getFeatureValue=function(k,f){return f};g.get=function(){return c}}(window);`;
2656
+ function scriptSnippet(scriptUrl, initOptions) {
2657
+ return `<script>
2658
+ ${SCRIPT_STUB}
2659
+ Guidely.init(${initOptions});
2660
+ </script>
2661
+ <script src="${scriptUrl}" async></script>`;
2662
+ }
2663
+
2664
+ // src/localization.ts
2665
+ var DEFAULT_LOCALE = "en";
2666
+ var COMMON_LOCALES = [
2667
+ { code: "en", name: "English" },
2668
+ { code: "en-GB", name: "English (UK)" },
2669
+ { code: "fr", name: "French" },
2670
+ { code: "fr-CA", name: "French (Canada)" },
2671
+ { code: "de", name: "German" },
2672
+ { code: "es", name: "Spanish" },
2673
+ { code: "es-MX", name: "Spanish (Mexico)" },
2674
+ { code: "it", name: "Italian" },
2675
+ { code: "pt", name: "Portuguese" },
2676
+ { code: "pt-BR", name: "Portuguese (Brazil)" },
2677
+ { code: "nl", name: "Dutch" },
2678
+ { code: "sv", name: "Swedish" },
2679
+ { code: "da", name: "Danish" },
2680
+ { code: "nb", name: "Norwegian" },
2681
+ { code: "fi", name: "Finnish" },
2682
+ { code: "pl", name: "Polish" },
2683
+ { code: "cs", name: "Czech" },
2684
+ { code: "tr", name: "Turkish" },
2685
+ { code: "ru", name: "Russian" },
2686
+ { code: "uk", name: "Ukrainian" },
2687
+ { code: "ar", name: "Arabic" },
2688
+ { code: "he", name: "Hebrew" },
2689
+ { code: "hi", name: "Hindi" },
2690
+ { code: "ja", name: "Japanese" },
2691
+ { code: "ko", name: "Korean" },
2692
+ { code: "zh-Hans", name: "Chinese (Simplified)" },
2693
+ { code: "zh-Hant", name: "Chinese (Traditional)" },
2694
+ { code: "id", name: "Indonesian" },
2695
+ { code: "th", name: "Thai" },
2696
+ { code: "vi", name: "Vietnamese" }
2697
+ ];
2698
+ function localeName(code) {
2699
+ const exact = COMMON_LOCALES.find((l) => l.code.toLowerCase() === code.toLowerCase());
2700
+ if (exact) return exact.name;
2701
+ const base = COMMON_LOCALES.find((l) => l.code.toLowerCase() === baseLanguage(code));
2702
+ return base ? `${base.name} (${code})` : code;
2703
+ }
2704
+ function normalizeLocale(input) {
2705
+ if (typeof input !== "string") return "";
2706
+ const parts = input.trim().replace(/_/g, "-").split("-").filter(Boolean);
2707
+ if (!parts.length || !/^[a-zA-Z]{2,3}$/.test(parts[0])) return "";
2708
+ return parts.slice(0, 3).map((p, i) => i === 0 ? p.toLowerCase() : p.length === 4 ? p[0].toUpperCase() + p.slice(1).toLowerCase() : p.length === 2 ? p.toUpperCase() : p).join("-");
2709
+ }
2710
+ function baseLanguage(locale) {
2711
+ return normalizeLocale(locale).split("-")[0] ?? "";
2712
+ }
2713
+ function resolveLocale(requested, available, defaultLocale = DEFAULT_LOCALE) {
2714
+ const def = normalizeLocale(defaultLocale) || DEFAULT_LOCALE;
2715
+ const avail = available.map(normalizeLocale).filter(Boolean);
2716
+ const all = [def, ...avail.filter((a) => a.toLowerCase() !== def.toLowerCase())];
2717
+ for (const raw of requested) {
2718
+ const want = normalizeLocale(raw);
2719
+ if (!want) continue;
2720
+ const exact = all.find((a) => a.toLowerCase() === want.toLowerCase());
2721
+ if (exact) return exact;
2722
+ const base = baseLanguage(want);
2723
+ const sameBase = all.find((a) => a.toLowerCase() === base) ?? all.find((a) => baseLanguage(a) === base);
2724
+ if (sameBase) return sameBase;
2725
+ }
2726
+ return def;
2727
+ }
2728
+ function visitorLocales(explicit, traits, platform = []) {
2729
+ const out = [];
2730
+ const push = (v) => {
2731
+ const n = normalizeLocale(v);
2732
+ if (n && !out.includes(n)) out.push(n);
2733
+ };
2734
+ push(explicit);
2735
+ push(traits?.language);
2736
+ push(traits?.locale);
2737
+ for (const p of platform) push(p);
2738
+ return out;
2739
+ }
2740
+ function guideTextEntries(config) {
2741
+ const out = [];
2742
+ const add = (key, source, kind, label) => {
2743
+ if (source && source.trim()) out.push({ key, source, kind, label });
2744
+ };
2745
+ config.steps.forEach((s, i) => {
2746
+ const at = `Step ${i + 1}`;
2747
+ add(`steps.${s.id}.title`, s.title, "text", `${at} \xB7 Title`);
2748
+ add(`steps.${s.id}.body`, s.body, "html", `${at} \xB7 Body`);
2749
+ add(`steps.${s.id}.customHtml`, s.customHtml, "html", `${at} \xB7 Custom HTML`);
2750
+ add(`steps.${s.id}.imageAlt`, s.imageAlt, "text", `${at} \xB7 Image description`);
2751
+ s.buttons.forEach((b) => add(`steps.${s.id}.buttons.${b.id}.label`, b.label, "text", `${at} \xB7 Button \u201C${b.label}\u201D`));
2752
+ });
2753
+ const c = config.checklist;
2754
+ if (c) {
2755
+ add("checklist.launcherLabel", c.launcherLabel, "text", "Checklist \xB7 Launcher label");
2756
+ add("checklist.completionTitle", c.completionTitle, "text", "Checklist \xB7 Completion title");
2757
+ add("checklist.completionBody", c.completionBody, "html", "Checklist \xB7 Completion message");
2758
+ c.tasks.forEach((t, i) => {
2759
+ add(`checklist.tasks.${t.id}.title`, t.title, "text", `Task ${i + 1} \xB7 Title`);
2760
+ add(`checklist.tasks.${t.id}.description`, t.description, "html", `Task ${i + 1} \xB7 Description`);
2761
+ });
2762
+ }
2763
+ const sv = config.survey;
2764
+ if (sv) {
2765
+ sv.questions.forEach((q, i) => {
2766
+ const at = `Question ${i + 1}`;
2767
+ add(`survey.questions.${q.id}.title`, q.title, "text", `${at} \xB7 Question`);
2768
+ add(`survey.questions.${q.id}.description`, q.description, "text", `${at} \xB7 Description`);
2769
+ add(`survey.questions.${q.id}.placeholder`, q.placeholder, "text", `${at} \xB7 Placeholder`);
2770
+ add(`survey.questions.${q.id}.lowLabel`, q.lowLabel, "text", `${at} \xB7 Low label`);
2771
+ add(`survey.questions.${q.id}.highLabel`, q.highLabel, "text", `${at} \xB7 High label`);
2772
+ q.options.forEach((o) => add(`survey.questions.${q.id}.options.${o.id}.label`, o.label, "text", `${at} \xB7 Option \u201C${o.label}\u201D`));
2773
+ });
2774
+ add("survey.thankYouTitle", sv.thankYouTitle, "text", "Survey \xB7 Thank-you title");
2775
+ add("survey.thankYouBody", sv.thankYouBody, "html", "Survey \xB7 Thank-you message");
2776
+ }
2777
+ return out;
2778
+ }
2779
+ function guideLocales(config) {
2780
+ const t = config.localization?.translations ?? {};
2781
+ return Object.keys(t).filter((l) => Object.values(t[l] ?? {}).some((v) => typeof v === "string" && v.trim() !== ""));
2782
+ }
2783
+ function pick(map, key, fallback) {
2784
+ const v = map?.[key];
2785
+ return typeof v === "string" && v.trim() !== "" ? v : fallback;
2786
+ }
2787
+ function applyGuideTranslations(config, map) {
2788
+ if (!map || !Object.keys(map).length) return config;
2789
+ return {
2790
+ ...config,
2791
+ steps: config.steps.map((s) => ({
2792
+ ...s,
2793
+ title: pick(map, `steps.${s.id}.title`, s.title),
2794
+ body: pick(map, `steps.${s.id}.body`, s.body),
2795
+ customHtml: pick(map, `steps.${s.id}.customHtml`, s.customHtml),
2796
+ imageAlt: pick(map, `steps.${s.id}.imageAlt`, s.imageAlt),
2797
+ buttons: s.buttons.map((b) => ({ ...b, label: pick(map, `steps.${s.id}.buttons.${b.id}.label`, b.label) }))
2798
+ })),
2799
+ checklist: config.checklist ? {
2800
+ ...config.checklist,
2801
+ launcherLabel: pick(map, "checklist.launcherLabel", config.checklist.launcherLabel),
2802
+ completionTitle: pick(map, "checklist.completionTitle", config.checklist.completionTitle),
2803
+ completionBody: pick(map, "checklist.completionBody", config.checklist.completionBody),
2804
+ tasks: config.checklist.tasks.map((t) => ({ ...t, title: pick(map, `checklist.tasks.${t.id}.title`, t.title), description: pick(map, `checklist.tasks.${t.id}.description`, t.description) }))
2805
+ } : config.checklist,
2806
+ survey: config.survey ? {
2807
+ ...config.survey,
2808
+ thankYouTitle: pick(map, "survey.thankYouTitle", config.survey.thankYouTitle),
2809
+ thankYouBody: pick(map, "survey.thankYouBody", config.survey.thankYouBody),
2810
+ questions: config.survey.questions.map((q) => ({
2811
+ ...q,
2812
+ title: pick(map, `survey.questions.${q.id}.title`, q.title),
2813
+ description: pick(map, `survey.questions.${q.id}.description`, q.description),
2814
+ placeholder: pick(map, `survey.questions.${q.id}.placeholder`, q.placeholder),
2815
+ lowLabel: pick(map, `survey.questions.${q.id}.lowLabel`, q.lowLabel),
2816
+ highLabel: pick(map, `survey.questions.${q.id}.highLabel`, q.highLabel),
2817
+ options: q.options.map((o) => ({ ...o, label: pick(map, `survey.questions.${q.id}.options.${o.id}.label`, o.label) }))
2818
+ }))
2819
+ } : config.survey
2820
+ };
2821
+ }
2822
+ function localizeGuide(guide, requested, defaultLocale = DEFAULT_LOCALE) {
2823
+ const translations = guide.config.localization?.translations ?? {};
2824
+ const locale = resolveLocale(requested, guideLocales(guide.config), defaultLocale);
2825
+ const key = Object.keys(translations).find((l) => normalizeLocale(l).toLowerCase() === locale.toLowerCase());
2826
+ if (!key) return { ...guide, locale };
2827
+ return { ...guide, locale, config: applyGuideTranslations(guide.config, translations[key]) };
2828
+ }
2829
+ function translationCoverage(entries, map, locale) {
2830
+ const keys = new Set(entries.map((e) => e.key));
2831
+ const missing = entries.filter((e) => !pick(map, e.key, void 0)).map((e) => e.key);
2832
+ const stale = Object.keys(map ?? {}).filter((k) => !keys.has(k) && (map?.[k] ?? "").trim() !== "");
2833
+ return { locale, total: entries.length, translated: entries.length - missing.length, missing, stale };
2834
+ }
2835
+ function resourceCenterTextEntries(rc) {
2836
+ const out = [];
2837
+ const add = (key, source, kind, label) => {
2838
+ if (source && source.trim()) out.push({ key, source, kind, label });
2839
+ };
2840
+ add("title", rc.title, "text", "Title");
2841
+ add("launcher.label", rc.launcher?.label, "text", "Launcher label");
2842
+ rc.collections.forEach((c) => {
2843
+ add(`collections.${c.id}.name`, c.name, "text", `Collection \u201C${c.name}\u201D`);
2844
+ add(`collections.${c.id}.description`, c.description, "text", `Collection \u201C${c.name}\u201D \xB7 Description`);
2845
+ });
2846
+ rc.links.forEach((l) => add(`links.${l.id}.label`, l.label, "text", `Link \u201C${l.label}\u201D`));
2847
+ rc.faqs.forEach((f, i) => {
2848
+ add(`faqs.${f.id}.question`, f.question, "text", `FAQ ${i + 1} \xB7 Question`);
2849
+ add(`faqs.${f.id}.answer`, f.answer, "html", `FAQ ${i + 1} \xB7 Answer`);
2850
+ });
2851
+ return out;
2852
+ }
2853
+ function articleTextEntries(a) {
2854
+ const out = [];
2855
+ if (a.title.trim()) out.push({ key: "title", source: a.title, kind: "text", label: "Title" });
2856
+ if (a.summary?.trim()) out.push({ key: "summary", source: a.summary, kind: "text", label: "Summary" });
2857
+ if (a.body?.trim()) out.push({ key: "body", source: a.body, kind: "html", label: "Body" });
2858
+ return out;
2859
+ }
2860
+ function resourceCenterLocales(rc) {
2861
+ const set = new Set(Object.keys(rc.translations ?? {}));
2862
+ for (const a of rc.articles) for (const l of Object.keys(a.translations ?? {})) set.add(l);
2863
+ for (const a of rc.announcements ?? []) for (const l of Object.keys(a.translations ?? {})) set.add(l);
2864
+ return [...set];
2865
+ }
2866
+ function translationFor(map, locale) {
2867
+ if (!map) return void 0;
2868
+ const key = Object.keys(map).find((l) => normalizeLocale(l).toLowerCase() === locale.toLowerCase());
2869
+ return key ? map[key] : void 0;
2870
+ }
2871
+ function localizeArticle(a, locale) {
2872
+ const t = translationFor(a.translations, locale);
2873
+ if (!t) return a;
2874
+ const body = t.body?.trim() ? t.body : a.body;
2875
+ return { ...a, title: t.title?.trim() ? t.title : a.title, summary: t.summary?.trim() ? t.summary : a.summary, body, ...t.bodyOmitted ? { bodyOmitted: true } : {} };
2876
+ }
2877
+ function localizeAnnouncement(a, locale) {
2878
+ const t = translationFor(a.translations, locale);
2879
+ if (!t) return a;
2880
+ return { ...a, title: t.title?.trim() ? t.title : a.title, body: t.body?.trim() ? t.body : a.body };
2881
+ }
2882
+ function localizeResourceCenter(rc, requested, defaultLocale = DEFAULT_LOCALE) {
2883
+ const locale = resolveLocale(requested, resourceCenterLocales(rc), defaultLocale);
2884
+ if (locale.toLowerCase() === normalizeLocale(defaultLocale).toLowerCase()) return { ...rc, locale };
2885
+ const map = translationFor(rc.translations, locale);
2886
+ return {
2887
+ ...rc,
2888
+ locale,
2889
+ title: pick(map, "title", rc.title),
2890
+ launcher: { ...rc.launcher, label: pick(map, "launcher.label", rc.launcher.label) },
2891
+ collections: rc.collections.map((c) => ({ ...c, name: pick(map, `collections.${c.id}.name`, c.name), description: pick(map, `collections.${c.id}.description`, c.description) })),
2892
+ links: rc.links.map((l) => ({ ...l, label: pick(map, `links.${l.id}.label`, l.label) })),
2893
+ faqs: rc.faqs.map((f) => ({ ...f, question: pick(map, `faqs.${f.id}.question`, f.question), answer: pick(map, `faqs.${f.id}.answer`, f.answer) })),
2894
+ articles: rc.articles.map((a) => localizeArticle(a, locale)),
2895
+ announcements: rc.announcements?.map((a) => localizeAnnouncement(a, locale))
2896
+ };
2897
+ }
2898
+
2899
+ // src/guide-experiments.ts
2900
+ var CONTROL_VARIANT_ID = "control";
2901
+ var GUIDE_EXPERIMENT_STATUSES = ["draft", "running", "completed"];
2902
+ var GUIDE_EXPERIMENT_GOALS = ["guide_completed", "event", "page_visit", "click_text"];
2903
+ var GUIDE_EXPERIMENT_GOAL_LABELS = {
2904
+ guide_completed: "Completes the guide",
2905
+ event: "Tracks an event",
2906
+ page_visit: "Visits a page",
2907
+ click_text: "Clicks an element with text"
2908
+ };
2909
+ function experimentSalt(experimentId) {
2910
+ return `gx:${experimentId}`;
2911
+ }
2912
+ function variantRanges(variants) {
2913
+ let at = 0;
2914
+ return variants.map((v) => {
2915
+ const from = at;
2916
+ at = Math.min(100, at + Math.max(0, Math.round(v.weight)));
2917
+ return { id: v.id, from, to: at };
2918
+ });
2919
+ }
2920
+ function assignGuideVariant(variants, experimentId, subject) {
2921
+ const bucket = rolloutBucket(subject, experimentSalt(experimentId));
2922
+ return variantRanges(variants).find((r) => bucket >= r.from && bucket < r.to)?.id ?? null;
2923
+ }
2924
+ function experimentBucketRules(salt, from, to) {
2925
+ return [
2926
+ { id: "experiment-from", field: "experiment.bucket", key: salt, op: "gte", value: from },
2927
+ { id: "experiment-to", field: "experiment.bucket", key: salt, op: "lt", value: to }
2928
+ ];
2929
+ }
2930
+ function withExperimentBucket(targeting, salt, from, to) {
2931
+ return { id: "experiment", op: "and", rules: [...experimentBucketRules(salt, from, to), targeting] };
2932
+ }
2933
+ function variantProblems(variants) {
2934
+ const problems = [];
2935
+ if (variants.length < 2) problems.push("An A/B test needs at least two variants.");
2936
+ if (variants.length > 5) problems.push("An A/B test can have at most five variants.");
2937
+ const guides = variants.filter((v) => v.guideId);
2938
+ if (guides.length === 0) problems.push("At least one variant must show a guide.");
2939
+ if (variants.filter((v) => !v.guideId).length > 1) problems.push("Only one variant can be the control group (no guide).");
2940
+ if (new Set(guides.map((v) => v.guideId)).size !== guides.length) problems.push("Each variant needs its own guide.");
2941
+ if (new Set(variants.map((v) => v.id)).size !== variants.length) problems.push("Variant ids must be unique.");
2942
+ if (variants.some((v) => !Number.isInteger(v.weight) || v.weight < 1)) problems.push("Every variant needs a whole-number share of at least 1%.");
2943
+ const total = variants.reduce((s, v) => s + v.weight, 0);
2944
+ if (total !== 100) problems.push(`Traffic shares must add up to 100% (now ${total}%).`);
2945
+ return problems;
2946
+ }
2947
+ function evenWeights(n) {
2948
+ if (n <= 0) return [];
2949
+ const base = Math.floor(100 / n);
2950
+ return Array.from({ length: n }, (_, i) => base + (i < 100 - base * n ? 1 : 0));
2951
+ }
2952
+
2953
+ // src/custom-css.ts
2954
+ var MAX_CUSTOM_CSS = 2e4;
2955
+ var BLOCKED_AT_RULES = /^@(import|charset|namespace|document|-moz-document)\b/i;
2956
+ var ALLOWED_AT_RULES = /^@(media|supports|container|layer|keyframes|-webkit-keyframes|font-face)\b/i;
2957
+ function splitBlocks(css) {
2958
+ const out = [];
2959
+ let i = 0;
2960
+ const n = css.length;
2961
+ while (i < n) {
2962
+ let prelude = "";
2963
+ let quote = null;
2964
+ while (i < n) {
2965
+ const ch = css[i];
2966
+ if (quote) {
2967
+ prelude += ch;
2968
+ if (ch === "\\") prelude += css[++i] ?? "";
2969
+ else if (ch === quote) quote = null;
2970
+ } else if (ch === '"' || ch === "'") {
2971
+ quote = ch;
2972
+ prelude += ch;
2973
+ } else if (ch === "{") break;
2974
+ else if (ch === ";") {
2975
+ prelude = "";
2976
+ } else if (ch === "}") {
2977
+ prelude = "";
2978
+ } else prelude += ch;
2979
+ i++;
2980
+ }
2981
+ if (i >= n) break;
2982
+ i++;
2983
+ let depth = 1;
2984
+ let body = "";
2985
+ quote = null;
2986
+ while (i < n && depth > 0) {
2987
+ const ch = css[i];
2988
+ if (quote) {
2989
+ body += ch;
2990
+ if (ch === "\\") body += css[++i] ?? "";
2991
+ else if (ch === quote) quote = null;
2992
+ } else if (ch === '"' || ch === "'") {
2993
+ quote = ch;
2994
+ body += ch;
2995
+ } else if (ch === "{") {
2996
+ depth++;
2997
+ body += ch;
2998
+ } else if (ch === "}") {
2999
+ depth--;
3000
+ if (depth > 0) body += ch;
3001
+ } else body += ch;
3002
+ i++;
3003
+ }
3004
+ out.push({ prelude: prelude.trim(), body });
3005
+ }
3006
+ return out;
3007
+ }
3008
+ function splitSelectors(list) {
3009
+ const out = [];
3010
+ let depth = 0;
3011
+ let cur = "";
3012
+ for (const ch of list) {
3013
+ if (ch === "(" || ch === "[") depth++;
3014
+ else if (ch === ")" || ch === "]") depth = Math.max(0, depth - 1);
3015
+ if (ch === "," && depth === 0) {
3016
+ out.push(cur.trim());
3017
+ cur = "";
3018
+ } else cur += ch;
3019
+ }
3020
+ if (cur.trim()) out.push(cur.trim());
3021
+ return out;
3022
+ }
3023
+ function safeUrl(raw) {
3024
+ const u = raw.trim().replace(/^['"]|['"]$/g, "").trim();
3025
+ return /^https:\/\//i.test(u) || /^data:image\/(png|jpe?g|gif|webp|svg\+xml)[;,]/i.test(u);
3026
+ }
3027
+ function cleanDeclarations(body) {
3028
+ return body.replace(/url\(([^)]*)\)/gi, (m, inner) => safeUrl(inner) ? m : "none").replace(/expression\s*\(/gi, "(").replace(/javascript\s*:/gi, "").replace(/(^|[;{\s])(-moz-binding|behavior)\s*:[^;]*;?/gi, "$1").replace(/[{}]/g, "").trim();
3029
+ }
3030
+ function sanitizeCustomCss(input) {
3031
+ if (!input) return "";
3032
+ let css = String(input).slice(0, MAX_CUSTOM_CSS);
3033
+ css = css.replace(/\/\*[\s\S]*?\*\//g, "").replace(/<(script|style)\b[^>]*>[\s\S]*?<\/\1\s*>/gi, "").replace(/<\/?[a-z!][^>]*>/gi, "").replace(/</g, "");
3034
+ return render(splitBlocks(css), 0);
3035
+ }
3036
+ function render(blocks, depth) {
3037
+ const parts = [];
3038
+ for (const b of blocks) {
3039
+ if (!b.prelude) continue;
3040
+ if (b.prelude.startsWith("@")) {
3041
+ if (BLOCKED_AT_RULES.test(b.prelude) || !ALLOWED_AT_RULES.test(b.prelude)) continue;
3042
+ if (/^@(-webkit-)?keyframes|^@font-face/i.test(b.prelude)) {
3043
+ const inner = /^@font-face/i.test(b.prelude) ? cleanDeclarations(b.body) : splitBlocks(b.body).map((k) => `${k.prelude}{${cleanDeclarations(k.body)}}`).join("");
3044
+ parts.push(`${b.prelude}{${inner}}`);
3045
+ } else if (depth < 3) parts.push(`${b.prelude}{${render(splitBlocks(b.body), depth + 1)}}`);
3046
+ continue;
3047
+ }
3048
+ const selectors = splitSelectors(b.prelude).filter((s) => !/:host|::slotted|::part/i.test(s));
3049
+ if (!selectors.length) continue;
3050
+ parts.push(`${selectors.join(",")}{${cleanDeclarations(b.body)}}`);
3051
+ }
3052
+ return parts.join("\n");
3053
+ }
3054
+ function scopeCustomCss(css, scope) {
3055
+ return scopeBlocks(splitBlocks(sanitizeCustomCss(css)), scope, 0);
3056
+ }
3057
+ function scopeBlocks(blocks, scope, depth) {
3058
+ const parts = [];
3059
+ for (const b of blocks) {
3060
+ if (b.prelude.startsWith("@")) {
3061
+ if (/^@(-webkit-)?keyframes|^@font-face/i.test(b.prelude)) parts.push(`${b.prelude}{${b.body}}`);
3062
+ else if (depth < 3) parts.push(`${b.prelude}{${scopeBlocks(splitBlocks(b.body), scope, depth + 1)}}`);
3063
+ continue;
3064
+ }
3065
+ const sels = splitSelectors(b.prelude).map((s) => {
3066
+ const self = s.match(/^(:root|html|body|:scope|&)(?![\w-])(.*)$/i);
3067
+ if (self) return `${scope}${self[2] ?? ""}`;
3068
+ return `${scope} ${s}`;
3069
+ });
3070
+ parts.push(`${sels.join(",")}{${b.body}}`);
3071
+ }
3072
+ return parts.join("\n");
3073
+ }
3074
+
3075
+ // src/translation-files.ts
3076
+ function xmlEscape(s) {
3077
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
3078
+ }
3079
+ function xmlUnescape(s) {
3080
+ return s.replace(/<!\[CDATA\[([\s\S]*?)\]\]>/g, (_, c) => c.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")).replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&#(\d+);/g, (_, d) => String.fromCodePoint(Number(d))).replace(/&#x([0-9a-f]+);/gi, (_, h) => String.fromCodePoint(parseInt(h, 16))).replace(/&amp;/g, "&");
3081
+ }
3082
+ function toXliff(units, opts) {
3083
+ const body = units.map(
3084
+ (u) => ` <trans-unit id="${xmlEscape(u.key)}">
3085
+ <source>${xmlEscape(u.source)}</source>
3086
+ <target${u.target ? "" : ' state="needs-translation"'}>${xmlEscape(u.target)}</target>${u.note ? `
3087
+ <note>${xmlEscape(u.note)}</note>` : ""}
3088
+ </trans-unit>`
3089
+ ).join("\n");
3090
+ return `<?xml version="1.0" encoding="UTF-8"?>
3091
+ <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
3092
+ <file original="${xmlEscape(opts.original)}" source-language="${xmlEscape(opts.sourceLocale)}" target-language="${xmlEscape(opts.targetLocale)}" datatype="html">
3093
+ <body>
3094
+ ${body}
3095
+ </body>
3096
+ </file>
3097
+ </xliff>
3098
+ `;
3099
+ }
3100
+ function parseXliff(xml) {
3101
+ const target = xml.match(/target-language="([^"]+)"/)?.[1] ?? xml.match(/\btrgLang="([^"]+)"/)?.[1];
3102
+ const entries = {};
3103
+ for (const m of xml.matchAll(/<(trans-unit|unit)\b[^>]*\bid="([^"]*)"[^>]*>([\s\S]*?)<\/\1>/g)) {
3104
+ const key = xmlUnescape(m[2]);
3105
+ const t = m[3].match(/<target\b[^>]*>([\s\S]*?)<\/target>/);
3106
+ const text = t ? xmlUnescape(t[1]) : "";
3107
+ if (key && text.trim()) entries[key] = text;
3108
+ }
3109
+ return { targetLocale: target ? xmlUnescape(target) : void 0, entries };
3110
+ }
3111
+ function csvCell(s) {
3112
+ return /[",\n\r]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
3113
+ }
3114
+ function toTranslationCsv(units, targetLocale) {
3115
+ const rows = [["key", "context", "source", targetLocale], ...units.map((u) => [u.key, u.note ?? "", u.source, u.target])];
3116
+ return rows.map((r) => r.map(csvCell).join(",")).join("\r\n") + "\r\n";
3117
+ }
3118
+ function parseCsvRows(text) {
3119
+ const rows = [];
3120
+ let row = [];
3121
+ let cell = "";
3122
+ let quoted2 = false;
3123
+ const src = text.replace(/^\uFEFF/, "");
3124
+ for (let i = 0; i < src.length; i++) {
3125
+ const ch = src[i];
3126
+ if (quoted2) {
3127
+ if (ch === '"') {
3128
+ if (src[i + 1] === '"') {
3129
+ cell += '"';
3130
+ i++;
3131
+ } else quoted2 = false;
3132
+ } else cell += ch;
3133
+ } else if (ch === '"') quoted2 = true;
3134
+ else if (ch === ",") {
3135
+ row.push(cell);
3136
+ cell = "";
3137
+ } else if (ch === "\n" || ch === "\r") {
3138
+ if (ch === "\r" && src[i + 1] === "\n") i++;
3139
+ row.push(cell);
3140
+ rows.push(row);
3141
+ row = [];
3142
+ cell = "";
3143
+ } else cell += ch;
3144
+ }
3145
+ if (cell !== "" || row.length) {
3146
+ row.push(cell);
3147
+ rows.push(row);
3148
+ }
3149
+ return rows.filter((r) => r.some((c) => c.trim() !== ""));
3150
+ }
3151
+ function parseTranslationCsv(text) {
3152
+ const [header, ...rows] = parseCsvRows(text);
3153
+ if (!header) return { entries: {} };
3154
+ const names = header.map((h) => h.trim());
3155
+ const lower = names.map((h) => h.toLowerCase());
3156
+ const keyCol = lower.indexOf("key");
3157
+ if (keyCol < 0) return { entries: {} };
3158
+ let targetCol = lower.indexOf("target");
3159
+ if (targetCol < 0) {
3160
+ for (let i = names.length - 1; i >= 0; i--) {
3161
+ if (!["key", "context", "source", "label", "note"].includes(lower[i])) {
3162
+ targetCol = i;
3163
+ break;
3164
+ }
3165
+ }
3166
+ }
3167
+ if (targetCol < 0) return { entries: {} };
3168
+ const entries = {};
3169
+ for (const r of rows) {
3170
+ const key = (r[keyCol] ?? "").trim();
3171
+ const value = r[targetCol] ?? "";
3172
+ if (key && value.trim()) entries[key] = value;
3173
+ }
3174
+ return { targetLocale: lower[targetCol] === "target" ? void 0 : names[targetCol], entries };
3175
+ }
3176
+
1695
3177
  // src/index.ts
1696
3178
  var SDK_API_VERSION = "v1";
1697
- var SHARED_VERSION = "0.9.0";
3179
+ var SHARED_VERSION = "0.11.0";
1698
3180
  // Annotate the CommonJS export names for ESM import in node:
1699
3181
  0 && (module.exports = {
1700
3182
  ADVANCE_ON,
3183
+ AGENT_METADATA_MAX_BYTES,
3184
+ AGENT_METADATA_MAX_KEYS,
3185
+ AGENT_OUTCOMES,
3186
+ AGENT_TOOL_CALLS_PER_TURN,
3187
+ AGENT_TOOL_STATUSES,
3188
+ AGENT_TURNS_PER_BATCH,
3189
+ AGENT_TURN_MAX_TEXT,
3190
+ AGENT_TURN_ROLES,
1701
3191
  ANNOTATION_COLORS,
3192
+ APP_LIFECYCLE_EVENTS,
1702
3193
  ARTICLE_VISIBILITIES,
1703
3194
  AUTOCAPTURE_EVENTS,
3195
+ AgentEventsRequestSchema,
3196
+ AgentMetadataSchema,
3197
+ AgentToolCallSchema,
3198
+ AgentTurnInputSchema,
1704
3199
  AppearanceSchema,
1705
3200
  AuthoringPickSchema,
1706
3201
  AutocaptureSettingsSchema,
@@ -1708,9 +3203,11 @@ var SHARED_VERSION = "0.9.0";
1708
3203
  ButtonSchema,
1709
3204
  CAPTURE_PARAM,
1710
3205
  CAPTURE_SCREENSHOT_MAX_BYTES,
3206
+ COMMON_LOCALES,
1711
3207
  COMPLAINT_EVENTS,
1712
3208
  COMPLAINT_FIELD_TYPES,
1713
3209
  COMPLAINT_STATUSES,
3210
+ CONTROL_VARIANT_ID,
1714
3211
  CaptureStepSchema,
1715
3212
  CapturedElementSchema,
1716
3213
  ChecklistConfigSchema,
@@ -1719,28 +3216,54 @@ var SHARED_VERSION = "0.9.0";
1719
3216
  ConversationLookupSchema,
1720
3217
  ConversationRatingSchema,
1721
3218
  DEFAULT_CAPTURE_SETTINGS,
3219
+ DEFAULT_FEATURE_ATTRIBUTE,
3220
+ DEFAULT_LOCALE,
1722
3221
  DEFAULT_PLATFORMS,
1723
3222
  EMBED_IFRAME_ATTRS,
1724
3223
  EVENT_NAMES,
1725
3224
  ErrorTrackingSettingsSchema,
1726
3225
  EventBatchSchema,
3226
+ FEATURE_ATTRIBUTE_PATTERN,
3227
+ FEATURE_RULE_LIMITS,
3228
+ FEEDBACK_EVENTS,
3229
+ FEEDBACK_PRIORITIES,
3230
+ FEEDBACK_PRIORITY_LABEL,
3231
+ FEEDBACK_PRIORITY_WEIGHT,
3232
+ FEEDBACK_STATUSES,
3233
+ FEEDBACK_STATUS_LABEL,
1727
3234
  FILE_LINK_CLASS,
3235
+ FeedbackCommentSchema,
3236
+ FeedbackFollowSchema,
3237
+ FeedbackListRequestSchema,
3238
+ FeedbackSimilarSchema,
3239
+ FeedbackUpdatesReadSchema,
3240
+ FeedbackVisitorSchema,
3241
+ FeedbackVoteSchema,
1728
3242
  FileComplaintSchema,
1729
3243
  FrequencySchema,
1730
3244
  GUIDELY_ID_ATTRIBUTE,
3245
+ GUIDE_EXPERIMENT_GOALS,
3246
+ GUIDE_EXPERIMENT_GOAL_LABELS,
3247
+ GUIDE_EXPERIMENT_STATUSES,
1731
3248
  GUIDE_KINDS,
1732
3249
  GUIDE_LIFECYCLE_EVENTS,
1733
3250
  GUIDE_STATUSES,
1734
3251
  GUIDE_TEMPLATES,
1735
3252
  GUIDE_VISIBILITIES,
1736
3253
  GuideConfigSchema,
3254
+ GuideLocalizationSchema,
3255
+ GuideScheduleSchema,
1737
3256
  GuideStateUpdateSchema,
3257
+ GuideThrottlingSchema,
1738
3258
  HEATMAP_VIEWPORTS,
1739
3259
  HOWTO_ACTIONS,
1740
3260
  HOWTO_STEP_KINDS,
1741
3261
  HowToAnnotationSchema,
1742
3262
  IdentifyRequestSchema,
3263
+ LOCALE_PATTERN,
1743
3264
  LOGGED_IN_AUDIENCE,
3265
+ LocaleSchema,
3266
+ LocalizationSettingsSchema,
1744
3267
  MAX_ANNOTATIONS,
1745
3268
  MAX_COLLECTION_DEPTH,
1746
3269
  MAX_COMPLAINT_ANSWER_LENGTH,
@@ -1748,6 +3271,11 @@ var SHARED_VERSION = "0.9.0";
1748
3271
  MAX_COMPLAINT_CHOICES,
1749
3272
  MAX_COMPLAINT_FIELDS,
1750
3273
  MAX_COMPLAINT_LENGTH,
3274
+ MAX_CUSTOM_CSS,
3275
+ MAX_FEEDBACK_COMMENT,
3276
+ MAX_FEEDBACK_DESCRIPTION,
3277
+ MAX_FEEDBACK_NOTE,
3278
+ MAX_FEEDBACK_TITLE,
1751
3279
  MAX_MESSAGE_LENGTH,
1752
3280
  MAX_PROPERTY_BYTES,
1753
3281
  MAX_STACK_FRAMES,
@@ -1761,8 +3289,10 @@ var SHARED_VERSION = "0.9.0";
1761
3289
  MESSAGE_AUTHORS,
1762
3290
  MessengerPageRequestSchema,
1763
3291
  NETWORK_PLUGIN,
3292
+ NOISY_DATA_ATTR,
1764
3293
  NormalizedPointSchema,
1765
3294
  NormalizedRectSchema,
3295
+ PAGE_RULE_LIMITS,
1766
3296
  PATH_ID_PATTERN,
1767
3297
  PDF_BLOCK_CLASS,
1768
3298
  PDF_MAX_PAGES,
@@ -1772,6 +3302,8 @@ var SHARED_VERSION = "0.9.0";
1772
3302
  PostMessageSchema,
1773
3303
  ProjectThemeSchema,
1774
3304
  PublishedGuideSchema,
3305
+ RC_MODULE_IDS,
3306
+ RC_MODULE_LABELS,
1775
3307
  REPLAY_MAX_COMPRESSED_BYTES,
1776
3308
  REPLAY_MAX_RAW_BYTES,
1777
3309
  REPLY_TIMES,
@@ -1781,6 +3313,9 @@ var SHARED_VERSION = "0.9.0";
1781
3313
  ReplaySettingsSchema,
1782
3314
  RuleGroupSchema,
1783
3315
  RuleSchema,
3316
+ SCOUT_AGENT_ID,
3317
+ SCRIPT_STUB,
3318
+ SCRIPT_STUB_METHODS,
1784
3319
  SDK_API_VERSION,
1785
3320
  SELECTOR_KINDS,
1786
3321
  SENSITIVE_HEADER_PATTERN,
@@ -1790,30 +3325,46 @@ var SHARED_VERSION = "0.9.0";
1790
3325
  SHARED_VERSION,
1791
3326
  SHOW_ME_CLASS,
1792
3327
  SHOW_ME_HREF_PREFIX,
3328
+ SNAPSHOT_ATTRS,
3329
+ SNAPSHOT_LIMITS,
1793
3330
  SOURCEMAP_MAX_FILES_PER_UPLOAD,
1794
3331
  SOURCEMAP_MAX_FILE_BYTES,
1795
3332
  STATUS_LEVELS,
1796
3333
  STEP_TYPES,
1797
3334
  SURVEY_QUESTION_TYPES,
3335
+ SdkAgentEventsSchema,
1798
3336
  SdkEventSchema,
1799
3337
  SelectorStrategySchema,
3338
+ SelectorSyntaxError,
1800
3339
  StartConversationSchema,
1801
3340
  StepBranchSchema,
1802
3341
  StepSchema,
3342
+ SubmitFeedbackSchema,
1803
3343
  SurveyConfigSchema,
1804
3344
  SurveyQuestionSchema,
1805
3345
  SurveyResponseRequestSchema,
3346
+ TAG_PROPERTY_LIMITS,
1806
3347
  TRIGGER_TYPES,
1807
3348
  TargetSchema,
1808
3349
  TriggerSchema,
1809
3350
  VIDEO_ATTRS,
3351
+ WCAG_AA_LARGE,
3352
+ WCAG_AA_TEXT,
1810
3353
  WS_MAX_MESSAGES_PER_SOCKET,
1811
3354
  WS_MAX_MESSAGE_BYTES,
3355
+ applyGuideTranslations,
3356
+ articleTextEntries,
3357
+ assignGuideVariant,
3358
+ baseLanguage,
1812
3359
  clamp,
1813
3360
  cleanLabel,
1814
3361
  compare,
1815
3362
  compareVersions,
1816
3363
  complaintReference,
3364
+ compoundMatches,
3365
+ contrastIssues,
3366
+ contrastRatio,
3367
+ cssSelectorError,
1817
3368
  defaultGuideConfig,
1818
3369
  defaultStep,
1819
3370
  describeCaptureStep,
@@ -1821,12 +3372,21 @@ var SHARED_VERSION = "0.9.0";
1821
3372
  emptyRuleGroup,
1822
3373
  evaluateRule,
1823
3374
  evaluateRules,
3375
+ evenWeights,
3376
+ experimentBucketRules,
3377
+ experimentSalt,
3378
+ featureCssSelectors,
3379
+ featureRuleError,
3380
+ featureRuleMatchesClick,
3381
+ feedbackReference,
1824
3382
  fingerprintError,
1825
3383
  firstNameFromTraits,
1826
3384
  fnv1a,
1827
3385
  foldPathIds,
1828
3386
  getPath,
3387
+ guideLocales,
1829
3388
  guidePlatforms,
3389
+ guideTextEntries,
1830
3390
  guidelyIdFromSelector,
1831
3391
  hasVideoMedia,
1832
3392
  isAllowedEmbedSrc,
@@ -1839,6 +3399,12 @@ var SHARED_VERSION = "0.9.0";
1839
3399
  isRuleGroup,
1840
3400
  isSafeMediaUrl,
1841
3401
  isVideoContentType,
3402
+ localeName,
3403
+ localizeAnnouncement,
3404
+ localizeArticle,
3405
+ localizeGuide,
3406
+ localizeResourceCenter,
3407
+ matchCssSelector,
1842
3408
  matchUrlPattern,
1843
3409
  matchesAudiences,
1844
3410
  matchesHelpQuery,
@@ -1846,30 +3412,63 @@ var SHARED_VERSION = "0.9.0";
1846
3412
  mediaMaxBytes,
1847
3413
  normalizeErrorMessage,
1848
3414
  normalizeFrameFile,
3415
+ normalizeLocale,
3416
+ normalizeSnapshot,
3417
+ orderedModules,
1849
3418
  pageLabel,
1850
3419
  pageName,
3420
+ pagePattern,
3421
+ pageRuleError,
3422
+ pageRuleMatches,
3423
+ pageRulesMatch,
1851
3424
  pageTerms,
3425
+ parseCssSelector,
3426
+ parseCsvRows,
3427
+ parseHexColor,
1852
3428
  parseStack,
3429
+ parseTranslationCsv,
3430
+ parseXliff,
3431
+ propertyAttributeAllowed,
3432
+ queryConditionRegex,
1853
3433
  randomId,
3434
+ readableTextOn,
3435
+ relativeLuminance,
1854
3436
  resolveCaptureSettings,
3437
+ resolveLocale,
3438
+ resourceCenterLocales,
1855
3439
  resourceCenterSections,
3440
+ resourceCenterTextEntries,
1856
3441
  rolloutBucket,
1857
3442
  safeRegExp,
3443
+ sanitizeCustomCss,
1858
3444
  sanitizeProperties,
3445
+ scopeCustomCss,
1859
3446
  screenPath,
3447
+ scriptSnippet,
1860
3448
  servedArticleAudiences,
1861
3449
  showMeHref,
1862
3450
  showMeKeyFromHref,
1863
3451
  showMeKeys,
1864
3452
  slugify,
3453
+ snapshotFromSelector,
3454
+ stableStringify,
1865
3455
  stripOrigin,
1866
3456
  supportsPlatform,
1867
3457
  templateConfig,
1868
3458
  toEmbedUrl,
3459
+ toTranslationCsv,
3460
+ toXliff,
3461
+ translationCoverage,
3462
+ unreadAnnouncements,
1869
3463
  validateGuideConfig,
3464
+ variantProblems,
3465
+ variantRanges,
3466
+ visibleAnnouncements,
1870
3467
  visibleArticleIds,
1871
3468
  visibleButtons,
1872
3469
  visitorAudiences,
3470
+ visitorLocales,
3471
+ withExperimentBucket,
1873
3472
  withVisibility
1874
3473
  });
1875
3474
  //# sourceMappingURL=index.cjs.map