or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-slate-hyperscript

A hyperscript helper for creating Slate documents with JSX-like syntax.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/slate-hyperscript@0.115.x

To install, run

npx @tessl/cli install tessl/npm-slate-hyperscript@0.115.0

index.mddocs/

Slate Hyperscript

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.

Package Information

  • Package Name: slate-hyperscript
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install slate-hyperscript

Core Imports

import { 
  jsx, 
  createHyperscript, 
  createEditor, 
  createText, 
  HyperscriptCreators, 
  HyperscriptShorthands,
  Token,
  AnchorToken,
  FocusToken,
  addAnchorToken,
  addFocusToken,
  getAnchorOffset,
  getFocusOffset
} from "slate-hyperscript";

For CommonJS:

const { 
  jsx, 
  createHyperscript, 
  createEditor, 
  createText, 
  HyperscriptCreators, 
  HyperscriptShorthands,
  Token,
  AnchorToken,
  FocusToken,
  addAnchorToken,
  addFocusToken,
  getAnchorOffset,
  getFocusOffset
} = require("slate-hyperscript");

Basic Usage

/** @jsx jsx */
import { jsx } from "slate-hyperscript";

// Create a simple editor with text content
const editor = (
  <editor>
    <element>
      Hello <text bold>world</text>!
    </element>
  </editor>
);

// Create elements with selections
const editorWithSelection = (
  <editor>
    <element>
      w<anchor />or<focus />d
    </element>
  </editor>
);

// Create nested elements
const nestedEditor = (
  <editor>
    <element type="paragraph">
      <element type="bold">Bold text</element>
      Regular text
    </element>
  </editor>
);

Architecture

Slate Hyperscript is built around several key components:

  • JSX Factory: The main jsx function that processes JSX elements into Slate objects
  • Creator Functions: Specialized functions for creating different Slate node types (used internally by JSX)
  • Token System: Anchor and focus tokens for precise selection positioning within JSX
  • Hyperscript Factory: Customizable factory for creating domain-specific hyperscript functions

Capabilities

Default JSX Factory

The pre-configured hyperscript function that creates Slate objects from JSX elements.

/**
 * The default hyperscript factory that ships with Slate, without custom tags.
 */
const jsx: <S extends string>(
  tagName: S,
  attributes?: Object,
  ...children: any[]
) => any;

Usage Example:

/** @jsx jsx */
import { jsx } from "slate-hyperscript";

// Basic element creation
const element = <element>Hello world</element>;

// Text with formatting
const formattedText = <text bold italic>Important text</text>;

// Complete editor
const editor = (
  <editor>
    <element>Content goes here</element>
  </editor>
);

Custom Hyperscript Creation

Factory function for creating custom hyperscript functions with specialized creators and element shortcuts.

/**
 * Create a Slate hyperscript function with custom options
 * @param options - Configuration object
 * @returns Custom hyperscript function
 */
function createHyperscript(options?: {
  creators?: HyperscriptCreators;
  elements?: HyperscriptShorthands;
}): <S extends string>(
  tagName: S,  
  attributes?: Object,
  ...children: any[]
) => any;

/**
 * Dictionary of creator functions keyed by tag name
 */
type HyperscriptCreators<T = any> = Record<
  string,
  (tagName: string, attributes: { [key: string]: any }, children: any[]) => T
>;

/**
 * Dictionary of properties applied to specific element types, keyed by tag name
 */
type HyperscriptShorthands = Record<string, Record<string, any>>;

Usage Example:

import { createHyperscript } from "slate-hyperscript";

// Create hyperscript with custom element shortcuts
const jsx = createHyperscript({
  elements: {
    paragraph: { type: "paragraph" },
    heading: { type: "heading", level: 1 },
  },
});

// Now you can use custom tags
const content = (
  <editor>
    <heading>My Title</heading>
    <paragraph>Some content</paragraph>
  </editor>
);

Utility Functions

Higher-order functions for creating specific Slate objects outside of JSX context.

/**
 * Create a top-level Editor object creator
 * @param makeEditor - Factory function that creates a base editor instance
 * @returns Creator function for editors
 */
const createEditor: (makeEditor: () => Editor) => (
  tagName: string,
  attributes: { [key: string]: any },
  children: any[]
) => Editor;

/**
 * Create a Text object creator
 * @param tagName - The tag name (typically "text")
 * @param attributes - Text formatting attributes (bold, italic, etc.)
 * @param children - Text content
 * @returns Slate Text node
 */
function createText(
  tagName: string,
  attributes: { [key: string]: any },
  children: any[]
): Text;

Usage Example:

import { createText, createEditor } from "slate-hyperscript";
import { createEditor as makeEditor } from "slate";

// Create text node directly
const textNode = createText("text", { bold: true }, ["Hello world"]);

// Create custom editor creator
const myCreateEditor = createEditor(makeEditor);

Selection Token System

Advanced token system for programmatic selection handling and token manipulation.

/**
 * Add an anchor token to the end of a text node
 * @param text - Text node to add anchor token to
 * @param token - Anchor token to add
 */
function addAnchorToken(text: Text, token: AnchorToken): void;

/**
 * Get the offset if a text node has an associated anchor token
 * @param text - Text node to check
 * @returns Tuple of offset and token, or undefined if no anchor token
 */
function getAnchorOffset(text: Text): [number, AnchorToken] | undefined;

/**
 * Add a focus token to the end of a text node
 * @param text - Text node to add focus token to
 * @param token - Focus token to add
 */
function addFocusToken(text: Text, token: FocusToken): void;

/**
 * Get the offset if a text node has an associated focus token
 * @param text - Text node to check
 * @returns Tuple of offset and token, or undefined if no focus token
 */
function getFocusOffset(text: Text): [number, FocusToken] | undefined;

Usage Example:

import { addAnchorToken, AnchorToken, createText } from "slate-hyperscript";

// Create a text node and programmatically add selection tokens
const textNode = createText("text", {}, ["Hello world"]);
const anchorToken = new AnchorToken({ offset: 5 });
addAnchorToken(textNode, anchorToken);

JSX Element Types

The following JSX elements are available by default when using the jsx factory:

Core Elements

// Basic document structure
<editor>...</editor>         // Creates Editor with content and optional selection
<element>...</element>       // Creates Element nodes with children
<text>...</text>            // Creates Text nodes with formatting
<fragment>...</fragment>     // Creates arrays of Descendant nodes

// Selection positioning
<anchor />                   // Marks selection anchor point
<focus />                   // Marks selection focus point  
<cursor />                  // Marks collapsed selection point
<selection>...</selection>   // Creates explicit Selection objects

Usage Examples:

/** @jsx jsx */
import { jsx } from "slate-hyperscript";

// Basic elements
const element = <element type="paragraph">Hello world</element>;
const textNode = <text bold italic>Formatted text</text>;

// Document fragments
const fragment = (
  <fragment>
    <element>First paragraph</element>
    <element>Second paragraph</element>
  </fragment>
);

// Selections in text
const withSelection = (
  <editor>
    <element>
      Hello <anchor />beautiful<focus /> world
    </element>
  </editor>
);

// Collapsed selection (cursor)
const withCursor = (
  <editor>
    <element>
      Hello <cursor />world
    </element>
  </editor>
);

// Explicit selection object
const selection = (
  <selection>
    <anchor path={[0, 0]} offset={5} />
    <focus path={[0, 0]} offset={14} />
  </selection>
);

Types

/**
 * Base class for all selection tokens
 */
class Token {}

/**
 * Represents selection anchor points
 */
class AnchorToken extends Token {
  offset?: number;
  path?: Path;
  
  constructor(props?: {
    offset?: number;
    path?: Path;
  });
}

/**
 * Represents selection focus points
 */
class FocusToken extends Token {
  offset?: number;
  path?: Path;
  
  constructor(props?: {
    offset?: number;
    path?: Path;
  });
}

Error Handling

Common errors you may encounter:

  • Missing Creator: "No hyperscript creator found for tag: <tagName>" - occurs when using undefined JSX tag names
  • 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
  • Text Content Validation: "The <text> hyperscript tag can only contain text content as children." - occurs when <text> tags contain non-text children like elements
  • 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
  • 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

JSX Setup

To use JSX syntax with slate-hyperscript, configure your TypeScript/Babel setup:

TypeScript (tsconfig.json):

{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "jsx"
  }
}

Per-file pragma:

/** @jsx jsx */
import { jsx } from "slate-hyperscript";

Dependencies

  • slate: Peer dependency (>=0.114.3) providing core types Element, Text, Range, Editor, Descendant, Path, etc.