or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

editor-enhancements.mdhooks-state.mdindex.mdplugin-configuration.mdreact-components.mdtransforms-utilities.mdtypes-interfaces.md

transforms-utilities.mddocs/

0

# Transforms and Utilities

1

2

Functions for programmatically inserting images and utility functions for image URL validation.

3

4

## Capabilities

5

6

### Image Insertion Transform

7

8

Function for programmatically inserting image elements into the Plate editor.

9

10

```typescript { .api }

11

/**

12

* Inserts an image element at the current cursor position

13

* Creates a properly structured image element with the provided URL

14

* @param editor - Plate editor instance

15

* @param url - Image URL (string) or data (ArrayBuffer) to insert

16

*/

17

function insertImage<V extends Value>(

18

editor: PlateEditor<V>,

19

url: string | ArrayBuffer

20

): void;

21

```

22

23

**Element Creation:**

24

- Creates `TImageElement` with proper type and structure

25

- Sets URL from provided parameter

26

- Adds empty text child node (required by Slate)

27

- Inserts at current selection or cursor position

28

29

**Usage Examples:**

30

31

```typescript

32

import { insertImage } from "@udecode/plate-image";

33

import { useEditorRef } from "@udecode/plate-core";

34

35

// Insert image from URL

36

function InsertImageButton({ imageUrl }: { imageUrl: string }) {

37

const editor = useEditorRef();

38

39

const handleInsert = () => {

40

insertImage(editor, imageUrl);

41

};

42

43

return (

44

<button onClick={handleInsert}>

45

Insert Image

46

</button>

47

);

48

}

49

50

// Insert multiple images

51

function InsertImageGallery({ imageUrls }: { imageUrls: string[] }) {

52

const editor = useEditorRef();

53

54

const insertGallery = () => {

55

imageUrls.forEach((url, index) => {

56

// Insert with slight delay to ensure proper positioning

57

setTimeout(() => {

58

insertImage(editor, url);

59

}, index * 100);

60

});

61

};

62

63

return (

64

<button onClick={insertGallery}>

65

Insert Gallery ({imageUrls.length} images)

66

</button>

67

);

68

}

69

70

// Insert image from file upload

71

function FileUploadImageInserter() {

72

const editor = useEditorRef();

73

74

const handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>) => {

75

const file = event.target.files?.[0];

76

if (file && file.type.startsWith('image/')) {

77

const reader = new FileReader();

78

reader.onload = (e) => {

79

if (e.target?.result) {

80

insertImage(editor, e.target.result as string);

81

}

82

};

83

reader.readAsDataURL(file);

84

}

85

};

86

87

return (

88

<input

89

type="file"

90

accept="image/*"

91

onChange={handleFileUpload}

92

/>

93

);

94

}

95

96

// Insert with custom image processing

97

async function insertProcessedImage(

98

editor: PlateEditor,

99

rawImageData: string | ArrayBuffer

100

) {

101

try {

102

// Process or upload image first

103

const processedUrl = await processImageData(rawImageData);

104

insertImage(editor, processedUrl);

105

} catch (error) {

106

console.error('Failed to process image:', error);

107

// Fallback to raw data

108

insertImage(editor, rawImageData);

109

}

110

}

111

```

112

113

### Image URL Validation Utility

114

115

Utility function to determine if a given URL points to an image file based on file extension.

116

117

```typescript { .api }

118

/**

119

* Checks if a URL points to an image file

120

* Validates both URL format and file extension against comprehensive image format list

121

* @param url - URL string to validate

122

* @returns Boolean indicating whether URL is a valid image URL

123

*/

124

function isImageUrl(url: string): boolean;

125

```

126

127

**Validation Process:**

128

1. **URL Format**: Checks if string is a valid URL using `isUrl` helper

129

2. **Extension Extraction**: Extracts file extension from URL pathname

130

3. **Format Check**: Compares extension against comprehensive list of image formats

131

132

**Supported Image Formats:**

133

- **Common formats**: jpg, jpeg, png, gif, webp, svg, bmp, tiff, ico

134

- **Raw formats**: cr2, raw, dng, nef, arw

135

- **Professional formats**: psd, ai, eps, xcf

136

- **Specialized formats**: Many additional formats (120+ total)

137

138

**Usage Examples:**

139

140

```typescript

141

import { isImageUrl } from "@udecode/plate-image";

142

143

// Basic URL validation

144

const urls = [

145

'https://example.com/image.jpg', // true

146

'https://example.com/image.png', // true

147

'https://example.com/document.pdf', // false

148

'not-a-url', // false

149

'https://example.com/image.webp', // true

150

];

151

152

urls.forEach(url => {

153

console.log(`${url}: ${isImageUrl(url)}`);

154

});

155

156

// Use in paste handler

157

function handlePaste(event: ClipboardEvent) {

158

const text = event.clipboardData?.getData('text/plain');

159

160

if (text && isImageUrl(text)) {

161

console.log('Pasted text is an image URL:', text);

162

insertImage(editor, text);

163

event.preventDefault();

164

}

165

}

166

167

// Filter image URLs from mixed content

168

function filterImageUrls(urls: string[]): string[] {

169

return urls.filter(isImageUrl);

170

}

171

172

// Validate before insertion

173

function safeInsertImage(editor: PlateEditor, url: string) {

174

if (isImageUrl(url)) {

175

insertImage(editor, url);

176

return true;

177

} else {

178

console.warn('Invalid image URL:', url);

179

return false;

180

}

181

}

182

183

// Custom validation with fallback

184

function validateAndInsertImage(editor: PlateEditor, url: string) {

185

if (isImageUrl(url)) {

186

insertImage(editor, url);

187

} else {

188

// Try to detect image by MIME type or other means

189

fetch(url, { method: 'HEAD' })

190

.then(response => {

191

const contentType = response.headers.get('content-type');

192

if (contentType?.startsWith('image/')) {

193

insertImage(editor, url);

194

} else {

195

console.error('URL does not point to an image');

196

}

197

})

198

.catch(error => {

199

console.error('Failed to validate URL:', error);

200

});

201

}

202

}

203

```

204

205

## Advanced Transform Patterns

206

207

### Batch Image Operations

208

209

```typescript

210

import { insertImage, isImageUrl } from "@udecode/plate-image";

211

import { Transforms } from "slate";

212

213

// Insert multiple images with spacing

214

async function insertImageBatch(

215

editor: PlateEditor,

216

urls: string[],

217

spacing: boolean = true

218

) {

219

const validUrls = urls.filter(isImageUrl);

220

221

for (let i = 0; i < validUrls.length; i++) {

222

insertImage(editor, validUrls[i]);

223

224

if (spacing && i < validUrls.length - 1) {

225

// Insert paragraph between images

226

Transforms.insertNodes(editor, {

227

type: 'p',

228

children: [{ text: '' }]

229

});

230

}

231

}

232

}

233

234

// Replace selected content with image

235

function replaceSelectionWithImage(editor: PlateEditor, url: string) {

236

if (isImageUrl(url)) {

237

// Delete current selection

238

if (editor.selection) {

239

Transforms.delete(editor);

240

}

241

insertImage(editor, url);

242

}

243

}

244

```

245

246

### Integration with Upload Systems

247

248

```typescript

249

// Insert image with upload progress tracking

250

async function insertImageWithUpload(

251

editor: PlateEditor,

252

file: File,

253

onProgress?: (percent: number) => void

254

) {

255

try {

256

// Create temporary data URL for immediate display

257

const reader = new FileReader();

258

reader.onload = (e) => {

259

if (e.target?.result) {

260

insertImage(editor, e.target.result as string);

261

}

262

};

263

reader.readAsDataURL(file);

264

265

// Upload file and replace with final URL

266

const uploadedUrl = await uploadWithProgress(file, onProgress);

267

268

// Replace temporary image with uploaded version

269

// (Implementation would need to track and update the specific image)

270

271

} catch (error) {

272

console.error('Upload failed:', error);

273

}

274

}

275

276

// Utility for drag-and-drop integration

277

function handleImageDrop(

278

editor: PlateEditor,

279

event: DragEvent,

280

uploadFunction?: (file: File) => Promise<string>

281

) {

282

event.preventDefault();

283

284

const files = Array.from(event.dataTransfer?.files || []);

285

const imageFiles = files.filter(file => file.type.startsWith('image/'));

286

287

imageFiles.forEach(async (file) => {

288

if (uploadFunction) {

289

try {

290

const url = await uploadFunction(file);

291

insertImage(editor, url);

292

} catch (error) {

293

// Fallback to data URL

294

const reader = new FileReader();

295

reader.onload = (e) => {

296

if (e.target?.result) {

297

insertImage(editor, e.target.result as string);

298

}

299

};

300

reader.readAsDataURL(file);

301

}

302

} else {

303

// Direct data URL insertion

304

const reader = new FileReader();

305

reader.onload = (e) => {

306

if (e.target?.result) {

307

insertImage(editor, e.target.result as string);

308

}

309

};

310

reader.readAsDataURL(file);

311

}

312

});

313

}

314

```

315

316

### Error Handling and Validation

317

318

```typescript

319

// Robust image insertion with validation and error handling

320

async function safeInsertImage(

321

editor: PlateEditor,

322

urlOrData: string | ArrayBuffer,

323

options?: {

324

validateUrl?: boolean;

325

maxSize?: number;

326

allowedFormats?: string[];

327

}

328

) {

329

try {

330

// Validate URL if it's a string

331

if (typeof urlOrData === 'string') {

332

if (options?.validateUrl && !isImageUrl(urlOrData)) {

333

throw new Error('Invalid image URL format');

334

}

335

336

// Optional: Check if URL is accessible

337

if (options?.validateUrl) {

338

const response = await fetch(urlOrData, { method: 'HEAD' });

339

if (!response.ok) {

340

throw new Error(`Image URL not accessible: ${response.status}`);

341

}

342

}

343

}

344

345

// Insert the image

346

insertImage(editor, urlOrData);

347

return true;

348

349

} catch (error) {

350

console.error('Failed to insert image:', error);

351

352

// Optional: Show user-friendly error message

353

if (typeof urlOrData === 'string') {

354

console.log('Failed URL:', urlOrData);

355

}

356

357

return false;

358

}

359

}

360

```