Working with Content
Output Formats
Section titled “Output Formats”notectl supports three output formats:
JSON (Document Model)
Section titled “JSON (Document Model)”The canonical format — a structured tree of blocks, text nodes, and marks:
const doc = editor.getJSON();Returns a Document object:
{ "children": [ { "type": "heading", "id": "abc123", "attrs": { "level": 1 }, "children": [ { "type": "text", "text": "Hello ", "marks": [] }, { "type": "text", "text": "World", "marks": [{ "type": "bold" }] } ] }, { "type": "paragraph", "id": "def456", "children": [ { "type": "text", "text": "Some text here.", "marks": [] } ] } ]}Sanitized HTML output suitable for rendering or storage:
const html = editor.getHTML();// "<h1>Hello <strong>World</strong></h1><p>Some text here.</p>"The HTML is sanitized with DOMPurify. Only safe tags and attributes are included:
- Tags:
p,h1-h6,strong,em,u,s,a,span,ul,ol,li,hr,blockquote,div,br - Attributes:
href,target,rel,style
Plain Text
Section titled “Plain Text”Plain text content with blocks joined by newlines:
const text = editor.getText();// "Hello World\nSome text here."Setting Content
Section titled “Setting Content”From HTML
Section titled “From HTML”editor.setHTML('<h1>Welcome</h1><p>Start editing...</p>');The HTML is parsed into the document model. Supported elements:
| HTML | Block Type |
|---|---|
<p>, <div> | paragraph |
<h1> - <h6> | heading (level 1-6) |
<ul><li> | list_item (bullet) |
<ol><li> | list_item (ordered) |
<li> with checkbox | list_item (checklist) |
<hr> | horizontal_rule |
<blockquote> | blockquote |
Inline formatting maps:
| HTML | Mark Type |
|---|---|
<strong>, <b> | bold |
<em>, <i> | italic |
<u> | underline |
<s> | strikethrough |
<a href="..."> | link |
<span style="color: ..."> | textColor |
<span style="font-family: ..."> | font |
From JSON
Section titled “From JSON”import { createDocument, createBlockNode, createTextNode, nodeType } from '@notectl/core';
const doc = createDocument([ createBlockNode(nodeType('paragraph'), [ createTextNode('Hello world'), ]),]);
editor.setJSON(doc);Checking Empty State
Section titled “Checking Empty State”if (editor.isEmpty()) { console.log('Editor has no content');}The editor is considered empty when it contains a single empty paragraph.
Listening for Changes
Section titled “Listening for Changes”editor.on('stateChange', ({ oldState, newState, transaction }) => { // Called on every state change const html = editor.getHTML(); saveToBackend(html);});Programmatic Editing
Section titled “Programmatic Editing”Use the command API for common operations:
// Toggle inline markseditor.commands.toggleBold();editor.commands.toggleItalic();editor.commands.toggleUnderline();
// Execute named commands from pluginseditor.executeCommand('toggleStrikethrough');editor.executeCommand('insertHorizontalRule');editor.executeCommand('toggleList:ordered');editor.executeCommand('toggleList:bullet');editor.executeCommand('toggleBlockquote');
// Undo / Redoeditor.commands.undo();editor.commands.redo();
// Select alleditor.commands.selectAll();Check Command Availability
Section titled “Check Command Availability”const canToggle = editor.can();
if (canToggle.toggleBold()) { editor.commands.toggleBold();}
if (canToggle.undo()) { editor.commands.undo();}Advanced: Direct State Access
Section titled “Advanced: Direct State Access”For advanced use cases, you can access the editor state directly:
const state = editor.getState();
// Inspect the documentconsole.log(state.doc.children.length, 'blocks');
// Check selectionconsole.log(state.selection);
// Access schemaconsole.log(state.schema.nodeTypes);console.log(state.schema.markTypes);