From zbeyens. The source code is available on GitHub.

Plate
PlatePliteEditorsTemplates
GitHub16kGitHub
DiscordDiscord
UNPUBLISHED
  • Overview
  • Why This Fork
  • Examples
Walkthroughs
  • Installing Plite
  • Adding Event Handlers
  • Defining Custom Elements
  • Applying Custom Formatting
  • Executing Commands
  • Saving to a Database
  • Canonical Change Substrate
  • Improving Performance
Concepts
  • Interfaces
  • Nodes
  • Locations
  • Transforms
  • Document Changes
  • Commands
  • Editor
  • Extensions
  • Rendering
  • Serializing
  • Normalizing
  • Using TypeScript
  • Roots
  • Document State
  • Editing Behavior
  • Selection And DOM
  • Clipboard And Paste
  • Projection And Overlays
  • Schema
API
  • Anchor API
  • Location API
  • Path API
  • PointEntry API
  • Point API
  • Range API
  • Selection API
  • Location Types APIs
  • Span API
  • Editor
  • Element API
  • NodeEntry API
  • Node API
  • Node Types APIs
  • Text API
  • Debug Value Scrubbing
  • Transforms API
Libraries
  • Plite DOM
  • History Editor API
  • History Extension Setup
  • History
  • Plite History
  • Plite Hyperscript
  • Plite Layout
  • Annotations
  • DOM Coverage Boundaries
  • Editable Component
  • Plite React Event Handling
  • Virtualized Rendering
  • Plite React Hooks
  • React Editor Setup
  • React Editor
  • Plite React
  • Plite Component
  • Plite Yjs
  • Plite
General
  • Migration
  • Contributing
  • Docs Proof Map
  • FAQ
  • Resources

Interfaces

PreviousNext

Understand the plain JSON interfaces that make up Plite documents.

Plite documents are plain JSON objects with a small set of structural interfaces. Your app owns the product-specific fields.

Text

Text nodes contain text plus optional mark properties.

interface Text {
  text: string;
}
interface Text {
  text: string;
}
Transforms APINodes

On This Page

TextElementHelper NamespacesDomain Helpers
Build your editor
Production-ready AI template and reusable components.
Get all-access
const text = {
  text: "Bold",
  bold: true,
};
const text = {
  text: "Bold",
  bold: true,
};

Plite treats bold as your data. The editor only requires the text string.

Element

Elements contain child nodes and any product fields your schema needs.

interface Element {
  children: Node[];
}
interface Element {
  children: Node[];
}
const paragraph = {
  type: "paragraph",
  children: [{ text: "Body" }],
};
 
const link = {
  type: "link",
  url: "https://example.com",
  children: [{ text: "Example" }],
};
const paragraph = {
  type: "paragraph",
  children: [{ text: "Body" }],
};
 
const link = {
  type: "link",
  url: "https://example.com",
  children: [{ text: "Example" }],
};

The type and url fields are your API. Plite sees them, preserves them, and passes them to renderers and transforms, but your app decides what they mean.

const LinkElement = ({ attributes, children, element }) => {
  return (
    <a {...attributes} href={element.url}>
      {children}
    </a>
  );
};
const LinkElement = ({ attributes, children, element }) => {
  return (
    <a {...attributes} href={element.url}>
      {children}
    </a>
  );
};

Helper Namespaces

Runtime values use plain objects. Static helper functions live on *Api namespaces such as NodeApi, ElementApi, TextApi, PathApi, PointApi, RangeApi, and SelectionApi.

import { ElementApi, NodeApi, RangeApi } from "@platejs/plite";
 
const string = NodeApi.string(element);
const isElement = ElementApi.isElement(value);
const collapsed = RangeApi.isCollapsed(range);
import { ElementApi, NodeApi, RangeApi } from "@platejs/plite";
 
const string = NodeApi.string(element);
const isElement = ElementApi.isElement(value);
const collapsed = RangeApi.isCollapsed(range);

Use the helper namespace when you need structural checks, path math, range direction, or text extraction outside an editor read/update callback.

Inside editor.read(...) and editor.update(...), prefer the grouped runtime helpers because they understand the current root, schema, and transaction.

const linkEntry = editor.read((state) =>
  state.nodes.above({
    match: (node) => ElementApi.isElement(node) && node.type === "link",
  })
);
const linkEntry = editor.read((state) =>
  state.nodes.above({
    match: (node) => ElementApi.isElement(node) && node.type === "link",
  })
);

Domain Helpers

Keep domain helpers as normal functions or expose them from an extension when they need editor state.

import { ElementApi, type Element } from "@platejs/plite";
 
type ImageElement = Element & {
  type: "image";
  url: string;
};
 
const isImageElement = (value: unknown): value is ImageElement =>
  ElementApi.isElement(value) &&
  value.type === "image" &&
  typeof value.url === "string";
import { ElementApi, type Element } from "@platejs/plite";
 
type ImageElement = Element & {
  type: "image";
  url: string;
};
 
const isImageElement = (value: unknown): value is ImageElement =>
  ElementApi.isElement(value) &&
  value.type === "image" &&
  typeof value.url === "string";

Use Extensions when a helper should become a typed state, tx, or api namespace installed on the editor.