@@ -21,6 +21,25 @@ export function downloadFile(url: string | undefined | null, filename: string) {
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
|
||||
export function externalLinkProps(url: string): {
|
||||
href: string | undefined;
|
||||
target: "_blank";
|
||||
rel: "noopener noreferrer";
|
||||
} {
|
||||
let safeHref: string | undefined;
|
||||
try {
|
||||
const parsed = new URL(url);
|
||||
if (parsed.protocol === "http:" || parsed.protocol === "https:") {
|
||||
safeHref = url;
|
||||
} else {
|
||||
console.error("Invalid URL protocol. Only HTTP and HTTPS URLs are allowed:", url);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Invalid URL format:", url, error);
|
||||
}
|
||||
return { href: safeHref, target: "_blank", rel: "noopener noreferrer" };
|
||||
}
|
||||
|
||||
export function safeOpenUrl(url: string) {
|
||||
try {
|
||||
const parsedUrl = new URL(url);
|
||||
|
||||
@@ -13,6 +13,7 @@ export {
|
||||
export {
|
||||
withViewTransition,
|
||||
downloadFile,
|
||||
externalLinkProps,
|
||||
safeOpenUrl,
|
||||
focusSiblingElement,
|
||||
} from "./dom";
|
||||
@@ -78,6 +79,7 @@ export {
|
||||
parseDate,
|
||||
} from "./date";
|
||||
export { getTrustCenterUrl } from "./trustCenter";
|
||||
export { detectSocialName } from "./socialUrl";
|
||||
export { formatError, type GraphQLError } from "./error";
|
||||
export { Role, roles, getAssignableRoles } from "./roles";
|
||||
export {
|
||||
|
||||
12
packages/helpers/src/socialUrl.ts
Normal file
12
packages/helpers/src/socialUrl.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
const SOCIAL_PATTERNS: Array<[RegExp, string]> = [
|
||||
[/linkedin\.com/i, "LinkedIn"],
|
||||
[/(?:twitter|x)\.com/i, "X"],
|
||||
[/facebook\.com/i, "Facebook"],
|
||||
];
|
||||
|
||||
export function detectSocialName(url: string): string | null {
|
||||
for (const [pattern, name] of SOCIAL_PATTERNS) {
|
||||
if (pattern.test(url)) return name;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user