A hyperscript helper for creating Slate documents with JSX-like syntax.
npx @tessl/cli install tessl/npm-slate-hyperscript@0.115.00
# Slate Hyperscript
1
2
Slate Hyperscript provides a hyperscript helper for creating Slate documents with JSX-like syntax. It enables developers to programmatically generate Slate editor content using a familiar JSX-style API, making it easier to create complex document structures, test Slate-based editors, and work with Slate's data model.
3
4
## Package Information
5
6
- **Package Name**: slate-hyperscript
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install slate-hyperscript`
10
11
## Core Imports
12
13
```typescript
14
import {
15
jsx,
16
createHyperscript,
17
createEditor,
18
createText,
19
HyperscriptCreators,
20
HyperscriptShorthands,
21
Token,
22
AnchorToken,
23
FocusToken,
24
addAnchorToken,
25
addFocusToken,
26
getAnchorOffset,
27
getFocusOffset
28
} from "slate-hyperscript";
29
```
30
31
For CommonJS:
32
33
```javascript
34
const {
35
jsx,
36
createHyperscript,
37
createEditor,
38
createText,
39
HyperscriptCreators,
40
HyperscriptShorthands,
41
Token,
42
AnchorToken,
43
FocusToken,
44
addAnchorToken,
45
addFocusToken,
46
getAnchorOffset,
47
getFocusOffset
48
} = require("slate-hyperscript");
49
```
50
51
## Basic Usage
52
53
```typescript
54
/** @jsx jsx */
55
import { jsx } from "slate-hyperscript";
56
57
// Create a simple editor with text content
58
const editor = (
59
<editor>
60
<element>
61
Hello <text bold>world</text>!
62
</element>
63
</editor>
64
);
65
66
// Create elements with selections
67
const editorWithSelection = (
68
<editor>
69
<element>
70
w<anchor />or<focus />d
71
</element>
72
</editor>
73
);
74
75
// Create nested elements
76
const nestedEditor = (
77
<editor>
78
<element type="paragraph">
79
<element type="bold">Bold text</element>
80
Regular text
81
</element>
82
</editor>
83
);
84
```
85
86
## Architecture
87
88
Slate Hyperscript is built around several key components:
89
90
- **JSX Factory**: The main `jsx` function that processes JSX elements into Slate objects
91
- **Creator Functions**: Specialized functions for creating different Slate node types (used internally by JSX)
92
- **Token System**: Anchor and focus tokens for precise selection positioning within JSX
93
- **Hyperscript Factory**: Customizable factory for creating domain-specific hyperscript functions
94
95
## Capabilities
96
97
### Default JSX Factory
98
99
The pre-configured hyperscript function that creates Slate objects from JSX elements.
100
101
```typescript { .api }
102
/**
103
* The default hyperscript factory that ships with Slate, without custom tags.
104
*/
105
const jsx: <S extends string>(
106
tagName: S,
107
attributes?: Object,
108
...children: any[]
109
) => any;
110
```
111
112
**Usage Example:**
113
114
```typescript
115
/** @jsx jsx */
116
import { jsx } from "slate-hyperscript";
117
118
// Basic element creation
119
const element = <element>Hello world</element>;
120
121
// Text with formatting
122
const formattedText = <text bold italic>Important text</text>;
123
124
// Complete editor
125
const editor = (
126
<editor>
127
<element>Content goes here</element>
128
</editor>
129
);
130
```
131
132
### Custom Hyperscript Creation
133
134
Factory function for creating custom hyperscript functions with specialized creators and element shortcuts.
135
136
```typescript { .api }
137
/**
138
* Create a Slate hyperscript function with custom options
139
* @param options - Configuration object
140
* @returns Custom hyperscript function
141
*/
142
function createHyperscript(options?: {
143
creators?: HyperscriptCreators;
144
elements?: HyperscriptShorthands;
145
}): <S extends string>(
146
tagName: S,
147
attributes?: Object,
148
...children: any[]
149
) => any;
150
151
/**
152
* Dictionary of creator functions keyed by tag name
153
*/
154
type HyperscriptCreators<T = any> = Record<
155
string,
156
(tagName: string, attributes: { [key: string]: any }, children: any[]) => T
157
>;
158
159
/**
160
* Dictionary of properties applied to specific element types, keyed by tag name
161
*/
162
type HyperscriptShorthands = Record<string, Record<string, any>>;
163
```
164
165
**Usage Example:**
166
167
```typescript
168
import { createHyperscript } from "slate-hyperscript";
169
170
// Create hyperscript with custom element shortcuts
171
const jsx = createHyperscript({
172
elements: {
173
paragraph: { type: "paragraph" },
174
heading: { type: "heading", level: 1 },
175
},
176
});
177
178
// Now you can use custom tags
179
const content = (
180
<editor>
181
<heading>My Title</heading>
182
<paragraph>Some content</paragraph>
183
</editor>
184
);
185
```
186
187
### Utility Functions
188
189
Higher-order functions for creating specific Slate objects outside of JSX context.
190
191
```typescript { .api }
192
/**
193
* Create a top-level Editor object creator
194
* @param makeEditor - Factory function that creates a base editor instance
195
* @returns Creator function for editors
196
*/
197
const createEditor: (makeEditor: () => Editor) => (
198
tagName: string,
199
attributes: { [key: string]: any },
200
children: any[]
201
) => Editor;
202
203
/**
204
* Create a Text object creator
205
* @param tagName - The tag name (typically "text")
206
* @param attributes - Text formatting attributes (bold, italic, etc.)
207
* @param children - Text content
208
* @returns Slate Text node
209
*/
210
function createText(
211
tagName: string,
212
attributes: { [key: string]: any },
213
children: any[]
214
): Text;
215
```
216
217
**Usage Example:**
218
219
```typescript
220
import { createText, createEditor } from "slate-hyperscript";
221
import { createEditor as makeEditor } from "slate";
222
223
// Create text node directly
224
const textNode = createText("text", { bold: true }, ["Hello world"]);
225
226
// Create custom editor creator
227
const myCreateEditor = createEditor(makeEditor);
228
```
229
230
### Selection Token System
231
232
Advanced token system for programmatic selection handling and token manipulation.
233
234
```typescript { .api }
235
/**
236
* Add an anchor token to the end of a text node
237
* @param text - Text node to add anchor token to
238
* @param token - Anchor token to add
239
*/
240
function addAnchorToken(text: Text, token: AnchorToken): void;
241
242
/**
243
* Get the offset if a text node has an associated anchor token
244
* @param text - Text node to check
245
* @returns Tuple of offset and token, or undefined if no anchor token
246
*/
247
function getAnchorOffset(text: Text): [number, AnchorToken] | undefined;
248
249
/**
250
* Add a focus token to the end of a text node
251
* @param text - Text node to add focus token to
252
* @param token - Focus token to add
253
*/
254
function addFocusToken(text: Text, token: FocusToken): void;
255
256
/**
257
* Get the offset if a text node has an associated focus token
258
* @param text - Text node to check
259
* @returns Tuple of offset and token, or undefined if no focus token
260
*/
261
function getFocusOffset(text: Text): [number, FocusToken] | undefined;
262
```
263
264
**Usage Example:**
265
266
```typescript
267
import { addAnchorToken, AnchorToken, createText } from "slate-hyperscript";
268
269
// Create a text node and programmatically add selection tokens
270
const textNode = createText("text", {}, ["Hello world"]);
271
const anchorToken = new AnchorToken({ offset: 5 });
272
addAnchorToken(textNode, anchorToken);
273
```
274
275
## JSX Element Types
276
277
The following JSX elements are available by default when using the `jsx` factory:
278
279
### Core Elements
280
281
```typescript { .api }
282
// Basic document structure
283
<editor>...</editor> // Creates Editor with content and optional selection
284
<element>...</element> // Creates Element nodes with children
285
<text>...</text> // Creates Text nodes with formatting
286
<fragment>...</fragment> // Creates arrays of Descendant nodes
287
288
// Selection positioning
289
<anchor /> // Marks selection anchor point
290
<focus /> // Marks selection focus point
291
<cursor /> // Marks collapsed selection point
292
<selection>...</selection> // Creates explicit Selection objects
293
```
294
295
**Usage Examples:**
296
297
```typescript
298
/** @jsx jsx */
299
import { jsx } from "slate-hyperscript";
300
301
// Basic elements
302
const element = <element type="paragraph">Hello world</element>;
303
const textNode = <text bold italic>Formatted text</text>;
304
305
// Document fragments
306
const fragment = (
307
<fragment>
308
<element>First paragraph</element>
309
<element>Second paragraph</element>
310
</fragment>
311
);
312
313
// Selections in text
314
const withSelection = (
315
<editor>
316
<element>
317
Hello <anchor />beautiful<focus /> world
318
</element>
319
</editor>
320
);
321
322
// Collapsed selection (cursor)
323
const withCursor = (
324
<editor>
325
<element>
326
Hello <cursor />world
327
</element>
328
</editor>
329
);
330
331
// Explicit selection object
332
const selection = (
333
<selection>
334
<anchor path={[0, 0]} offset={5} />
335
<focus path={[0, 0]} offset={14} />
336
</selection>
337
);
338
```
339
340
## Types
341
342
```typescript { .api }
343
/**
344
* Base class for all selection tokens
345
*/
346
class Token {}
347
348
/**
349
* Represents selection anchor points
350
*/
351
class AnchorToken extends Token {
352
offset?: number;
353
path?: Path;
354
355
constructor(props?: {
356
offset?: number;
357
path?: Path;
358
});
359
}
360
361
/**
362
* Represents selection focus points
363
*/
364
class FocusToken extends Token {
365
offset?: number;
366
path?: Path;
367
368
constructor(props?: {
369
offset?: number;
370
path?: Path;
371
});
372
}
373
```
374
375
## Error Handling
376
377
Common errors you may encounter:
378
379
- **Missing Creator**: `"No hyperscript creator found for tag: <tagName>"` - occurs when using undefined JSX tag names
380
- **Invalid Selection Setup**: `"The <selection> hyperscript tag must have an <anchor> tag as a child with \`path\` and \`offset\` attributes defined."` - occurs when selection tags are missing required anchor/focus children with proper attributes
381
- **Text Content Validation**: `"The <text> hyperscript tag can only contain text content as children."` - occurs when `<text>` tags contain non-text children like elements
382
- **Incomplete Selection Ranges**: `"Slate hyperscript ranges must have both \`<anchor />\` and \`<focus />\` defined if one is defined, but you only defined \`<anchor />\`. For collapsed selections, use \`<cursor />\` instead."` - occurs when only one selection point is defined
383
- **Custom Element Configuration**: `"Properties specified for a hyperscript shorthand should be an object, but for the custom element <tagName> tag you passed: [value]"` - occurs when element shortcuts in `createHyperscript` options are not objects
384
385
## JSX Setup
386
387
To use JSX syntax with slate-hyperscript, configure your TypeScript/Babel setup:
388
389
**TypeScript (tsconfig.json):**
390
```json
391
{
392
"compilerOptions": {
393
"jsx": "react",
394
"jsxFactory": "jsx"
395
}
396
}
397
```
398
399
**Per-file pragma:**
400
```typescript
401
/** @jsx jsx */
402
import { jsx } from "slate-hyperscript";
403
```
404
405
## Dependencies
406
407
- **slate**: Peer dependency (>=0.114.3) providing core types `Element`, `Text`, `Range`, `Editor`, `Descendant`, `Path`, etc.