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