@guidelytech/shared 0.15.0 → 0.17.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/runtime.cjs CHANGED
@@ -28,6 +28,7 @@ __export(runtime_exports, {
28
28
  AGENT_TURNS_PER_BATCH: () => AGENT_TURNS_PER_BATCH,
29
29
  AGENT_TURN_MAX_TEXT: () => AGENT_TURN_MAX_TEXT,
30
30
  AGENT_TURN_ROLES: () => AGENT_TURN_ROLES,
31
+ ARTICLE_HREF_PREFIX: () => ARTICLE_HREF_PREFIX,
31
32
  ARTICLE_VISIBILITIES: () => ARTICLE_VISIBILITIES,
32
33
  CAPTURE_PARAM: () => CAPTURE_PARAM,
33
34
  CAPTURE_SCREENSHOT_MAX_BYTES: () => CAPTURE_SCREENSHOT_MAX_BYTES,
@@ -49,6 +50,10 @@ __export(runtime_exports, {
49
50
  GUIDE_EXPERIMENT_STATUSES: () => GUIDE_EXPERIMENT_STATUSES,
50
51
  GUIDE_VISIBILITIES: () => GUIDE_VISIBILITIES,
51
52
  LOGGED_IN_AUDIENCE: () => LOGGED_IN_AUDIENCE,
53
+ MAX_APP_VERSION_LENGTH: () => MAX_APP_VERSION_LENGTH,
54
+ MAX_BREADCRUMBS: () => MAX_BREADCRUMBS,
55
+ MAX_BUG_REPORT_LENGTH: () => MAX_BUG_REPORT_LENGTH,
56
+ MAX_BUG_REPORT_SCREENSHOT_BYTES: () => MAX_BUG_REPORT_SCREENSHOT_BYTES,
52
57
  MAX_COLLECTION_DEPTH: () => MAX_COLLECTION_DEPTH,
53
58
  MAX_COMPLAINT_ANSWER_LENGTH: () => MAX_COMPLAINT_ANSWER_LENGTH,
54
59
  MAX_COMPLAINT_ATTACHMENT_BYTES: () => MAX_COMPLAINT_ATTACHMENT_BYTES,
@@ -56,6 +61,13 @@ __export(runtime_exports, {
56
61
  MAX_COMPLAINT_FIELDS: () => MAX_COMPLAINT_FIELDS,
57
62
  MAX_COMPLAINT_LENGTH: () => MAX_COMPLAINT_LENGTH,
58
63
  MAX_CUSTOM_CSS: () => MAX_CUSTOM_CSS,
64
+ MAX_DEBUG_IMAGES: () => MAX_DEBUG_IMAGES,
65
+ MAX_DETAIL_FRAMES: () => MAX_DETAIL_FRAMES,
66
+ MAX_DETAIL_THREADS: () => MAX_DETAIL_THREADS,
67
+ MAX_ERROR_TAGS: () => MAX_ERROR_TAGS,
68
+ MAX_EXCEPTION_CHAIN: () => MAX_EXCEPTION_CHAIN,
69
+ MAX_EXCEPTION_DETAIL_BYTES: () => MAX_EXCEPTION_DETAIL_BYTES,
70
+ MAX_EXCEPTION_DETAIL_RAW_BYTES: () => MAX_EXCEPTION_DETAIL_RAW_BYTES,
59
71
  MAX_PROPERTY_BYTES: () => MAX_PROPERTY_BYTES,
60
72
  MAX_STACK_FRAMES: () => MAX_STACK_FRAMES,
61
73
  MEDIA_FILE_MAX_BYTES: () => MEDIA_FILE_MAX_BYTES,
@@ -96,6 +108,8 @@ __export(runtime_exports, {
96
108
  WS_MAX_MESSAGES_PER_SOCKET: () => WS_MAX_MESSAGES_PER_SOCKET,
97
109
  WS_MAX_MESSAGE_BYTES: () => WS_MAX_MESSAGE_BYTES,
98
110
  applyGuideTranslations: () => applyGuideTranslations,
111
+ articleHref: () => articleHref,
112
+ articleIdFromHref: () => articleIdFromHref,
99
113
  articleTextEntries: () => articleTextEntries,
100
114
  assignGuideVariant: () => assignGuideVariant,
101
115
  baseLanguage: () => baseLanguage,
@@ -107,8 +121,10 @@ __export(runtime_exports, {
107
121
  contrastIssues: () => contrastIssues,
108
122
  contrastRatio: () => contrastRatio,
109
123
  cssSelectorError: () => cssSelectorError,
124
+ customFingerprint: () => customFingerprint,
110
125
  describeRule: () => describeRule,
111
126
  emptyRuleGroup: () => emptyRuleGroup,
127
+ errorFilterDrops: () => errorFilterDrops,
112
128
  evaluateRule: () => evaluateRule,
113
129
  evaluateRules: () => evaluateRules,
114
130
  evenWeights: () => evenWeights,
@@ -137,6 +153,7 @@ __export(runtime_exports, {
137
153
  isRuleGroup: () => isRuleGroup,
138
154
  isSafeMediaUrl: () => isSafeMediaUrl,
139
155
  isVideoContentType: () => isVideoContentType,
156
+ isVideoFileUrl: () => isVideoFileUrl,
140
157
  localeName: () => localeName,
141
158
  localizeAnnouncement: () => localizeAnnouncement,
142
159
  localizeArticle: () => localizeArticle,
@@ -149,10 +166,12 @@ __export(runtime_exports, {
149
166
  mediaKind: () => mediaKind,
150
167
  mediaMaxBytes: () => mediaMaxBytes,
151
168
  needsReview: () => needsReview,
169
+ normalizeAppVersion: () => normalizeAppVersion,
152
170
  normalizeErrorMessage: () => normalizeErrorMessage,
153
171
  normalizeFrameFile: () => normalizeFrameFile,
154
172
  normalizeLocale: () => normalizeLocale,
155
173
  normalizeSnapshot: () => normalizeSnapshot,
174
+ normalizeTags: () => normalizeTags,
156
175
  orderedModules: () => orderedModules,
157
176
  pageLabel: () => pageLabel,
158
177
  pagePattern: () => pagePattern,
@@ -166,6 +185,7 @@ __export(runtime_exports, {
166
185
  propertyAttributeAllowed: () => propertyAttributeAllowed,
167
186
  queryConditionRegex: () => queryConditionRegex,
168
187
  randomId: () => randomId,
188
+ reactNativeBundleUrl: () => reactNativeBundleUrl,
169
189
  readableTextOn: () => readableTextOn,
170
190
  relativeLuminance: () => relativeLuminance,
171
191
  resolveLocale: () => resolveLocale,
@@ -185,13 +205,16 @@ __export(runtime_exports, {
185
205
  slugify: () => slugify,
186
206
  snapshotFromSelector: () => snapshotFromSelector,
187
207
  stableStringify: () => stableStringify,
208
+ stepVideo: () => stepVideo,
188
209
  stripOrigin: () => stripOrigin,
189
210
  supportsPlatform: () => supportsPlatform,
190
211
  toEmbedUrl: () => toEmbedUrl,
191
212
  translationCoverage: () => translationCoverage,
213
+ trimExceptionDetail: () => trimExceptionDetail,
192
214
  unreadAnnouncements: () => unreadAnnouncements,
193
215
  variantProblems: () => variantProblems,
194
216
  variantRanges: () => variantRanges,
217
+ videoThumbnailUrl: () => videoThumbnailUrl,
195
218
  visibleAnnouncements: () => visibleAnnouncements,
196
219
  visibleArticleIds: () => visibleArticleIds,
197
220
  visitorAudiences: () => visitorAudiences,
@@ -217,18 +240,18 @@ function slugify(input) {
217
240
  return input.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "untitled";
218
241
  }
219
242
  var ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
220
- function randomId(size = 16) {
243
+ function randomId(size2 = 16) {
221
244
  const g = typeof globalThis !== "undefined" ? globalThis : {};
222
245
  let bytes;
223
246
  if (g.crypto && typeof g.crypto.getRandomValues === "function") {
224
- bytes = new Uint8Array(size);
247
+ bytes = new Uint8Array(size2);
225
248
  g.crypto.getRandomValues(bytes);
226
249
  } else {
227
- bytes = new Uint8Array(size);
228
- for (let i = 0; i < size; i++) bytes[i] = Math.floor(Math.random() * 256);
250
+ bytes = new Uint8Array(size2);
251
+ for (let i = 0; i < size2; i++) bytes[i] = Math.floor(Math.random() * 256);
229
252
  }
230
253
  let out = "";
231
- for (let i = 0; i < size; i++) out += ALPHABET[bytes[i] % ALPHABET.length];
254
+ for (let i = 0; i < size2; i++) out += ALPHABET[bytes[i] % ALPHABET.length];
232
255
  return out;
233
256
  }
234
257
  function isPlainObject(v) {
@@ -585,16 +608,23 @@ function describeRule(rule) {
585
608
  // src/events-util.ts
586
609
  var SENSITIVE_PROPERTY_PATTERN = /(password|passwd|secret|token|credit|card|cvv|ssn|iban)/i;
587
610
  var MAX_PROPERTY_BYTES = 8 * 1024;
611
+ var MAX_APP_VERSION_LENGTH = 64;
612
+ function normalizeAppVersion(input) {
613
+ if (typeof input !== "string" && typeof input !== "number") return null;
614
+ const printable = Array.from(String(input)).filter((c) => c.charCodeAt(0) > 31 && c.charCodeAt(0) !== 127).join("");
615
+ const v = printable.trim().slice(0, MAX_APP_VERSION_LENGTH).trim();
616
+ return v || null;
617
+ }
588
618
  function sanitizeProperties(props) {
589
619
  if (!props) return {};
590
620
  const out = {};
591
- let size = 0;
621
+ let size2 = 0;
592
622
  for (const [k, v] of Object.entries(props)) {
593
623
  if (SENSITIVE_PROPERTY_PATTERN.test(k)) continue;
594
624
  if (typeof v === "function" || typeof v === "symbol") continue;
595
625
  const str2 = typeof v === "string" ? v : JSON.stringify(v ?? null);
596
- size += k.length + (str2?.length ?? 0);
597
- if (size > MAX_PROPERTY_BYTES) break;
626
+ size2 += k.length + (str2?.length ?? 0);
627
+ if (size2 > MAX_PROPERTY_BYTES) break;
598
628
  out[k.slice(0, 100)] = typeof v === "string" ? v.slice(0, 1e3) : v;
599
629
  }
600
630
  return out;
@@ -604,16 +634,23 @@ function sanitizeProperties(props) {
604
634
  var MAX_STACK_FRAMES = 30;
605
635
  var V8 = /^\s*at (?:(.+?) \()?((?:[a-z][\w+.-]*:)?[^\s()]+?):(\d+):(\d+)\)?\s*$/i;
606
636
  var GECKO = /^\s*(.*?)@(.+?):(\d+):(\d+)\s*$/;
637
+ var HERMES = /^\s*at (?:(.+?) \()?address at ([^\s()]+?):(\d+):(\d+)\)?\s*$/;
638
+ function reactNativeBundleUrl(file) {
639
+ const base = file.replace(/[?#].*$/, "").split("/").pop() || file;
640
+ return `app:///${base}`;
641
+ }
607
642
  function parseStack(stack, max = MAX_STACK_FRAMES) {
608
643
  if (!stack || typeof stack !== "string") return [];
609
644
  const frames = [];
610
645
  for (const raw of stack.split("\n")) {
611
646
  if (frames.length >= max) break;
612
647
  const line = raw.slice(0, 1e3);
613
- const m = V8.exec(line) ?? GECKO.exec(line);
648
+ const hermes = HERMES.exec(line);
649
+ const m = hermes ?? V8.exec(line) ?? GECKO.exec(line);
614
650
  if (!m) continue;
615
651
  const fn = (m[1] || "").trim();
616
- frames.push({ fn: fn ? fn.slice(0, 200) : void 0, file: m[2]?.slice(0, 500), line: Number(m[3]), col: Number(m[4]) });
652
+ const file = hermes ? reactNativeBundleUrl(m[2]) : m[2];
653
+ frames.push({ fn: fn ? fn.slice(0, 200) : void 0, file: file?.slice(0, 500), line: Number(m[3]), col: Number(m[4]) });
617
654
  }
618
655
  return frames;
619
656
  }
@@ -633,13 +670,23 @@ function normalizeFrameFile(file) {
633
670
  var SOURCEMAP_MAX_FILE_BYTES = 100 * 1024 * 1024;
634
671
  var SOURCEMAP_MAX_FILES_PER_UPLOAD = 200;
635
672
  function fingerprintError(input) {
636
- const top = (input.frames ?? []).find((f) => f.file);
637
- const frameKey = input.original ? `src:${input.original.source}:${input.original.name || "?"}` : top ? `${normalizeFrameFile(top.file)}:${top.fn || "?"}` : "";
673
+ const withFile = (input.frames ?? []).filter((f) => f.file || f.module);
674
+ const top = withFile.find((f) => f.inApp === true) ?? withFile.find((f) => f.inApp !== false) ?? withFile[0];
675
+ const frameKey = input.original ? `src:${input.original.source}:${input.original.name || "?"}` : top ? `${top.file ? normalizeFrameFile(top.file) : `mod:${top.module}`}:${top.fn || "?"}` : "";
638
676
  const key = [input.type || "Error", normalizeErrorMessage(input.message || ""), frameKey].join("|");
639
677
  const a = fnv1a(key).toString(16).padStart(8, "0");
640
678
  const b = fnv1a(`guidely:${key}`).toString(16).padStart(8, "0");
641
679
  return a + b;
642
680
  }
681
+ function customFingerprint(parts, computed) {
682
+ if (!Array.isArray(parts) || parts.length === 0) return computed;
683
+ const items = parts.filter((p) => typeof p === "string" || typeof p === "number").map((p) => String(p).slice(0, 200)).slice(0, 20);
684
+ if (items.length === 0) return computed;
685
+ const isDefault = (p) => /^\{\{\s*default\s*\}\}$/i.test(p);
686
+ if (items.every(isDefault)) return computed;
687
+ const key = items.map((p) => isDefault(p) ? computed : p).join("|");
688
+ return fnv1a(key).toString(16).padStart(8, "0") + fnv1a(`guidely:fp:${key}`).toString(16).padStart(8, "0");
689
+ }
643
690
 
644
691
  // src/network.ts
645
692
  var NETWORK_PLUGIN = "guidely/network@1";
@@ -775,6 +822,19 @@ function isSafeMediaUrl(url) {
775
822
  return false;
776
823
  }
777
824
  }
825
+ function videoThumbnailUrl(url) {
826
+ const embed = url ? toEmbedUrl(url) : null;
827
+ if (embed?.provider !== "youtube") return null;
828
+ const id = embed.src.split("/embed/")[1]?.split("?")[0];
829
+ return id ? `https://i.ytimg.com/vi/${id}/hqdefault.jpg` : null;
830
+ }
831
+ function isVideoFileUrl(url) {
832
+ return isSafeMediaUrl(url) && /\.(mp4|webm|m4v|mov|ogv)$/i.test(new URL(url).pathname);
833
+ }
834
+ function stepVideo(step) {
835
+ if (!step.videoUrl || !isSafeMediaUrl(step.videoUrl)) return null;
836
+ return { url: step.videoUrl, poster: (step.imageUrl && isSafeMediaUrl(step.imageUrl) ? step.imageUrl : null) ?? videoThumbnailUrl(step.videoUrl) };
837
+ }
778
838
 
779
839
  // src/resource-center.ts
780
840
  var MAX_COLLECTION_DEPTH = 3;
@@ -897,6 +957,16 @@ function unreadAnnouncements(items, lastSeenAt) {
897
957
  if (Number.isNaN(seen)) return items.length;
898
958
  return items.filter((a) => Date.parse(a.publishedAt) > seen).length;
899
959
  }
960
+ var ARTICLE_HREF_PREFIX = "#guidely-article:";
961
+ var ARTICLE_ID = /^[A-Za-z0-9_-]{1,64}$/;
962
+ function articleHref(articleId) {
963
+ return `${ARTICLE_HREF_PREFIX}${articleId}`;
964
+ }
965
+ function articleIdFromHref(href) {
966
+ if (!href || !href.startsWith(ARTICLE_HREF_PREFIX)) return null;
967
+ const id = href.slice(ARTICLE_HREF_PREFIX.length);
968
+ return ARTICLE_ID.test(id) ? id : null;
969
+ }
900
970
 
901
971
  // src/howto-limits.ts
902
972
  var CAPTURE_PARAM = "guidely_capture";
@@ -1487,6 +1557,10 @@ var MAX_COMPLAINT_ANSWER_LENGTH = 500;
1487
1557
  var MAX_COMPLAINT_ATTACHMENT_BYTES = 2 * 1024 * 1024;
1488
1558
  var complaintReference = (number) => `CMP-${number}`;
1489
1559
 
1560
+ // src/bug-reports-limits.ts
1561
+ var MAX_BUG_REPORT_LENGTH = 4e3;
1562
+ var MAX_BUG_REPORT_SCREENSHOT_BYTES = 4 * 1024 * 1024;
1563
+
1490
1564
  // src/agents-limits.ts
1491
1565
  var AGENT_TURN_ROLES = ["user", "assistant", "tool", "system"];
1492
1566
  var AGENT_OUTCOMES = ["success", "failure", "escalated", "abandoned"];
@@ -1960,6 +2034,71 @@ function contrastIssues(colors) {
1960
2034
  }
1961
2035
  return issues;
1962
2036
  }
2037
+
2038
+ // src/error-detail.ts
2039
+ var MAX_EXCEPTION_DETAIL_BYTES = 64 * 1024;
2040
+ var MAX_EXCEPTION_DETAIL_RAW_BYTES = 1024 * 1024;
2041
+ var MAX_BREADCRUMBS = 100;
2042
+ var MAX_EXCEPTION_CHAIN = 20;
2043
+ var MAX_DETAIL_FRAMES = 250;
2044
+ var MAX_DETAIL_THREADS = 100;
2045
+ var MAX_DEBUG_IMAGES = 500;
2046
+ var MAX_ERROR_TAGS = 50;
2047
+ var size = (v) => {
2048
+ try {
2049
+ return JSON.stringify(v)?.length ?? 0;
2050
+ } catch {
2051
+ return Infinity;
2052
+ }
2053
+ };
2054
+ function normalizeTags(tags) {
2055
+ const out = {};
2056
+ for (const [k, v] of Object.entries(tags ?? {})) {
2057
+ if (Object.keys(out).length >= MAX_ERROR_TAGS) break;
2058
+ if (!k || v === void 0 || v === null) continue;
2059
+ out[k.slice(0, 32)] = String(v).slice(0, 200);
2060
+ }
2061
+ return out;
2062
+ }
2063
+ function trimExceptionDetail(detail, max = MAX_EXCEPTION_DETAIL_BYTES) {
2064
+ const d = detail;
2065
+ if (d.breadcrumbs?.values && d.breadcrumbs.values.length > MAX_BREADCRUMBS) d.breadcrumbs.values = d.breadcrumbs.values.slice(-MAX_BREADCRUMBS);
2066
+ if (d.exception?.values && d.exception.values.length > MAX_EXCEPTION_CHAIN) d.exception.values = d.exception.values.slice(-MAX_EXCEPTION_CHAIN);
2067
+ if (d.threads?.values && d.threads.values.length > MAX_DETAIL_THREADS) d.threads.values = d.threads.values.slice(0, MAX_DETAIL_THREADS);
2068
+ if (d.debug_meta?.images && d.debug_meta.images.length > MAX_DEBUG_IMAGES) d.debug_meta.images = d.debug_meta.images.slice(0, MAX_DEBUG_IMAGES);
2069
+ const stacks = () => [...d.exception?.values ?? [], ...d.threads?.values ?? []].map((x) => x.stacktrace).filter((s) => !!s);
2070
+ for (const s of stacks()) if (s.frames && s.frames.length > MAX_DETAIL_FRAMES) s.frames = s.frames.slice(-MAX_DETAIL_FRAMES);
2071
+ if (size(d) <= max) return d;
2072
+ while (d.breadcrumbs?.values.length && size(d) > max) d.breadcrumbs.values = d.breadcrumbs.values.slice(Math.ceil(d.breadcrumbs.values.length / 2));
2073
+ if (size(d) <= max) return d;
2074
+ for (const s of stacks())
2075
+ for (const f of s.frames ?? []) {
2076
+ delete f.vars;
2077
+ delete f.pre_context;
2078
+ delete f.post_context;
2079
+ }
2080
+ if (size(d) <= max) return d;
2081
+ if (d.threads?.values) d.threads.values = d.threads.values.filter((t) => t.crashed || t.current);
2082
+ if (size(d) <= max) return d;
2083
+ if (d.extra) d.extra = { _trimmed: true };
2084
+ if (d.request) delete d.request.data;
2085
+ for (const s of stacks()) while (s.frames && s.frames.length > 20 && size(d) > max) s.frames.splice(Math.floor(s.frames.length / 2) - 5, 10);
2086
+ if (d.debug_meta?.images && size(d) > max) d.debug_meta.images = d.debug_meta.images.slice(0, 50);
2087
+ return d;
2088
+ }
2089
+ var matches = (patterns, value) => patterns.some((p) => typeof p === "string" ? p !== "" && value.includes(p) : safeTest(p, value));
2090
+ function safeTest(re, value) {
2091
+ re.lastIndex = 0;
2092
+ return re.test(value);
2093
+ }
2094
+ function errorFilterDrops(e, opts) {
2095
+ const message = e.message ?? "";
2096
+ if (opts.ignoreErrors?.length && (matches(opts.ignoreErrors, `${e.type || "Error"}: ${message}`) || matches(opts.ignoreErrors, message))) return true;
2097
+ if (!e.file) return false;
2098
+ if (opts.denyUrls?.length && matches(opts.denyUrls, e.file)) return true;
2099
+ if (opts.allowUrls?.length && !matches(opts.allowUrls, e.file)) return true;
2100
+ return false;
2101
+ }
1963
2102
  // Annotate the CommonJS export names for ESM import in node:
1964
2103
  0 && (module.exports = {
1965
2104
  AGENT_METADATA_MAX_BYTES,
@@ -1970,6 +2109,7 @@ function contrastIssues(colors) {
1970
2109
  AGENT_TURNS_PER_BATCH,
1971
2110
  AGENT_TURN_MAX_TEXT,
1972
2111
  AGENT_TURN_ROLES,
2112
+ ARTICLE_HREF_PREFIX,
1973
2113
  ARTICLE_VISIBILITIES,
1974
2114
  CAPTURE_PARAM,
1975
2115
  CAPTURE_SCREENSHOT_MAX_BYTES,
@@ -1991,6 +2131,10 @@ function contrastIssues(colors) {
1991
2131
  GUIDE_EXPERIMENT_STATUSES,
1992
2132
  GUIDE_VISIBILITIES,
1993
2133
  LOGGED_IN_AUDIENCE,
2134
+ MAX_APP_VERSION_LENGTH,
2135
+ MAX_BREADCRUMBS,
2136
+ MAX_BUG_REPORT_LENGTH,
2137
+ MAX_BUG_REPORT_SCREENSHOT_BYTES,
1994
2138
  MAX_COLLECTION_DEPTH,
1995
2139
  MAX_COMPLAINT_ANSWER_LENGTH,
1996
2140
  MAX_COMPLAINT_ATTACHMENT_BYTES,
@@ -1998,6 +2142,13 @@ function contrastIssues(colors) {
1998
2142
  MAX_COMPLAINT_FIELDS,
1999
2143
  MAX_COMPLAINT_LENGTH,
2000
2144
  MAX_CUSTOM_CSS,
2145
+ MAX_DEBUG_IMAGES,
2146
+ MAX_DETAIL_FRAMES,
2147
+ MAX_DETAIL_THREADS,
2148
+ MAX_ERROR_TAGS,
2149
+ MAX_EXCEPTION_CHAIN,
2150
+ MAX_EXCEPTION_DETAIL_BYTES,
2151
+ MAX_EXCEPTION_DETAIL_RAW_BYTES,
2001
2152
  MAX_PROPERTY_BYTES,
2002
2153
  MAX_STACK_FRAMES,
2003
2154
  MEDIA_FILE_MAX_BYTES,
@@ -2038,6 +2189,8 @@ function contrastIssues(colors) {
2038
2189
  WS_MAX_MESSAGES_PER_SOCKET,
2039
2190
  WS_MAX_MESSAGE_BYTES,
2040
2191
  applyGuideTranslations,
2192
+ articleHref,
2193
+ articleIdFromHref,
2041
2194
  articleTextEntries,
2042
2195
  assignGuideVariant,
2043
2196
  baseLanguage,
@@ -2049,8 +2202,10 @@ function contrastIssues(colors) {
2049
2202
  contrastIssues,
2050
2203
  contrastRatio,
2051
2204
  cssSelectorError,
2205
+ customFingerprint,
2052
2206
  describeRule,
2053
2207
  emptyRuleGroup,
2208
+ errorFilterDrops,
2054
2209
  evaluateRule,
2055
2210
  evaluateRules,
2056
2211
  evenWeights,
@@ -2079,6 +2234,7 @@ function contrastIssues(colors) {
2079
2234
  isRuleGroup,
2080
2235
  isSafeMediaUrl,
2081
2236
  isVideoContentType,
2237
+ isVideoFileUrl,
2082
2238
  localeName,
2083
2239
  localizeAnnouncement,
2084
2240
  localizeArticle,
@@ -2091,10 +2247,12 @@ function contrastIssues(colors) {
2091
2247
  mediaKind,
2092
2248
  mediaMaxBytes,
2093
2249
  needsReview,
2250
+ normalizeAppVersion,
2094
2251
  normalizeErrorMessage,
2095
2252
  normalizeFrameFile,
2096
2253
  normalizeLocale,
2097
2254
  normalizeSnapshot,
2255
+ normalizeTags,
2098
2256
  orderedModules,
2099
2257
  pageLabel,
2100
2258
  pagePattern,
@@ -2108,6 +2266,7 @@ function contrastIssues(colors) {
2108
2266
  propertyAttributeAllowed,
2109
2267
  queryConditionRegex,
2110
2268
  randomId,
2269
+ reactNativeBundleUrl,
2111
2270
  readableTextOn,
2112
2271
  relativeLuminance,
2113
2272
  resolveLocale,
@@ -2127,13 +2286,16 @@ function contrastIssues(colors) {
2127
2286
  slugify,
2128
2287
  snapshotFromSelector,
2129
2288
  stableStringify,
2289
+ stepVideo,
2130
2290
  stripOrigin,
2131
2291
  supportsPlatform,
2132
2292
  toEmbedUrl,
2133
2293
  translationCoverage,
2294
+ trimExceptionDetail,
2134
2295
  unreadAnnouncements,
2135
2296
  variantProblems,
2136
2297
  variantRanges,
2298
+ videoThumbnailUrl,
2137
2299
  visibleAnnouncements,
2138
2300
  visibleArticleIds,
2139
2301
  visitorAudiences,