New to Telerik UI for Blazor? Download free 30-day trial

Modify the Default ProseMirror Schema

This article describes how you can modify the default ProseMirror schema that the Editor for Blazor uses. Updating the existing schema is useful if you want to:

  • Extend the Editor capabilities and allow end users to add more kinds of HTML tags than the predefined ones.
  • Allow adding more attributes to the predefined HTML elements.
  • Restrict end users from adding some of the predefined HTML elements.

Prerequisites

To work with ProseMirror, make sure you are familiar with:

  • JavaScript—ProseMirror is a JavaScript library and the schema uses JavaScript syntax.
  • ProseMirror Schema—The schema structure and its children (nodes and marks).

Modifying the ProseMirror Schema is outside of the Editor scope and we do not provide support for such customizations.

Basics

The Editor accepts a custom ProseMirror schema through its Schema parameter. Set this string parameter to the name of a JavaScript function that:

  • Is declared in the global scope (the window object).
  • Returns an instance of the ProseMirror Schema class(the updated schema). You can access this class from the ProseMirror object of the event arguments.
  • Accepts a single argument.

The Editor will call this function and will pass an argument object that contains the following properties:

Property Description
getSchema A function that returns the current Schema object. Before the Editor is initialized, the returned Schema object is the default schema of the Editor. After the Editor is initialized, the returned Schema object is the updated schema. If you don't provide a custom schema, this function always returns the default schema.
getView A function that returns the currently used instance of the EditorView object. Before the Editor is initialized, the view (the result of the function) is null.
ProseMirror An object that contains various ProseMirror classes and functions.

You can set a custom schema only once during initialization of the Editor component. Further changes to the schema will not take effect and the component will continue using the initial custom or built-in schema.

Modifying the Schema

The below example shows how to:

  • Get the default ProseMirror schema.
  • Add a data-id attribute to the <p> node.
  • Remove the default horizontal_rule node that does not allow any attributes and add a custom node for the <hr> element that allows setting a CSS class.
  • Add a mark for the <s> element.
  • Return the updated schema, so the Editor can use it.

The Editor in this example uses the Div edit mode, so the style for the <hr> element is applied. If you use the default Iframe edit mode, you have to plug the styles with JavaScript as shown in this example.

Modify the default ProseMirror Schema

<style>
    hr.custom-hr {
        border-color: red;
    }
</style>

<TelerikEditor @bind-Value="@TheEditorValue"
               Schema="schemaProvider"
               EditMode="@EditorEditMode.Div">
</TelerikEditor>

@code {
    private string TheEditorValue { get; set; }

    protected override Task OnInitializedAsync()
    {
        TheEditorValue = @"
        A horizontal rule with a custom class
        <hr class='custom-hr' />
        <p data-id='paragraph-data-id'>
            A paragraph with a 'data-id' attribute.
        </p>
        <s>
            An s element.
        </s>";

        return base.OnInitializedAsync();
    }
}

@* Move JavaScript code to a separate JS file in production *@
<script suppress-error="BL9992">
    var tagMark = (tag) => ({
        [tag]: {
            name: tag,
            inclusive: true,
            parseDOM: [{ tag }],
            toDOM: () => [tag, 0],
        },
    });

    var updatedHr = {
        attrs: {
            class: { default: null },
        },
        group: "block",
        parseDOM: [
            {
                tag: "hr",
                getAttrs: (dom) => ({
                    class: dom.getAttribute("class")
                }),
            },
        ],
        toDOM: (node) => {
            return ["hr", { class: node.attrs.class }];
        },
    };

    window.schemaProvider = (args) => {
        const schema = args.getSchema();
        const Schema = args.ProseMirror.Schema

        const paragraph = { ...schema.spec.nodes.get("paragraph") };
        paragraph.attrs["data-id"] = { default: null };
        let nodes = schema.spec.nodes.update("paragraph", paragraph);

        nodes = nodes.remove("horizontal_rule");

        nodes = nodes.addToEnd("hr", updatedHr);

        const markStrikeThrough = tagMark("s");
        const marks = schema.spec.marks.append(markStrikeThrough);

        const newSchema = new Schema({ nodes, marks });
        return newSchema;
    }
</script>

See Also

In this article