Modifying the Schema

Each document of the Editor conforms to a specific schema which describes the nodes and the marks that the document may contain.

The nodes conform to the HTML elements such as paragraphs, headings, lists, tables, images, and so on. The marks conform to the inline formatting options such as Bold, Italic, FontSize, and so on. By modifying the default, built-in schema, you can add additional types of nodes and marks as well as edit and remove the existing ones.

Modifying the Default Schema

The following example demonstrates how to:

  • Add a new node to nodes object of the schema.
  • Add a new mark to marks object of the schema.
  • Add a custom attribute to the existing nodes.
import React from 'react';
import ReactDOM from 'react-dom';
import { Editor, EditorTools, EditorUtils, ProseMirror } from '@progress/kendo-react-editor';
import { iframe } from './new-node';
import { tagMark } from './new-mark';

const { Bold, Italic, Underline, ViewHtml } = EditorTools;
const { Schema, EditorView, EditorState } = ProseMirror;

class App extends React.Component {
    html = `<p dir="rtl">A paragraph with <code>dir="rtl"</code> attribute, and the new added mark - <s>new mark formatting</s></p>
        <iframe style="width: 500px; height: 340px;" src="https://www.youtube.com/embed/2OvvwWShNWo"></iframe>`;

    onMount = event => {
        const { viewProps } = event;
        const { plugins, schema } = viewProps.state;

        // Add the 'data-test' attribute to paragraph node.
        const paragraph = { ...schema.spec.nodes.get('paragraph') };
        paragraph.attrs['dir'] = { default: null };
        let nodes = schema.spec.nodes.update('paragraph', paragraph);

        // Append the new node.
        nodes = nodes.addToEnd('iframe', iframe);

        // Append a new mark representing the <s> formatting tag.
        const mark = tagMark('s');
        let marks = schema.spec.marks.append(mark);

        // Create the new schema.
        const mySchema = new Schema({ nodes, marks });

        // Create a new document using the modified schema.
        const doc = EditorUtils.createDocument(mySchema, this.html);

        // Return the custom EditorView object that will be used by Editor.
        return new EditorView(
            { mount: event.dom }, {
                ...event.viewProps,
                state: EditorState.create({ doc, plugins })
            }
        );
    }

    render() {
        return (
            <Editor
                tools={[ [ Bold, Italic, Underline, ViewHtml ] ]}
                contentStyle={{ height: 420 }}
                onMount={this.onMount}
            />
        );
    }
}

ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);

Creating Custom Schema

The following example demonstrates how to implement a custom Editor schema.

import React from 'react';
import ReactDOM from 'react-dom';
import { Editor, EditorTools, EditorUtils, ProseMirror } from '@progress/kendo-react-editor';
import mySchema from './schema';
import content from './content';

const { Bold, Italic, Underline,
    AlignLeft, AlignRight, AlignCenter,
    Indent, Outdent,
    OrderedList, UnorderedList,
    Undo, Redo, Link, Unlink } = EditorTools;

const { EditorView, EditorState } = ProseMirror;

class App extends React.Component {
    onMount = event => {
        const { viewProps } = event;
        const { plugins } = viewProps.state;

        // Create a new document using the schema.
        const doc = EditorUtils.createDocument(mySchema, content);

        // Return the custom EditorView object that will be used by Editor.
        return new EditorView(
            { mount: event.dom }, {
                ...event.viewProps,
                state: EditorState.create({ doc, plugins })
            }
        );
    }

    render() {
        return (
            <Editor
                tools={[
                    [ Bold, Italic, Underline ],
                    [ Undo, Redo ],
                    [ Link, Unlink ],
                    [ AlignLeft, AlignCenter, AlignRight ],
                    [ OrderedList, UnorderedList, Indent, Outdent ]
                ]}
                contentStyle={{ height: 330 }}
                onMount={this.onMount}
            />
        );
    }
}

ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);
 /