These interfaces define the structure of document data used by Canvas Editor.
IEditorData
Represents the complete document structure with header, main, and footer sections.
src/editor/interface/Editor.ts
interface IEditorData {
header?: IElement[]
main: IElement[]
footer?: IElement[]
graffiti?: IGraffitiData[]
}
Properties
Main document content. This is required and contains the primary document elements.
Optional header content that appears at the top of each page
Optional footer content that appears at the bottom of each page
Optional graffiti/drawing data for annotations
Example
import { IEditorData, IElement } from '@hufe921/canvas-editor'
const data: IEditorData = {
header: [
{ value: 'Document Title', size: 20, bold: true }
],
main: [
{ value: 'This is the main content.' },
{ value: 'It can have multiple elements.' }
],
footer: [
{ value: 'Page ' },
{ value: '1' }
]
}
IEditorResult
Represents the complete editor state including data, version, and options.
src/editor/interface/Editor.ts
interface IEditorResult {
version: string
data: IEditorData
options: IEditorOption
}
Properties
Canvas Editor version that generated this result
Editor configuration options
Example
const result: IEditorResult = editor.command.getValue()
console.log('Editor version:', result.version)
console.log('Main content:', result.data.main)
console.log('Options:', result.options)
Use Cases
Saving Document:
editor.listener.saved = (result: IEditorResult) => {
// Save to server
fetch('/api/documents', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(result)
})
}
Getting Current State:
const currentState = editor.command.getValue()
// currentState is IEditorResult
IEditorHTML
Represents document data as HTML strings.
src/editor/interface/Editor.ts
interface IEditorHTML {
header: string
main: string
footer: string
}
Properties
Example
const html = editor.command.getHTML()
console.log('Main HTML:', html.main)
// Output: '<p>This is <b>bold</b> text</p>'
// Use in preview
document.querySelector('#preview').innerHTML = html.main
IEditorText
Alias for IEditorHTML - represents plain text for each section.
src/editor/interface/Editor.ts
type IEditorText = IEditorHTML
Example
const text = editor.command.getText()
console.log('Main text:', text.main)
console.log('Header text:', text.header)
console.log('Footer text:', text.footer)
Working with Document Data
Creating a New Document
import Editor, { IEditorData, ElementType } from '@hufe921/canvas-editor'
const data: IEditorData = {
main: [
{ value: 'Chapter 1', level: TitleLevel.FIRST },
{ value: 'Introduction paragraph.' }
]
}
const editor = new Editor(container, data)
You can also pass just an array for the main content:
import { IElement } from '@hufe921/canvas-editor'
const elements: IElement[] = [
{ value: 'Simple document' }
]
const editor = new Editor(container, elements)
// Equivalent to: { main: elements }
Loading Existing Document
// Fetch from server
const response = await fetch('/api/documents/123')
const result: IEditorResult = await response.json()
// Create editor with loaded data
const editor = new Editor(
container,
result.data,
result.options
)
Getting Document Data
// Get as IEditorResult (includes version and options)
const result = editor.command.getValue()
// Get specific sections
const mainContent: IElement[] = result.data.main
const headerContent: IElement[] = result.data.header || []
// Get as HTML
const html = editor.command.getHTML()
console.log(html.main)
// Get as plain text
const text = editor.command.getText()
console.log(text.main)
Setting Document Data
import { IEditorData } from '@hufe921/canvas-editor'
const newData: IEditorData = {
main: [
{ value: 'New content' }
]
}
editor.command.executeSetValue(newData)
Async Operations
// Get value asynchronously (waits for rendering)
const result = await editor.command.getValueAsync()
// Useful when you need up-to-date rendered positions
const positions = result.data.main.map(el => el.metrics)
Document Structure Best Practices
1. Always Include Main Content
// Good
const data: IEditorData = {
main: [{ value: 'Content' }]
}
// Bad - will cause error
const data: IEditorData = {
header: [{ value: 'Header only' }]
// Missing main!
}
const data: IEditorData = {
header: [
{ value: 'Company Name', bold: true, size: 18 },
{ value: '\n' },
{ value: 'Confidential Document', color: '#FF0000' }
],
main: [
{ value: 'Page content...' }
],
footer: [
{ value: 'Page ' },
{ value: '{{pageNo}}' }, // Dynamic page number
{ value: ' of ' },
{ value: '{{pageCount}}' }
]
}
3. Preserve Document Structure
// When modifying, maintain structure
const result = editor.command.getValue()
// Modify main content
result.data.main.push({ value: 'New paragraph' })
// Keep header/footer intact
editor.command.executeSetValue(result.data)
4. Handle Optional Sections
const result = editor.command.getValue()
// Safe access to optional sections
const header = result.data.header || []
const footer = result.data.footer || []
if (header.length > 0) {
console.log('Document has header')
}
JSON
const result = editor.command.getValue()
const json = JSON.stringify(result, null, 2)
// Save to file
const blob = new Blob([json], { type: 'application/json' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = 'document.json'
a.click()
HTML
const html = editor.command.getHTML()
const fullHtml = `
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<header>${html.header}</header>
<main>${html.main}</main>
<footer>${html.footer}</footer>
</body>
</html>
`
Plain Text
const text = editor.command.getText()
const fullText = [
'=== HEADER ===',
text.header,
'',
'=== CONTENT ===',
text.main,
'',
'=== FOOTER ===',
text.footer
].join('\n')