@uipath/apollo-react 4.63.0 → 4.64.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.
@@ -0,0 +1,394 @@
1
+ const YOUTUBE_VIDEO_ID = /^[A-Za-z0-9_-]{11}$/;
2
+ const YOUTUBE_HOSTS = new Set([
3
+ 'youtube.com',
4
+ 'www.youtube.com',
5
+ 'm.youtube.com',
6
+ 'music.youtube.com',
7
+ 'youtu.be',
8
+ 'www.youtu.be',
9
+ 'youtube-nocookie.com',
10
+ 'www.youtube-nocookie.com'
11
+ ]);
12
+ const PAGE_BASED_VIDEO_HOSTS = new Set([
13
+ 'vimeo.com',
14
+ 'www.vimeo.com',
15
+ 'player.vimeo.com',
16
+ 'loom.com',
17
+ 'www.loom.com'
18
+ ]);
19
+ const MEDIA_TITLE_PREFIX = 'sticky-note-media';
20
+ const MEDIA_TITLE_PATTERN = /^sticky-note-media;kind=(image|youtube|publicVideo);layout=(natural-width|full-width)$/;
21
+ const FLOW_MEDIA_TITLE_PATTERN = /^flow-media:(image|youtube|video):(natural-width|full-width)$/;
22
+ const LEGACY_FULL_WIDTH_IMAGE_TITLE = 'flow-full-width';
23
+ function parseHttpsUrl(rawUrl) {
24
+ let url;
25
+ try {
26
+ url = new URL(rawUrl.trim());
27
+ } catch {
28
+ return {
29
+ ok: false,
30
+ error: 'invalid-url'
31
+ };
32
+ }
33
+ if ('https:' !== url.protocol) return {
34
+ ok: false,
35
+ error: 'https-required'
36
+ };
37
+ if (url.username || url.password) return {
38
+ ok: false,
39
+ error: 'invalid-url'
40
+ };
41
+ return {
42
+ ok: true,
43
+ url
44
+ };
45
+ }
46
+ function youtubeVideoId(url) {
47
+ const hostname = url.hostname.toLowerCase();
48
+ let candidate = null;
49
+ if ('youtu.be' === hostname || 'www.youtu.be' === hostname) candidate = url.pathname.split('/').filter(Boolean)[0] ?? null;
50
+ else if ('/watch' === url.pathname) candidate = url.searchParams.get('v');
51
+ else {
52
+ const [kind, id] = url.pathname.split('/').filter(Boolean);
53
+ if ('embed' === kind || 'live' === kind || 'shorts' === kind) candidate = id ?? null;
54
+ }
55
+ return candidate && YOUTUBE_VIDEO_ID.test(candidate) ? candidate : null;
56
+ }
57
+ function parseStickyNoteMediaUrl(rawUrl, mediaType, options = {}) {
58
+ const parsed = parseHttpsUrl(rawUrl);
59
+ if (!parsed.ok) return parsed;
60
+ const { url } = parsed;
61
+ const hostname = url.hostname.toLowerCase();
62
+ const fullWidth = options.fullWidth ?? false;
63
+ if ('image' === mediaType) {
64
+ if (YOUTUBE_HOSTS.has(hostname)) return {
65
+ ok: false,
66
+ error: 'invalid-url'
67
+ };
68
+ return {
69
+ ok: true,
70
+ value: {
71
+ kind: 'image',
72
+ url: url.toString(),
73
+ alt: options.alt ?? '',
74
+ fullWidth
75
+ }
76
+ };
77
+ }
78
+ if (YOUTUBE_HOSTS.has(hostname)) {
79
+ const videoId = youtubeVideoId(url);
80
+ return videoId ? {
81
+ ok: true,
82
+ value: {
83
+ kind: 'youtube',
84
+ videoId,
85
+ fullWidth
86
+ }
87
+ } : {
88
+ ok: false,
89
+ error: 'invalid-youtube-url'
90
+ };
91
+ }
92
+ if (hostname.includes('youtube.') || hostname.includes('youtu.be')) return {
93
+ ok: false,
94
+ error: 'invalid-url'
95
+ };
96
+ if (PAGE_BASED_VIDEO_HOSTS.has(hostname)) return {
97
+ ok: false,
98
+ error: 'unsupported-video-url'
99
+ };
100
+ return {
101
+ ok: true,
102
+ value: {
103
+ kind: 'publicVideo',
104
+ url: url.toString(),
105
+ fullWidth
106
+ }
107
+ };
108
+ }
109
+ function escapeMarkdownLabel(value) {
110
+ return value.replace(/\r\n?|\n/g, ' ').replace(/\\/g, '\\\\').replace(/\[/g, '\\[').replace(/\]/g, '\\]');
111
+ }
112
+ function serializeStickyNoteMedia(media) {
113
+ const layout = media.fullWidth ? 'full-width' : 'natural-width';
114
+ const title = `${MEDIA_TITLE_PREFIX};kind=${media.kind};layout=${layout}`;
115
+ if ('youtube' === media.kind) return `![](<https://www.youtube.com/watch?v=${media.videoId}> "${title}")`;
116
+ const label = 'image' === media.kind ? escapeMarkdownLabel(media.alt) : '';
117
+ return `![${label}](<${new URL(media.url).toString()}> "${title}")`;
118
+ }
119
+ function parseStickyNoteMediaMarker(title) {
120
+ if (title === LEGACY_FULL_WIDTH_IMAGE_TITLE) return {
121
+ kind: 'image',
122
+ fullWidth: true
123
+ };
124
+ const marker = title?.match(MEDIA_TITLE_PATTERN);
125
+ const flowMarker = title?.match(FLOW_MEDIA_TITLE_PATTERN);
126
+ const kind = marker?.[1] ?? flowMarker?.[1];
127
+ const layout = marker?.[2] ?? flowMarker?.[2];
128
+ if (!kind || !layout) return null;
129
+ const normalizedKind = 'video' === kind ? 'publicVideo' : 'image' === kind || 'youtube' === kind || 'publicVideo' === kind ? kind : null;
130
+ if (!normalizedKind) return null;
131
+ return {
132
+ kind: normalizedKind,
133
+ fullWidth: 'full-width' === layout
134
+ };
135
+ }
136
+ function mediaTypeForKind(kind) {
137
+ return 'image' === kind ? 'image' : 'video';
138
+ }
139
+ function parseStickyNoteMediaSource(source, alt = '', title) {
140
+ const marker = parseStickyNoteMediaMarker(title);
141
+ if (!marker) return null;
142
+ const result = parseStickyNoteMediaUrl(source, mediaTypeForKind(marker.kind), {
143
+ alt,
144
+ fullWidth: marker.fullWidth
145
+ });
146
+ return result.ok && result.value.kind === marker.kind ? result.value : null;
147
+ }
148
+ function normalizedRange(length, selectionStart, selectionEnd) {
149
+ const start = Math.max(0, Math.min(length, Math.min(selectionStart, selectionEnd)));
150
+ const end = Math.max(0, Math.min(length, Math.max(selectionStart, selectionEnd)));
151
+ return [
152
+ start,
153
+ end
154
+ ];
155
+ }
156
+ function separatorAfter(prefix) {
157
+ if (!prefix || prefix.endsWith('\n\n')) return '';
158
+ return prefix.endsWith('\n') ? '\n' : '\n\n';
159
+ }
160
+ function separatorBefore(suffix) {
161
+ if (!suffix || suffix.startsWith('\n\n')) return '';
162
+ return suffix.startsWith('\n') ? '\n' : '\n\n';
163
+ }
164
+ function insertStickyNoteMedia(currentValue, block, selection) {
165
+ const selectionIsCurrent = selection?.value === currentValue;
166
+ const [start, end] = selectionIsCurrent ? normalizedRange(currentValue.length, selection.selectionStart, selection.selectionEnd) : [
167
+ currentValue.length,
168
+ currentValue.length
169
+ ];
170
+ const before = currentValue.slice(0, start);
171
+ const after = currentValue.slice(end);
172
+ const leadingSeparator = separatorAfter(before);
173
+ const trailingSeparator = separatorBefore(after);
174
+ const value = `${before}${leadingSeparator}${block}${trailingSeparator}${after}`;
175
+ const caret = before.length + leadingSeparator.length + block.length + trailingSeparator.length;
176
+ return {
177
+ value,
178
+ selectionStart: caret,
179
+ selectionEnd: caret
180
+ };
181
+ }
182
+ function replaceTextRange(currentValue, selectionStart, selectionEnd, replacement) {
183
+ const [start, end] = normalizedRange(currentValue.length, selectionStart, selectionEnd);
184
+ const value = currentValue.slice(0, start) + replacement + currentValue.slice(end);
185
+ const caret = start + replacement.length;
186
+ return {
187
+ value,
188
+ selectionStart: caret,
189
+ selectionEnd: caret
190
+ };
191
+ }
192
+ function unescapeMarkdownLabel(value) {
193
+ return value.replace(/\\(.)/g, (match, escaped)=>'\\' === escaped || '[' === escaped || ']' === escaped ? escaped : match);
194
+ }
195
+ function fencedCodeRanges(content) {
196
+ const ranges = [];
197
+ let openFence = null;
198
+ let lineStart = 0;
199
+ while(lineStart < content.length){
200
+ let lineEnd = lineStart;
201
+ while(lineEnd < content.length && '\n' !== content[lineEnd] && '\r' !== content[lineEnd])lineEnd += 1;
202
+ let nextLineStart = lineEnd;
203
+ if ('\r' === content[nextLineStart]) nextLineStart += 1;
204
+ if ('\n' === content[nextLineStart]) nextLineStart += 1;
205
+ const line = content.slice(lineStart, lineEnd);
206
+ if (openFence) {
207
+ const closingFence = new RegExp(`^ {0,3}${openFence.marker}{${openFence.length},}[ \\t]*$`);
208
+ if (closingFence.test(line)) {
209
+ ranges.push({
210
+ start: openFence.start,
211
+ end: nextLineStart
212
+ });
213
+ openFence = null;
214
+ }
215
+ } else {
216
+ const openingFence = /^ {0,3}(`{3,}|~{3,})/.exec(line);
217
+ const fence = openingFence?.[1];
218
+ const marker = fence?.[0];
219
+ const info = openingFence ? line.slice((openingFence.index ?? 0) + openingFence[0].length) : '';
220
+ if (openingFence && fence && ('`' === marker || '~' === marker) && !('`' === marker && info.includes('`'))) openFence = {
221
+ marker,
222
+ length: fence.length,
223
+ start: lineStart
224
+ };
225
+ }
226
+ lineStart = nextLineStart;
227
+ }
228
+ if (openFence) ranges.push({
229
+ start: openFence.start,
230
+ end: content.length
231
+ });
232
+ return ranges;
233
+ }
234
+ function isBackslashEscaped(content, index, segmentStart) {
235
+ let count = 0;
236
+ for(let cursor = index - 1; cursor >= segmentStart && '\\' === content[cursor]; cursor -= 1)count += 1;
237
+ return count % 2 === 1;
238
+ }
239
+ function inlineCodeRanges(content, start, end) {
240
+ const ranges = [];
241
+ let index = start;
242
+ while(index < end){
243
+ if ('`' !== content[index] || isBackslashEscaped(content, index, start)) {
244
+ index += 1;
245
+ continue;
246
+ }
247
+ let openingEnd = index + 1;
248
+ while(openingEnd < end && '`' === content[openingEnd])openingEnd += 1;
249
+ const markerLength = openingEnd - index;
250
+ let closingStart = openingEnd;
251
+ let found = false;
252
+ while(closingStart < end){
253
+ closingStart = content.indexOf('`', closingStart);
254
+ if (closingStart < 0 || closingStart >= end) break;
255
+ let closingEnd = closingStart + 1;
256
+ while(closingEnd < end && '`' === content[closingEnd])closingEnd += 1;
257
+ if (closingEnd - closingStart === markerLength) {
258
+ ranges.push({
259
+ start: index,
260
+ end: closingEnd
261
+ });
262
+ index = closingEnd;
263
+ found = true;
264
+ break;
265
+ }
266
+ closingStart = closingEnd;
267
+ }
268
+ if (!found) index = openingEnd;
269
+ }
270
+ return ranges;
271
+ }
272
+ function markdownCodeRanges(content) {
273
+ const fencedRanges = fencedCodeRanges(content);
274
+ const ranges = [
275
+ ...fencedRanges
276
+ ];
277
+ let segmentStart = 0;
278
+ for (const fencedRange of fencedRanges){
279
+ ranges.push(...inlineCodeRanges(content, segmentStart, fencedRange.start));
280
+ segmentStart = fencedRange.end;
281
+ }
282
+ ranges.push(...inlineCodeRanges(content, segmentStart, content.length));
283
+ return ranges.sort((left, right)=>left.start - right.start);
284
+ }
285
+ function isLineBreak(character) {
286
+ return '\n' === character || '\r' === character;
287
+ }
288
+ function readMarkdownImageToken(content, start) {
289
+ const failedAt = (index)=>({
290
+ nextIndex: Math.max(start + 2, index)
291
+ });
292
+ const nestedCandidateAt = (index)=>'!' === content[index] && '[' === content[index + 1];
293
+ let index = start + 2;
294
+ const altStart = index;
295
+ while(index < content.length && ']' !== content[index]){
296
+ if (nestedCandidateAt(index)) return failedAt(index);
297
+ if (isLineBreak(content[index])) return failedAt(index + 1);
298
+ if ('\\' === content[index]) index += 1;
299
+ index += 1;
300
+ }
301
+ if (']' !== content[index] || '(' !== content[index + 1]) return failedAt(index + 1);
302
+ const alt = content.slice(altStart, index);
303
+ index += 2;
304
+ let source = '';
305
+ if ('<' === content[index]) {
306
+ const sourceStart = ++index;
307
+ while(index < content.length && '>' !== content[index]){
308
+ if (nestedCandidateAt(index)) return failedAt(index);
309
+ if (isLineBreak(content[index])) return failedAt(index + 1);
310
+ index += 1;
311
+ }
312
+ if ('>' !== content[index]) return failedAt(index);
313
+ source = content.slice(sourceStart, index);
314
+ index += 1;
315
+ } else {
316
+ const sourceStart = index;
317
+ while(index < content.length && ')' !== content[index] && ' ' !== content[index] && '\t' !== content[index] && !isLineBreak(content[index])){
318
+ if (nestedCandidateAt(index)) return failedAt(index);
319
+ index += 1;
320
+ }
321
+ source = content.slice(sourceStart, index);
322
+ }
323
+ if (!source) return failedAt(index + 1);
324
+ while(' ' === content[index] || '\t' === content[index])index += 1;
325
+ let title;
326
+ if ('"' === content[index]) {
327
+ const titleStart = ++index;
328
+ while(index < content.length && '"' !== content[index]){
329
+ if (nestedCandidateAt(index)) return failedAt(index);
330
+ if (isLineBreak(content[index])) return failedAt(index + 1);
331
+ if ('\\' === content[index]) index += 1;
332
+ index += 1;
333
+ }
334
+ if ('"' !== content[index]) return failedAt(index);
335
+ title = content.slice(titleStart, index);
336
+ index += 1;
337
+ while(' ' === content[index] || '\t' === content[index])index += 1;
338
+ }
339
+ if (')' !== content[index]) return failedAt(index + 1);
340
+ const end = index + 1;
341
+ return {
342
+ token: {
343
+ alt,
344
+ source,
345
+ title,
346
+ end
347
+ },
348
+ nextIndex: end
349
+ };
350
+ }
351
+ function parseStickyNoteMediaTokens(content) {
352
+ const tokens = [];
353
+ const codeRanges = markdownCodeRanges(content);
354
+ let codeRangeIndex = 0;
355
+ let cursor = 0;
356
+ while(cursor < content.length){
357
+ const start = content.indexOf('![', cursor);
358
+ if (start < 0) break;
359
+ while(codeRanges[codeRangeIndex] && (codeRanges[codeRangeIndex]?.end ?? 1 / 0) <= start)codeRangeIndex += 1;
360
+ const codeRange = codeRanges[codeRangeIndex];
361
+ if (codeRange && start >= codeRange.start && start < codeRange.end) {
362
+ cursor = Math.max(start + 2, codeRange.end);
363
+ continue;
364
+ }
365
+ const parsed = readMarkdownImageToken(content, start);
366
+ cursor = parsed.nextIndex;
367
+ if (!parsed.token) continue;
368
+ const media = parseStickyNoteMediaSource(parsed.token.source, unescapeMarkdownLabel(parsed.token.alt), parsed.token.title);
369
+ if (media) tokens.push({
370
+ media,
371
+ start,
372
+ end: parsed.token.end
373
+ });
374
+ }
375
+ return tokens;
376
+ }
377
+ function findStickyNoteMediaAtSelection(content, selectionStart, selectionEnd) {
378
+ const [start, end] = normalizedRange(content.length, selectionStart, selectionEnd);
379
+ return parseStickyNoteMediaTokens(content).find((token)=>start === end ? start >= token.start && start < token.end : start < token.end && end > token.start) ?? null;
380
+ }
381
+ function sameSource(left, right) {
382
+ if (left.kind !== right.kind) return false;
383
+ if ('image' === left.kind && 'image' === right.kind) return left.url === right.url;
384
+ if ('youtube' === left.kind && 'youtube' === right.kind) return left.videoId === right.videoId;
385
+ return 'publicVideo' === left.kind && 'publicVideo' === right.kind && left.url === right.url;
386
+ }
387
+ function replaceStickyNoteMedia(content, original, replacement) {
388
+ let closest = null;
389
+ for (const token of parseStickyNoteMediaTokens(content))if (sameSource(token.media, original.media)) {
390
+ if (!closest || Math.abs(token.start - original.start) < Math.abs(closest.start - original.start)) closest = token;
391
+ }
392
+ return closest ? replaceTextRange(content, closest.start, closest.end, replacement) : null;
393
+ }
394
+ export { findStickyNoteMediaAtSelection, insertStickyNoteMedia, parseStickyNoteMediaMarker, parseStickyNoteMediaSource, parseStickyNoteMediaTokens, parseStickyNoteMediaUrl, replaceStickyNoteMedia, serializeStickyNoteMedia };