mirror of
https://github.com/facebook/lexical.git
synced 2025-05-17 15:18:47 +08:00
[lexical-markdown] Bug Fix: Link Transformer URL Protocol Handling (#7499)
This commit is contained in:

committed by
GitHub

parent
6c458e4289
commit
0aa2d5aa73
@ -37,6 +37,8 @@ import {
|
||||
TextNode,
|
||||
} from 'lexical';
|
||||
|
||||
import {formatUrl} from './utils';
|
||||
|
||||
export type Transformer =
|
||||
| ElementTransformer
|
||||
| MultilineElementTransformer
|
||||
@ -559,7 +561,8 @@ export const LINK: TextMatchTransformer = {
|
||||
/(?:\[([^[]+)\])(?:\((?:([^()\s]+)(?:\s"((?:[^"]*\\")*[^"]*)"\s*)?)\))$/,
|
||||
replace: (textNode, match) => {
|
||||
const [, linkText, linkUrl, linkTitle] = match;
|
||||
const linkNode = $createLinkNode(linkUrl, {title: linkTitle});
|
||||
const formattedUrl = formatUrl(linkUrl);
|
||||
const linkNode = $createLinkNode(formattedUrl, {title: linkTitle});
|
||||
const linkTextNode = $createTextNode(linkText);
|
||||
linkTextNode.setFormat(textNode.getFormat());
|
||||
linkNode.append(linkTextNode);
|
||||
|
@ -27,6 +27,7 @@ import {
|
||||
MultilineElementTransformer,
|
||||
normalizeMarkdown,
|
||||
} from '../../MarkdownTransformers';
|
||||
import {formatUrl} from '../../utils';
|
||||
|
||||
const SIMPLE_INLINE_JSX_MATCHER: TextMatchTransformer = {
|
||||
dependencies: [LinkNode],
|
||||
@ -888,3 +889,39 @@ E3
|
||||
expect(normalizeMarkdown(markdown, false)).toBe(markdown);
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatUrl', () => {
|
||||
it('should not modify URLs with protocols', () => {
|
||||
expect(formatUrl('https://example.com')).toBe('https://example.com');
|
||||
expect(formatUrl('http://example.com')).toBe('http://example.com');
|
||||
expect(formatUrl('mailto:user@example.com')).toBe(
|
||||
'mailto:user@example.com',
|
||||
);
|
||||
expect(formatUrl('tel:+1234567890')).toBe('tel:+1234567890');
|
||||
});
|
||||
|
||||
it('should not modify relative paths', () => {
|
||||
expect(formatUrl('/path/to/resource')).toBe('/path/to/resource');
|
||||
expect(formatUrl('/index.html')).toBe('/index.html');
|
||||
});
|
||||
|
||||
it('should add mailto: to email addresses', () => {
|
||||
expect(formatUrl('user@example.com')).toBe('mailto:user@example.com');
|
||||
expect(formatUrl('name.lastname@domain.co.uk')).toBe(
|
||||
'mailto:name.lastname@domain.co.uk',
|
||||
);
|
||||
});
|
||||
|
||||
it('should add tel: to phone numbers', () => {
|
||||
expect(formatUrl('+1234567890')).toBe('tel:+1234567890');
|
||||
expect(formatUrl('123-456-7890')).toBe('tel:123-456-7890');
|
||||
});
|
||||
|
||||
it('should add https:// to URLs without protocols', () => {
|
||||
expect(formatUrl('www.example.com')).toBe('https://www.example.com');
|
||||
expect(formatUrl('example.com')).toBe('https://example.com');
|
||||
expect(formatUrl('subdomain.example.com/path')).toBe(
|
||||
'https://subdomain.example.com/path',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -460,3 +460,37 @@ export function isEmptyParagraph(node: LexicalNode): boolean {
|
||||
MARKDOWN_EMPTY_LINE_REG_EXP.test(firstChild.getTextContent()))
|
||||
);
|
||||
}
|
||||
|
||||
export const PHONE_NUMBER_REGEX = /^\+?[0-9\s()-]{5,}$/;
|
||||
|
||||
/**
|
||||
* Formats a URL string by adding appropriate protocol if missing
|
||||
*
|
||||
* @param url - URL to format
|
||||
* @returns Formatted URL with appropriate protocol
|
||||
*/
|
||||
export function formatUrl(url: string): string {
|
||||
// Check if URL already has a protocol
|
||||
if (url.match(/^[a-z][a-z0-9+.-]*:/i)) {
|
||||
// URL already has a protocol, leave it as is
|
||||
return url;
|
||||
}
|
||||
// Check if it's a relative path (starting with '/', '.', or '#')
|
||||
else if (url.match(/^[/#.]/)) {
|
||||
// Relative path, leave it as is
|
||||
return url;
|
||||
}
|
||||
|
||||
// Check for email address
|
||||
else if (url.includes('@')) {
|
||||
return `mailto:${url}`;
|
||||
}
|
||||
|
||||
// Check for phone number
|
||||
else if (PHONE_NUMBER_REGEX.test(url)) {
|
||||
return `tel:${url}`;
|
||||
}
|
||||
|
||||
// For everything else, return with https:// prefix
|
||||
return `https://${url}`;
|
||||
}
|
||||
|
Reference in New Issue
Block a user