CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-udecode--plate-link

Link plugin for Plate rich text editor providing hyperlink functionality with URL validation, keyboard shortcuts, and UI components

Pending
Overview
Eval results
Files

url-utils.mddocs/

URL Utilities

URL utility functions provide robust URL processing, validation, and encoding/decoding capabilities with error handling and security considerations.

Capabilities

URL Validation

validateUrl

Validates URLs according to plugin configuration, allowing internal links and configured schemes.

/**
 * Validate a URL according to plugin configuration
 * @param editor - Slate editor instance for accessing configuration
 * @param url - URL string to validate
 * @returns Whether the URL is valid
 */
function validateUrl(editor: SlateEditor, url: string): boolean;

Usage Examples:

import { validateUrl } from "@udecode/plate-link";

// Basic validation
const isValid = validateUrl(editor, "https://example.com");
console.log(isValid); // true

// Internal links are allowed
const isInternalValid = validateUrl(editor, "/internal/page");
console.log(isInternalValid); // true

// Fragment links are allowed
const isFragmentValid = validateUrl(editor, "#section");
console.log(isFragmentValid); // true

// Scheme validation based on plugin config
const isMailtoValid = validateUrl(editor, "mailto:user@example.com");
// true if 'mailto' in allowedSchemes

Validation Rules:

  • Internal links starting with / are always valid
  • Fragment links starting with # are always valid
  • External URLs must match allowed schemes from plugin configuration
  • Empty or null URLs are invalid
  • Default allowed schemes: ['http', 'https', 'mailto', 'tel']

URL Encoding

encodeUrlIfNeeded

Conditionally encodes URLs that aren't already encoded, with graceful error handling.

/**
 * Encode URL if not already encoded, with error handling
 * @param url - URL string to potentially encode
 * @returns Encoded URL string
 */
function encodeUrlIfNeeded(url: string): string;

Usage Examples:

import { encodeUrlIfNeeded } from "@udecode/plate-link";

// Encode spaces and special characters
const encoded = encodeUrlIfNeeded("https://example.com/path with spaces");
console.log(encoded); // "https://example.com/path%20with%20spaces"

// Already encoded URLs are left unchanged
const alreadyEncoded = encodeUrlIfNeeded("https://example.com/path%20encoded");
console.log(alreadyEncoded); // "https://example.com/path%20encoded"

// Handles malformed URLs gracefully
const malformed = encodeUrlIfNeeded("not-a-url");
console.log(malformed); // Returns original string if encoding fails

Encoding Behavior:

  • Only encodes if the URL isn't already encoded
  • Handles URI component encoding errors gracefully
  • Returns original string if encoding fails
  • Preserves scheme and domain structure

URL Decoding

safeDecodeUrl

Safely decodes URLs with error handling, returning the original URL if decoding fails.

/**
 * Safely decode a URL with error handling
 * @param url - URL string to decode
 * @returns Decoded URL string, or original if decoding fails
 */
function safeDecodeUrl(url: string): string;

Usage Examples:

import { safeDecodeUrl } from "@udecode/plate-link";

// Decode percent-encoded URLs
const decoded = safeDecodeUrl("https://example.com/path%20with%20spaces");
console.log(decoded); // "https://example.com/path with spaces"

// Handles malformed encoded URLs
const malformed = safeDecodeUrl("https://example.com/bad%encoding");
console.log(malformed); // Returns original string if decoding fails

// Already decoded URLs pass through
const plainUrl = safeDecodeUrl("https://example.com/plain-path");
console.log(plainUrl); // "https://example.com/plain-path"

Decoding Safety:

  • Catches URI decoding errors gracefully
  • Returns original URL if decoding fails
  • Prevents crashes from malformed encoded URLs
  • Handles edge cases in percent encoding

Link Attributes

getLinkAttributes

Generates proper HTML attributes for link elements, including sanitization and default attributes.

/**
 * Generate HTML attributes for link elements with sanitization
 * @param editor - Slate editor instance for configuration access
 * @param link - Link element to generate attributes for
 * @returns React anchor element attributes
 */
function getLinkAttributes(
  editor: SlateEditor, 
  link: TLinkElement
): React.AnchorHTMLAttributes<HTMLAnchorElement>;

Usage Examples:

import { getLinkAttributes } from "@udecode/plate-link";

// Basic attribute generation
const linkElement = {
  type: 'a',
  url: 'https://example.com',
  children: [{ text: 'Example' }]
};

const attributes = getLinkAttributes(editor, linkElement);
console.log(attributes);
// { href: 'https://example.com', target: '_blank', rel: 'noopener' }

// With custom target
const linkWithTarget = {
  type: 'a',
  url: 'https://example.com',
  target: '_self',
  children: [{ text: 'Example' }]
};

const customAttributes = getLinkAttributes(editor, linkWithTarget);
console.log(customAttributes);
// { href: 'https://example.com', target: '_self' }

Attribute Processing:

  • Applies URL encoding if needed
  • Merges plugin default attributes
  • Handles target attribute logic
  • Applies security attributes for external links
  • Respects dangerouslySkipSanitization option

Node Creation

createLinkNode

Creates properly formatted link nodes with validation and attribute processing.

/**
 * Create a properly formatted link node
 * @param editor - Slate editor instance
 * @param options - Link creation options
 * @returns Formatted link element
 */
function createLinkNode(
  editor: SlateEditor, 
  options: CreateLinkNodeOptions
): TLinkElement;

interface CreateLinkNodeOptions {
  /** The URL for the link */
  url: string;
  /** Child text nodes (defaults to URL as text) */
  children?: TText[];
  /** Link target attribute */
  target?: string;
  /** Text content (alternative to children) */
  text?: string;
}

Usage Examples:

import { createLinkNode } from "@udecode/plate-link";

// Create basic link node
const linkNode = createLinkNode(editor, {
  url: "https://example.com",
  text: "Example Link"
});

// Create with custom children
const customLink = createLinkNode(editor, {
  url: "https://example.com",
  children: [
    { text: "Visit ", bold: true },
    { text: "Example" }
  ]
});

// Create with target
const externalLink = createLinkNode(editor, {
  url: "https://external.com",
  text: "External Link",
  target: "_blank"
});

Advanced URL Processing

URL Scheme Detection

import { validateUrl } from "@udecode/plate-link";

function getUrlScheme(url: string): string | null {
  try {
    const urlObj = new URL(url);
    return urlObj.protocol.slice(0, -1); // Remove trailing colon
  } catch {
    return null;
  }
}

function isExternalUrl(url: string): boolean {
  return !url.startsWith('/') && !url.startsWith('#') && getUrlScheme(url) !== null;
}

URL Normalization

import { encodeUrlIfNeeded, safeDecodeUrl } from "@udecode/plate-link";

function normalizeUrl(url: string): string {
  // Decode first to handle double-encoding
  const decoded = safeDecodeUrl(url);
  
  // Re-encode to ensure proper encoding
  return encodeUrlIfNeeded(decoded);
}

function addProtocolIfNeeded(url: string): string {
  if (!url.includes('://') && !url.startsWith('/') && !url.startsWith('#')) {
    return `https://${url}`;
  }
  return url;
}

Batch URL Processing

import { validateUrl, encodeUrlIfNeeded } from "@udecode/plate-link";

function processUrls(editor: SlateEditor, urls: string[]): Array<{
  original: string;
  processed: string;
  isValid: boolean;
}> {
  return urls.map(url => {
    const processed = encodeUrlIfNeeded(url);
    const isValid = validateUrl(editor, processed);
    
    return {
      original: url,
      processed,
      isValid
    };
  });
}

Install with Tessl CLI

npx tessl i tessl/npm-udecode--plate-link

docs

core-plugin.md

floating-interface.md

index.md

react-components.md

react-integration.md

transforms.md

url-utils.md

tile.json