Skip to content

Configuration ​

Types ​

The types key defines a map from Prosemirror types to Vnode names.

ts
createApp(App).use(ProsemirrorPlugin, {
  types: {
    // maps nodes with 'doc' type to HTML <article />
    doc: "article",
  },
});
json
{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [
        {
          "type": "text",
          "text": "The line."
        }
      ]
    }
  ]
}
html
<article>
  <p>The line.</p>
</article>

The key can be in snake_case or camelCase.

Unmatched types are rendered as is.

Options provider ​

You can modify the types map locally with the provideProsemirrorOptions composable.

vue
<script setup lang="ts">
import { provideProsemirrorOptions } from "@bicou/prosemirror-render-vue";

provideProsemirrorOptions({
  types: {
    doc: "article",
  },
});
</script>

<template>
  <prosemirror-render node="node" />
</template>

The types is merged with the current map and defined for descendant components like Vue provide / inject.

Vnode attributes ​

You can define additional attributes or properties by using a tuple of the element and the attributes.

ts
{
  types: {
    // every node of type 'doc' will have the lang attribute set to 'en'
    doc: ["article", { lang: "en" }], // [element, attributes]
  },
}
json
{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [
        {
          "type": "text",
          "text": "The line."
        }
      ]
    }
  ]
}
html
<article lang="en">
    <p>The line.</p>
</article>

This is useful when using CSS utilities framework like tailwind or unocss.

ts
{
  types: {
    // adds 'my-10' class to all paragraphs
    paragraph: ["p", { class: "my-10" }],
  },
}

ProseMirror attributes ​

The ProseMirror attributes of the node or mark data are available as the first argument when you use a function.

ts
{
  types: {
    // use the 'level' attribute from nodes of type 'header' to generate the tag name
    header: ({ level }) => `h${level}`,
  },
}
json
{
  "type": "doc",
  "content": [
    {
      "type": "header",
      "attrs": {
        "level": 1
      },
      "content": [
        {
          "type": "text",
          "text": "The header"
        }
      ]
    }
  ]
}
html
<div>
    <h1>The header</h1>
</div>

A use case for the Tiptap FontFamily extension which generate TextStyle marks.

ts
{
  types: {
    // pass 'fontFamily' attribute to the 'font-family' CSS property of a span
    textStyle: ({ fontFamily }) => ["span", { style: { fontFamily } }],
  },
}
json
{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [
        {
          "type": "text",
          "marks": [
            {
              "type": "textStyle",
              "attrs": {
                "fontFamily": "serif"
              }
            }
          ],
          "text": "Serious people use serif fonts."
        }
      ]
    }
  ]
}
html
<div>
    <p><span style="font-family: serif;">Serious people use serif fonts.</span></p>
</div>

Custom components ​

You can even use your components, but you still have to use a function definition :

ts
import { MyComponent } from "...";

provideProsemirrorOptions({
  types: {
    paragraph: () => MyComponent,
    // paragraph: MyComponent, // [WON'T WORK]
  },
});

The node or mark attributes will be available to the component as properties.

You can render marks of link type as RouterLink components from vue-router.

ts
{
  types: {
    // use 'href' attribute as the 'to' property of RouterLink and unset the href
    link: ({ href }) => ["router-link", { to: href, href: undefined }],
  },
}
json
{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [
        {
          "type": "text",
          "marks": [
            {
              "type": "link",
              "attrs": {
                "href": "/another-page"
              }
            }
          ],
          "text": "Go to another page"
        }
      ]
    }
  ]
}
html
<div>
    <p><router-link to="/another-page">Go to another page</router-link></p>
</div>

Be aware that RouterLink warns if the to property is not in the router pages.

Skipping types ​

If you work with unsafe documents, you may want to disallow rendering of specific types (like <script /> for example).

Set value to false in order to skip those types, rendered as HTML comments instead.

ts
{
  types: {
    script: false,
  },
}
json
{
  "type": "doc",
  "content": [
    {
      "type": "script",
      "content": [
        {
          "type": "text",
          "text": "console.log('unsafe code')"
        }
      ]
    }
  ]
}
html
<div>
    <!-- prosemirror type 'script' skipped -->
</div>

You can also skip all types without a match in the map by setting the skipUnknown option.

ts
{
  types: {
    // ...
  },
  skipUnknown: true,  
}

Default options ​

The default types map consist of the following HTML tag names :

ProseMirror typeVue vnode name
docdiv
headingh[level] or header
paragraphp
codecode
code_blockpre
linka
horizontal_rulehr
hard_breakbr
boldb
strongstrong
italici
emem
strikes
underlineu
subscriptsub
superscriptsup
highlightmark
blockquoteblockquote
bullet_listul
ordered_listol
list_itemli
imageimg
tabletable
table_rowtr
table_headerth
table_celltd