@platecms/delta-cast
v1.2.0
Published
Package containing the definition of CAST
Readme
CAST (Content Abstract Syntax Tree)
This package contains the CAST (Content Abstract Syntax Tree) schema and tools for working with it. CAST is a schema that adheres to the Unified collective
Features
Schema
The schema is defined in schema.ts, and is rendered into JSON Schema format in schema.json.
Utils
To work with CAST documents, we implement the following utitlities:
InvalidCastError: An error that is thrown when a CAST document is invalid.validateCast: Validates any input against the schema. ThrowsInvalidCastErrorif the input is invalid.
WIP fromSlate (Or some other editor)
As Delta uses Slate as a wysiwyg editor, we need to convert ~Slate~ documents to CAST documents, in order to process them in Delta.
WIP toSlate
As Delta uses Slate as a wysiwyg editor, we need to convert CAST documents to ~Slate~ documents, in order to display them in the editor.
WIP toHast
To display CAST documents in a web browser, we need to convert them to HAST. From a HAST tree, we can then use hast-util-to-html to create an HTML string or hast-util-to-dom to create a DOM tree.
Example usage of cast-utils-to-hast to render a CAST tree to a HTML string:
const castTree = {
type: 'root',
children: [
{
type: 'paragraph',
children: [
{ type: 'text', value: 'Hello, world!' }
]
}
]
}
const hast = toHast(castTree);
const htmlString = toHtml(hast);Normalization
A CAST tree can and should be normalized to ensure that it is in a consistent and predictable state. Different trees that represent the same content should be normalized to a single, canonical form.
Usage
import { normalizeCast } from '@platecms/delta-cast';
const normalizedTree = normalizeCast(castTree);Normalization Rules
The normalizeCast function applies the following normalization rules in an iterative process:
1. Adjacent Node Merging
- Text nodes: Merge adjacent
textnodes by concatenating their values - Formatting nodes: Merge adjacent formatting nodes of the same type by combining their children
- Mergeable types:
text,bold,italic,underline,strikethrough,highlight - Non-mergeable types:
contentValue,externalLink,internalLink,inlineCode
2. Formatting Node Nesting Order
Formatting nodes are reordered to follow a consistent hierarchy:
bold -> italic -> underline -> strikethrough -> highlight3. Duplicate Formatting Removal
- Remove duplicate formatting nodes in a single path (e.g.,
boldcontainingbold) - This prevents redundant nesting that doesn't change the visual output
4. Empty Node Cleanup
- Remove empty formatting (inline) nodes that contain no children
- Block-level container nodes (paragraphs, headings, lists, etc.) are preserved even when empty
Special Behavior
- ContentValue nodes: Completely untouched - their nested CAST trees are never normalized
- Property preservation: All node properties (
url,target,prn,level,lang, etc.) are preserved - Iterative process: Normalization is an iterative process that continues until no more changes are detected
- Immutable: Returns a new tree without modifying the input
Formatting Priority
The FORMATTING_PRIORITY constant defines the canonical nesting order for formatting nodes:
export const FORMATTING_PRIORITY = {
'bold': 1, // Highest priority
'italic': 2,
'underline': 3,
'strikethrough': 4,
'highlight': 5 // Lowest priority
} as const;This constant should be used across all packages (e.g., cast-util-to-slate, cast-util-from-slate) to ensure consistent formatting hierarchy throughout the platform.
