var Buffer = require('buffer/').Buffer; const ATTRIBUTE_WHITESPACES: RegExp = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g; const SAFE_URL: RegExp = /^(?:(?:https?|ftps?|mailto):|[^a-z]|[a-z+.-]+(?:[^a-z+.:-]|$))/i; const EMAIL_REG_EXP: RegExp = /^[\S]+@((?![-_])(?:[-\w\u00a1-\uffff]{0,63}[^-_]\.))+(?:[a-z\u00a1-\uffff]{2,})$/i; const PROTOCOL_REG_EXP: RegExp = /^((\w+:(\/{2,})?)|(\W))/i; export const LINK_KEYSTROKE: string = 'Ctrl+K'; export const ATTRIBUTE_NAME: string = 'linkHref'; export function isLinkElement(node: any) { return node.is('attributeElement') && !!node.getCustomProperty('link'); } export function createLinkElement(data: any, { writer }: { writer: any }) { const linkElement = writer.createAttributeElement( 'a', { href: data?.href, ['data-internal-link']: data?.json }, { priority: 5 } ); writer.setCustomProperty('link', true, linkElement); return linkElement; } export function ensureSafeUrl(url: string) { url = String(url); return isSafeUrl(url) ? url : '#'; } function isSafeUrl(url: string) { const normalizedUrl = url.replace(ATTRIBUTE_WHITESPACES, ''); return normalizedUrl.match(SAFE_URL); } export function isLinkableElement(element: any, schema: any) { if (!element) { return false; } return schema.checkAttribute(element.name, ATTRIBUTE_NAME); } export function isEmail(value: string) { return EMAIL_REG_EXP.test(value); } export function addLinkProtocolIfApplicable(link: string, defaultProtocol: string) { const protocol = isEmail(link) ? 'mailto:' : defaultProtocol; const isProtocolNeeded = !!protocol && !linkHasProtocol(link); return link && isProtocolNeeded ? protocol + link : link; } export function linkHasProtocol(link: string) { return PROTOCOL_REG_EXP.test(link); } export function openLink(link: string) { window.open(link, '_blank', 'noopener'); } export function encodeAttributes(attributeObject: { id?: null | number; sourceContentTypeUid?: string; sourceContentTypeId?: number; sourceFieldName?: string; targetContentTypeUid?: string; targetContentTypeId?: string; url?: string; text?: string; type?: string; domain?: string; urlAddition?: string; }) { if (!attributeObject) return ''; if (attributeObject?.text) { attributeObject.text = encodeURIComponent(attributeObject.text); } try { const json = JSON.stringify(attributeObject); const encodedJson = Buffer.from(json).toString('base64'); return encodedJson; } catch (error) { console.error('Error in encodeAttributes', error); return ''; } } export function decodeAttributes(base64String?: string) { if (!base64String) return undefined; try { const decodedJson = Buffer.from(base64String, 'base64').toString('ascii'); const parsedJSON = JSON.parse(decodedJson); if (parsedJSON?.text) { parsedJSON.text = decodeURIComponent(parsedJSON.text); } return parsedJSON; } catch (error) { console.error('Error in decodeAttributes', error); const decodedLink = Buffer.from(base64String, 'base64').toString('ascii'); // Sanitze the link if there are any control characters const sanitizedLink = decodedLink.replaceAll(/[\u0000-\u0019]/g, ''); return JSON.parse(sanitizedLink); } }