or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-plugin.mdfloating-interface.mdindex.mdreact-components.mdreact-integration.mdtransforms.mdurl-utils.md

url-utils.mddocs/

0

# URL Utilities

1

2

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

3

4

## Capabilities

5

6

### URL Validation

7

8

#### validateUrl

9

10

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

11

12

```typescript { .api }

13

/**

14

* Validate a URL according to plugin configuration

15

* @param editor - Slate editor instance for accessing configuration

16

* @param url - URL string to validate

17

* @returns Whether the URL is valid

18

*/

19

function validateUrl(editor: SlateEditor, url: string): boolean;

20

```

21

22

**Usage Examples:**

23

24

```typescript

25

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

26

27

// Basic validation

28

const isValid = validateUrl(editor, "https://example.com");

29

console.log(isValid); // true

30

31

// Internal links are allowed

32

const isInternalValid = validateUrl(editor, "/internal/page");

33

console.log(isInternalValid); // true

34

35

// Fragment links are allowed

36

const isFragmentValid = validateUrl(editor, "#section");

37

console.log(isFragmentValid); // true

38

39

// Scheme validation based on plugin config

40

const isMailtoValid = validateUrl(editor, "mailto:user@example.com");

41

// true if 'mailto' in allowedSchemes

42

```

43

44

**Validation Rules:**

45

46

- Internal links starting with `/` are always valid

47

- Fragment links starting with `#` are always valid

48

- External URLs must match allowed schemes from plugin configuration

49

- Empty or null URLs are invalid

50

- Default allowed schemes: `['http', 'https', 'mailto', 'tel']`

51

52

### URL Encoding

53

54

#### encodeUrlIfNeeded

55

56

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

57

58

```typescript { .api }

59

/**

60

* Encode URL if not already encoded, with error handling

61

* @param url - URL string to potentially encode

62

* @returns Encoded URL string

63

*/

64

function encodeUrlIfNeeded(url: string): string;

65

```

66

67

**Usage Examples:**

68

69

```typescript

70

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

71

72

// Encode spaces and special characters

73

const encoded = encodeUrlIfNeeded("https://example.com/path with spaces");

74

console.log(encoded); // "https://example.com/path%20with%20spaces"

75

76

// Already encoded URLs are left unchanged

77

const alreadyEncoded = encodeUrlIfNeeded("https://example.com/path%20encoded");

78

console.log(alreadyEncoded); // "https://example.com/path%20encoded"

79

80

// Handles malformed URLs gracefully

81

const malformed = encodeUrlIfNeeded("not-a-url");

82

console.log(malformed); // Returns original string if encoding fails

83

```

84

85

**Encoding Behavior:**

86

87

- Only encodes if the URL isn't already encoded

88

- Handles URI component encoding errors gracefully

89

- Returns original string if encoding fails

90

- Preserves scheme and domain structure

91

92

### URL Decoding

93

94

#### safeDecodeUrl

95

96

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

97

98

```typescript { .api }

99

/**

100

* Safely decode a URL with error handling

101

* @param url - URL string to decode

102

* @returns Decoded URL string, or original if decoding fails

103

*/

104

function safeDecodeUrl(url: string): string;

105

```

106

107

**Usage Examples:**

108

109

```typescript

110

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

111

112

// Decode percent-encoded URLs

113

const decoded = safeDecodeUrl("https://example.com/path%20with%20spaces");

114

console.log(decoded); // "https://example.com/path with spaces"

115

116

// Handles malformed encoded URLs

117

const malformed = safeDecodeUrl("https://example.com/bad%encoding");

118

console.log(malformed); // Returns original string if decoding fails

119

120

// Already decoded URLs pass through

121

const plainUrl = safeDecodeUrl("https://example.com/plain-path");

122

console.log(plainUrl); // "https://example.com/plain-path"

123

```

124

125

**Decoding Safety:**

126

127

- Catches URI decoding errors gracefully

128

- Returns original URL if decoding fails

129

- Prevents crashes from malformed encoded URLs

130

- Handles edge cases in percent encoding

131

132

### Link Attributes

133

134

#### getLinkAttributes

135

136

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

137

138

```typescript { .api }

139

/**

140

* Generate HTML attributes for link elements with sanitization

141

* @param editor - Slate editor instance for configuration access

142

* @param link - Link element to generate attributes for

143

* @returns React anchor element attributes

144

*/

145

function getLinkAttributes(

146

editor: SlateEditor,

147

link: TLinkElement

148

): React.AnchorHTMLAttributes<HTMLAnchorElement>;

149

```

150

151

**Usage Examples:**

152

153

```typescript

154

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

155

156

// Basic attribute generation

157

const linkElement = {

158

type: 'a',

159

url: 'https://example.com',

160

children: [{ text: 'Example' }]

161

};

162

163

const attributes = getLinkAttributes(editor, linkElement);

164

console.log(attributes);

165

// { href: 'https://example.com', target: '_blank', rel: 'noopener' }

166

167

// With custom target

168

const linkWithTarget = {

169

type: 'a',

170

url: 'https://example.com',

171

target: '_self',

172

children: [{ text: 'Example' }]

173

};

174

175

const customAttributes = getLinkAttributes(editor, linkWithTarget);

176

console.log(customAttributes);

177

// { href: 'https://example.com', target: '_self' }

178

```

179

180

**Attribute Processing:**

181

182

- Applies URL encoding if needed

183

- Merges plugin default attributes

184

- Handles target attribute logic

185

- Applies security attributes for external links

186

- Respects `dangerouslySkipSanitization` option

187

188

### Node Creation

189

190

#### createLinkNode

191

192

Creates properly formatted link nodes with validation and attribute processing.

193

194

```typescript { .api }

195

/**

196

* Create a properly formatted link node

197

* @param editor - Slate editor instance

198

* @param options - Link creation options

199

* @returns Formatted link element

200

*/

201

function createLinkNode(

202

editor: SlateEditor,

203

options: CreateLinkNodeOptions

204

): TLinkElement;

205

206

interface CreateLinkNodeOptions {

207

/** The URL for the link */

208

url: string;

209

/** Child text nodes (defaults to URL as text) */

210

children?: TText[];

211

/** Link target attribute */

212

target?: string;

213

/** Text content (alternative to children) */

214

text?: string;

215

}

216

```

217

218

**Usage Examples:**

219

220

```typescript

221

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

222

223

// Create basic link node

224

const linkNode = createLinkNode(editor, {

225

url: "https://example.com",

226

text: "Example Link"

227

});

228

229

// Create with custom children

230

const customLink = createLinkNode(editor, {

231

url: "https://example.com",

232

children: [

233

{ text: "Visit ", bold: true },

234

{ text: "Example" }

235

]

236

});

237

238

// Create with target

239

const externalLink = createLinkNode(editor, {

240

url: "https://external.com",

241

text: "External Link",

242

target: "_blank"

243

});

244

```

245

246

### Advanced URL Processing

247

248

#### URL Scheme Detection

249

250

```typescript

251

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

252

253

function getUrlScheme(url: string): string | null {

254

try {

255

const urlObj = new URL(url);

256

return urlObj.protocol.slice(0, -1); // Remove trailing colon

257

} catch {

258

return null;

259

}

260

}

261

262

function isExternalUrl(url: string): boolean {

263

return !url.startsWith('/') && !url.startsWith('#') && getUrlScheme(url) !== null;

264

}

265

```

266

267

#### URL Normalization

268

269

```typescript

270

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

271

272

function normalizeUrl(url: string): string {

273

// Decode first to handle double-encoding

274

const decoded = safeDecodeUrl(url);

275

276

// Re-encode to ensure proper encoding

277

return encodeUrlIfNeeded(decoded);

278

}

279

280

function addProtocolIfNeeded(url: string): string {

281

if (!url.includes('://') && !url.startsWith('/') && !url.startsWith('#')) {

282

return `https://${url}`;

283

}

284

return url;

285

}

286

```

287

288

#### Batch URL Processing

289

290

```typescript

291

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

292

293

function processUrls(editor: SlateEditor, urls: string[]): Array<{

294

original: string;

295

processed: string;

296

isValid: boolean;

297

}> {

298

return urls.map(url => {

299

const processed = encodeUrlIfNeeded(url);

300

const isValid = validateUrl(editor, processed);

301

302

return {

303

original: url,

304

processed,

305

isValid

306

};

307

});

308

}

309

```