@alpaca-editor/core 1.0.4084 → 1.0.4086
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/components/ui/paste-button.d.ts +14 -0
- package/dist/components/ui/paste-button.js +114 -0
- package/dist/components/ui/paste-button.js.map +1 -0
- package/dist/config/config.js +50 -0
- package/dist/config/config.js.map +1 -1
- package/dist/config/types.d.ts +21 -0
- package/dist/editor/FieldListField.js +50 -1
- package/dist/editor/FieldListField.js.map +1 -1
- package/dist/editor/LinkEditorDialog.d.ts +1 -0
- package/dist/editor/LinkEditorDialog.js +4 -2
- package/dist/editor/LinkEditorDialog.js.map +1 -1
- package/dist/editor/control-center/Setup.d.ts +1 -0
- package/dist/editor/control-center/Setup.js +229 -0
- package/dist/editor/control-center/Setup.js.map +1 -0
- package/dist/editor/field-types/InternalLinkFieldEditor.js +3 -1
- package/dist/editor/field-types/InternalLinkFieldEditor.js.map +1 -1
- package/dist/editor/field-types/richtext/components/ReactSlate.js +8 -4
- package/dist/editor/field-types/richtext/components/ReactSlate.js.map +1 -1
- package/dist/editor/field-types/richtext/utils/conversion.js +147 -13
- package/dist/editor/field-types/richtext/utils/conversion.js.map +1 -1
- package/dist/editor/field-types/richtext/utils/plugins.d.ts +1 -0
- package/dist/editor/field-types/richtext/utils/plugins.js +19 -4
- package/dist/editor/field-types/richtext/utils/plugins.js.map +1 -1
- package/dist/editor/utils/urlUtils.d.ts +9 -0
- package/dist/editor/utils/urlUtils.js +25 -0
- package/dist/editor/utils/urlUtils.js.map +1 -0
- package/dist/editor/utils.d.ts +5 -0
- package/dist/editor/utils.js +29 -0
- package/dist/editor/utils.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/styles.css +8 -0
- package/package.json +1 -1
- package/src/components/ui/paste-button.tsx +163 -0
- package/src/config/config.tsx +59 -0
- package/src/config/types.ts +21 -0
- package/src/editor/FieldListField.tsx +62 -0
- package/src/editor/LinkEditorDialog.tsx +6 -2
- package/src/editor/control-center/Setup.tsx +432 -0
- package/src/editor/field-types/InternalLinkFieldEditor.tsx +3 -1
- package/src/editor/field-types/richtext/components/ReactSlate.tsx +11 -6
- package/src/editor/field-types/richtext/utils/conversion.ts +167 -13
- package/src/editor/field-types/richtext/utils/plugins.ts +24 -4
- package/src/editor/utils/urlUtils.ts +24 -0
- package/src/editor/utils.ts +33 -0
- package/src/revision.ts +2 -2
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
HtmlToSlateResult,
|
|
13
13
|
SlateToHtmlResult
|
|
14
14
|
} from '../types';
|
|
15
|
+
import { normalizeUrl } from '../../../utils/urlUtils';
|
|
16
|
+
|
|
15
17
|
|
|
16
18
|
// Elements that should be completely preserved as raw HTML
|
|
17
19
|
const PRESERVE_AS_RAW_ELEMENTS = new Set([
|
|
@@ -241,14 +243,56 @@ const htmlToSlateInternal = (html: string, profile: SimplifiedProfile): Descenda
|
|
|
241
243
|
} else if (tagName === 'a') {
|
|
242
244
|
const href = childElement.getAttribute('href') || '';
|
|
243
245
|
const target = childElement.getAttribute('target') || '_self';
|
|
244
|
-
const isInternal = childElement.hasAttribute('data-internal')
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
246
|
+
const isInternal = childElement.hasAttribute('data-internal') ||
|
|
247
|
+
href.includes('~/link.aspx?_id=') ||
|
|
248
|
+
href.includes('/sitecore/service/notfound.aspx?item=');
|
|
249
|
+
|
|
250
|
+
let itemId = childElement.getAttribute('data-item-id') || '';
|
|
251
|
+
let targetItemLongId = childElement.getAttribute('data-item-longid') || '';
|
|
252
|
+
let queryString = childElement.getAttribute('data-querystring') || '';
|
|
253
|
+
|
|
254
|
+
// Parse standard Sitecore RTE format: ~/link.aspx?_id=GUID&_z=z
|
|
255
|
+
if (href.includes('~/link.aspx?_id=') && !itemId) {
|
|
256
|
+
// Decode HTML entities (e.g., & to &) before parsing
|
|
257
|
+
const decodedHref = href.replace(/&/g, '&');
|
|
258
|
+
const queryString_raw = decodedHref.split('?')[1];
|
|
259
|
+
|
|
260
|
+
const urlParams = new URLSearchParams(queryString_raw);
|
|
261
|
+
const id = urlParams.get('_id');
|
|
262
|
+
if (id) {
|
|
263
|
+
// Convert GUID format back to standard format with dashes
|
|
264
|
+
itemId = id.replace(/(\w{8})(\w{4})(\w{4})(\w{4})(\w{12})/, '$1-$2-$3-$4-$5').toLowerCase();
|
|
265
|
+
targetItemLongId = itemId;
|
|
266
|
+
|
|
267
|
+
// Extract other query parameters (excluding _id and _z)
|
|
268
|
+
const otherParams = Array.from(urlParams.entries())
|
|
269
|
+
.filter(([key]) => key !== '_id' && key !== '_z')
|
|
270
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
271
|
+
.join('&');
|
|
272
|
+
queryString = otherParams;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Parse Sitecore error page format: /sitecore/service/notfound.aspx?item=core:{GUID}@en
|
|
277
|
+
if (href.includes('/sitecore/service/notfound.aspx?item=') && !itemId) {
|
|
278
|
+
const urlParams = new URLSearchParams(href.split('?')[1]);
|
|
279
|
+
const itemParam = urlParams.get('item');
|
|
280
|
+
if (itemParam) {
|
|
281
|
+
// Decode URL encoding
|
|
282
|
+
const decodedItem = decodeURIComponent(itemParam);
|
|
283
|
+
|
|
284
|
+
// Extract GUID from format like: core:{B84A7A3D-8ED4-4336-BE4F-94D3C38C9E9F}@en
|
|
285
|
+
const guidMatch = decodedItem.match(/\{([A-F0-9-]{36})\}/i);
|
|
286
|
+
if (guidMatch && guidMatch[1]) {
|
|
287
|
+
itemId = guidMatch[1].toLowerCase();
|
|
288
|
+
targetItemLongId = itemId;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
248
292
|
|
|
249
293
|
const linkChildren = processNodeWithInlines(childElement, configuredMarks);
|
|
250
294
|
|
|
251
|
-
|
|
295
|
+
const linkElement = {
|
|
252
296
|
type: 'link',
|
|
253
297
|
url: href,
|
|
254
298
|
link: {
|
|
@@ -257,6 +301,33 @@ const htmlToSlateInternal = (html: string, profile: SimplifiedProfile): Descenda
|
|
|
257
301
|
target,
|
|
258
302
|
itemId,
|
|
259
303
|
targetItemLongId,
|
|
304
|
+
queryString,
|
|
305
|
+
originalHref: (href.includes('~/link.aspx?_id=') && !href.includes('/sitecore/service/notfound.aspx')) ? href : undefined // Preserve original Sitecore href, but not error pages
|
|
306
|
+
},
|
|
307
|
+
children: linkChildren.length ? linkChildren : [{ text: childElement.textContent || 'Link' }]
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
results.push(linkElement);
|
|
312
|
+
} else if (tagName === 'link') {
|
|
313
|
+
// Handle Sitecore XML link tags
|
|
314
|
+
const linktype = childElement.getAttribute('linktype') || '';
|
|
315
|
+
const itemId = childElement.getAttribute('id') || '';
|
|
316
|
+
const target = childElement.getAttribute('target') || '_self';
|
|
317
|
+
const queryString = childElement.getAttribute('querystring') || '';
|
|
318
|
+
const url = childElement.getAttribute('url') || '';
|
|
319
|
+
|
|
320
|
+
const linkChildren = processNodeWithInlines(childElement, configuredMarks);
|
|
321
|
+
|
|
322
|
+
results.push({
|
|
323
|
+
type: 'link',
|
|
324
|
+
url: linktype === 'internal' ? '' : url,
|
|
325
|
+
link: {
|
|
326
|
+
type: linktype === 'internal' ? 'internal' : 'external',
|
|
327
|
+
url: linktype === 'internal' ? '' : url,
|
|
328
|
+
target,
|
|
329
|
+
itemId: linktype === 'internal' ? itemId : '',
|
|
330
|
+
targetItemLongId: linktype === 'internal' ? itemId : '',
|
|
260
331
|
queryString
|
|
261
332
|
},
|
|
262
333
|
children: linkChildren.length ? linkChildren : [{ text: childElement.textContent || 'Link' }]
|
|
@@ -312,14 +383,56 @@ const htmlToSlateInternal = (html: string, profile: SimplifiedProfile): Descenda
|
|
|
312
383
|
} else if (tagName === 'a') {
|
|
313
384
|
const href = childElement.getAttribute('href') || '';
|
|
314
385
|
const target = childElement.getAttribute('target') || '_self';
|
|
315
|
-
const isInternal = childElement.hasAttribute('data-internal')
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
386
|
+
const isInternal = childElement.hasAttribute('data-internal') ||
|
|
387
|
+
href.includes('~/link.aspx?_id=') ||
|
|
388
|
+
href.includes('/sitecore/service/notfound.aspx?item=');
|
|
389
|
+
|
|
390
|
+
let itemId = childElement.getAttribute('data-item-id') || '';
|
|
391
|
+
let targetItemLongId = childElement.getAttribute('data-item-longid') || '';
|
|
392
|
+
let queryString = childElement.getAttribute('data-querystring') || '';
|
|
393
|
+
|
|
394
|
+
// Parse standard Sitecore RTE format: ~/link.aspx?_id=GUID&_z=z
|
|
395
|
+
if (href.includes('~/link.aspx?_id=') && !itemId) {
|
|
396
|
+
// Decode HTML entities (e.g., & to &) before parsing
|
|
397
|
+
const decodedHref = href.replace(/&/g, '&');
|
|
398
|
+
const queryString_raw = decodedHref.split('?')[1];
|
|
399
|
+
|
|
400
|
+
const urlParams = new URLSearchParams(queryString_raw);
|
|
401
|
+
const id = urlParams.get('_id');
|
|
402
|
+
if (id) {
|
|
403
|
+
// Convert GUID format back to standard format with dashes
|
|
404
|
+
itemId = id.replace(/(\w{8})(\w{4})(\w{4})(\w{4})(\w{12})/, '$1-$2-$3-$4-$5').toLowerCase();
|
|
405
|
+
targetItemLongId = itemId;
|
|
406
|
+
|
|
407
|
+
// Extract other query parameters (excluding _id and _z)
|
|
408
|
+
const otherParams = Array.from(urlParams.entries())
|
|
409
|
+
.filter(([key]) => key !== '_id' && key !== '_z')
|
|
410
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
411
|
+
.join('&');
|
|
412
|
+
queryString = otherParams;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Parse Sitecore error page format: /sitecore/service/notfound.aspx?item=core:{GUID}@en
|
|
417
|
+
if (href.includes('/sitecore/service/notfound.aspx?item=') && !itemId) {
|
|
418
|
+
const urlParams = new URLSearchParams(href.split('?')[1]);
|
|
419
|
+
const itemParam = urlParams.get('item');
|
|
420
|
+
if (itemParam) {
|
|
421
|
+
// Decode URL encoding
|
|
422
|
+
const decodedItem = decodeURIComponent(itemParam);
|
|
423
|
+
|
|
424
|
+
// Extract GUID from format like: core:{B84A7A3D-8ED4-4336-BE4F-94D3C38C9E9F}@en
|
|
425
|
+
const guidMatch = decodedItem.match(/\{([A-F0-9-]{36})\}/i);
|
|
426
|
+
if (guidMatch && guidMatch[1]) {
|
|
427
|
+
itemId = guidMatch[1].toLowerCase();
|
|
428
|
+
targetItemLongId = itemId;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
319
432
|
|
|
320
433
|
const linkChildren = processNodeWithInlines(childElement, configuredMarks);
|
|
321
434
|
|
|
322
|
-
|
|
435
|
+
const linkElement = {
|
|
323
436
|
type: 'link',
|
|
324
437
|
url: href,
|
|
325
438
|
link: {
|
|
@@ -328,6 +441,33 @@ const htmlToSlateInternal = (html: string, profile: SimplifiedProfile): Descenda
|
|
|
328
441
|
target,
|
|
329
442
|
itemId,
|
|
330
443
|
targetItemLongId,
|
|
444
|
+
queryString,
|
|
445
|
+
originalHref: (href.includes('~/link.aspx?_id=') && !href.includes('/sitecore/service/notfound.aspx')) ? href : undefined // Preserve original Sitecore href, but not error pages
|
|
446
|
+
},
|
|
447
|
+
children: linkChildren.length ? linkChildren : [{ text: childElement.textContent || 'Link' }]
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
results.push(linkElement);
|
|
452
|
+
} else if (tagName === 'link') {
|
|
453
|
+
// Handle Sitecore XML link tags
|
|
454
|
+
const linktype = childElement.getAttribute('linktype') || '';
|
|
455
|
+
const itemId = childElement.getAttribute('id') || '';
|
|
456
|
+
const target = childElement.getAttribute('target') || '_self';
|
|
457
|
+
const queryString = childElement.getAttribute('querystring') || '';
|
|
458
|
+
const url = childElement.getAttribute('url') || '';
|
|
459
|
+
|
|
460
|
+
const linkChildren = processNodeWithInlines(childElement, configuredMarks);
|
|
461
|
+
|
|
462
|
+
results.push({
|
|
463
|
+
type: 'link',
|
|
464
|
+
url: linktype === 'internal' ? '' : url,
|
|
465
|
+
link: {
|
|
466
|
+
type: linktype === 'internal' ? 'internal' : 'external',
|
|
467
|
+
url: linktype === 'internal' ? '' : url,
|
|
468
|
+
target,
|
|
469
|
+
itemId: linktype === 'internal' ? itemId : '',
|
|
470
|
+
targetItemLongId: linktype === 'internal' ? itemId : '',
|
|
331
471
|
queryString
|
|
332
472
|
},
|
|
333
473
|
children: linkChildren.length ? linkChildren : [{ text: childElement.textContent || 'Link' }]
|
|
@@ -619,12 +759,26 @@ const slateToHtmlInternal = (value: Descendant[], profile: SimplifiedProfile): s
|
|
|
619
759
|
|
|
620
760
|
if (isInternal) {
|
|
621
761
|
const itemId = linkElement.link?.itemId || '';
|
|
622
|
-
const targetItemLongId = linkElement.link?.targetItemLongId || '';
|
|
623
762
|
const target = linkElement.link?.target || '_self';
|
|
624
763
|
const queryString = linkElement.link?.queryString || '';
|
|
625
|
-
|
|
764
|
+
const originalHref = (linkElement.link as any)?.originalHref;
|
|
765
|
+
|
|
766
|
+
let href;
|
|
767
|
+
if (originalHref) {
|
|
768
|
+
// Use original Sitecore RTE href to preserve exact format
|
|
769
|
+
href = originalHref;
|
|
770
|
+
} else {
|
|
771
|
+
// Generate standard Sitecore RTE format for new links
|
|
772
|
+
href = `~/link.aspx?_id=${itemId.replace(/-/g, '').toUpperCase()}&_z=z`;
|
|
773
|
+
if (queryString) {
|
|
774
|
+
href += `&${queryString}`;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
result += `<a href="${href}" target="${target}">${linkText}</a>`;
|
|
626
779
|
} else {
|
|
627
|
-
const
|
|
780
|
+
const rawUrl = linkElement.url || linkElement.link?.url || '#';
|
|
781
|
+
const url = normalizeUrl(rawUrl);
|
|
628
782
|
const target = linkElement.link?.target || '_self';
|
|
629
783
|
const queryString = linkElement.link?.queryString || '';
|
|
630
784
|
result += `<a href="${url}" target="${target}" data-querystring="${queryString}">${linkText}</a>`;
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
SLATE_MARKS,
|
|
10
10
|
SLATE_BLOCKS,
|
|
11
11
|
} from "../types";
|
|
12
|
+
import { normalizeUrl } from "../../../utils/urlUtils";
|
|
12
13
|
|
|
13
14
|
// Hot key utility function
|
|
14
15
|
export const isHotkey = (hotkey: string, event: React.KeyboardEvent): boolean => {
|
|
@@ -146,7 +147,7 @@ export const withLink = (editor: Editor) => {
|
|
|
146
147
|
|
|
147
148
|
editor.insertText = (text: string) => {
|
|
148
149
|
if (text && isUrl(text)) {
|
|
149
|
-
wrapLink(editor, text);
|
|
150
|
+
wrapLink(editor, normalizeUrl(text));
|
|
150
151
|
} else {
|
|
151
152
|
insertText(text);
|
|
152
153
|
}
|
|
@@ -156,7 +157,7 @@ export const withLink = (editor: Editor) => {
|
|
|
156
157
|
const text = data.getData('text/plain');
|
|
157
158
|
|
|
158
159
|
if (text && isUrl(text)) {
|
|
159
|
-
wrapLink(editor, text);
|
|
160
|
+
wrapLink(editor, normalizeUrl(text));
|
|
160
161
|
} else {
|
|
161
162
|
insertData(data);
|
|
162
163
|
}
|
|
@@ -586,10 +587,29 @@ const isUrl = (text: string): boolean => {
|
|
|
586
587
|
new URL(text);
|
|
587
588
|
return true;
|
|
588
589
|
} catch {
|
|
589
|
-
|
|
590
|
+
// Check if it looks like a domain without protocol (like www.nivea.de, nivea.com)
|
|
591
|
+
const domainPattern = /^([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}(\/.*)?$/;
|
|
592
|
+
return domainPattern.test(text);
|
|
590
593
|
}
|
|
591
594
|
};
|
|
592
595
|
|
|
596
|
+
|
|
597
|
+
export const generateInternalLinkUrl = (itemId?: string, targetItemLongId?: string, queryString?: string): string => {
|
|
598
|
+
if (!itemId && !targetItemLongId) {
|
|
599
|
+
return '#';
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// Use itemId if available, otherwise fall back to targetItemLongId
|
|
603
|
+
const id = itemId || targetItemLongId;
|
|
604
|
+
let url = `/items/${id}`;
|
|
605
|
+
|
|
606
|
+
if (queryString) {
|
|
607
|
+
url += `?${queryString}`;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
return url;
|
|
611
|
+
};
|
|
612
|
+
|
|
593
613
|
const wrapLink = (editor: Editor, url: string, linkData?: any): void => {
|
|
594
614
|
if (editor.isLinkActive()) {
|
|
595
615
|
unwrapLink(editor);
|
|
@@ -605,7 +625,7 @@ const wrapLink = (editor: Editor, url: string, linkData?: any): void => {
|
|
|
605
625
|
url,
|
|
606
626
|
target: '_blank',
|
|
607
627
|
},
|
|
608
|
-
children: isCollapsed ? [{ text: url }] : [],
|
|
628
|
+
children: isCollapsed ? [{ text: url }] : [{ text: '' }], // Use placeholder for selected text
|
|
609
629
|
};
|
|
610
630
|
|
|
611
631
|
if (isCollapsed) {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL utility functions for the editor
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Normalizes a URL by adding https:// protocol if missing for domain-like strings
|
|
7
|
+
* @param text - The text to normalize
|
|
8
|
+
* @returns The normalized URL
|
|
9
|
+
*/
|
|
10
|
+
export const normalizeUrl = (text: string): string => {
|
|
11
|
+
if (!text) return text;
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
new URL(text);
|
|
15
|
+
return text; // Already a valid URL
|
|
16
|
+
} catch {
|
|
17
|
+
// Check if it looks like a domain without protocol
|
|
18
|
+
const domainPattern = /^([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}(\/.*)?$/;
|
|
19
|
+
if (domainPattern.test(text)) {
|
|
20
|
+
return `https://${text}`;
|
|
21
|
+
}
|
|
22
|
+
return text; // Return as is if not a recognizable domain
|
|
23
|
+
}
|
|
24
|
+
};
|
package/src/editor/utils.ts
CHANGED
|
@@ -539,3 +539,36 @@ export function findClosestFieldElement(node: Node | null): HTMLElement | null {
|
|
|
539
539
|
|
|
540
540
|
return null;
|
|
541
541
|
}
|
|
542
|
+
|
|
543
|
+
// GUID helpers for clipboard parsing and validation
|
|
544
|
+
export const GUID_REGEX_GLOBAL =
|
|
545
|
+
/[\{\(]?[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}[\}\)]?/g;
|
|
546
|
+
export const GUID_REGEX_EXACT =
|
|
547
|
+
/^[\{\(]?[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}[\}\)]?$/;
|
|
548
|
+
// Non-global regex for quick containment checks (avoids lastIndex issues with .test on /g)
|
|
549
|
+
export const GUID_REGEX_CONTAINS =
|
|
550
|
+
/[\{\(]?[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}[\}\)]?/;
|
|
551
|
+
|
|
552
|
+
export function containsGuidInText(text: string | undefined | null): boolean {
|
|
553
|
+
if (!text) return false;
|
|
554
|
+
return GUID_REGEX_CONTAINS.test(text);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
export function findGuidsInText(text: string | undefined | null): string[] {
|
|
558
|
+
if (!text) return [];
|
|
559
|
+
const matches = text.match(GUID_REGEX_GLOBAL) || [];
|
|
560
|
+
const normalized = matches
|
|
561
|
+
.map((m) => m.replace(/[{}()]/g, ""))
|
|
562
|
+
.filter((m) => !!m)
|
|
563
|
+
.map((m) => normalizeGuid(m));
|
|
564
|
+
// Deduplicate while preserving order
|
|
565
|
+
const seen = new Set<string>();
|
|
566
|
+
const unique: string[] = [];
|
|
567
|
+
for (const id of normalized) {
|
|
568
|
+
if (!seen.has(id)) {
|
|
569
|
+
seen.add(id);
|
|
570
|
+
unique.push(id);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
return unique;
|
|
574
|
+
}
|
package/src/revision.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const version = "1.0.
|
|
2
|
-
export const buildDate = "2025-09-
|
|
1
|
+
export const version = "1.0.4086";
|
|
2
|
+
export const buildDate = "2025-09-12 01:46:21";
|