Skip to content
GitHub

Saving and Loading Content

Saving and loading content is a fundamental requirement for any editor. ProseKit provides flexible options for persisting your content in different formats, primarily JSON and HTML. This guide will show you how to implement content persistence in your ProseKit editor.

Supported Formats

ProseKit supports multiple content formats:

FormatDescriptionBest For
JSONNative ProseMirror document structureLong-term storage, preserving all features
HTMLStandard HTML markupInteroperability with other systems, display

Working with JSON

JSON is the recommended format for storing ProseKit documents because it preserves the exact structure and all attributes of your content.

Saving Content as JSON

To get your document as JSON, use the getDocJSON() method:

// Get the current document as a JSON object
const json = editor.getDocJSON()

Loading Content from JSON

To load content from JSON when creating an editor:

// Create editor with the loaded content
const editor = createEditor({
  extension,
  defaultContent: json, // Pass the JSON object directly
})

Detecting Document Changes

To save content when the document changes, use the useDocChange hook:

import { useDocChange } from 'prosekit/react'

useDocChange(() => {
  // This runs whenever the document changes
  const json = editor.getDocJSON()
  localStorage.setItem('my-document', JSON.stringify(json))
}, { editor })

JSON Example

Here’s a complete example of saving and loading content using JSON:

import 'prosekit/basic/style.css'
import 'prosekit/basic/typography.css'

import type { Editor } from 'prosekit/core'
import {
  ProseKit,
  useDocChange,
} from 'prosekit/react'

export default function EditorComponent({
  editor,
  onDocChange,
}: {
  editor: Editor
  onDocChange: () => void
}) {
  useDocChange(onDocChange, { editor })

  return (
    <ProseKit editor={editor}>
      <div className='relative w-full flex-1 box-border overflow-y-scroll'>
        <div ref={editor.mount} className='ProseMirror box-border min-h-full px-[max(4rem,_calc(50%-20rem))] py-8 outline-none outline-0 [&_span[data-mention="user"]]:text-blue-500 [&_span[data-mention="tag"]]:text-violet-500'></div>
      </div>
    </ProseKit>
  )
}

Working with HTML

HTML is useful when you need to display your content outside the editor or integrate with systems that understand HTML.

Saving Content as HTML

To convert your document to HTML:

// Get the current document as an HTML string
const html = editor.getDocHTML()

// Store the HTML
localStorage.setItem('my-document-html', html)

Loading Content from HTML

To load content from HTML:

// Retrieve stored HTML
const html = localStorage.getItem('my-document-html')

// Create editor with the loaded HTML
const editor = createEditor({
  extension,
  defaultContent: html, // Pass the HTML string
})

HTML Example

Here’s an example of saving and loading content using HTML:

import 'prosekit/basic/style.css'
import 'prosekit/basic/typography.css'

import type { Editor } from 'prosekit/core'
import {
  ProseKit,
  useDocChange,
} from 'prosekit/react'

export default function EditorComponent({
  editor,
  onDocChange,
}: {
  editor: Editor
  onDocChange: () => void
}) {
  useDocChange(onDocChange, { editor })

  return (
    <ProseKit editor={editor}>
      <div className='relative w-full flex-1 box-border overflow-y-scroll'>
        <div ref={editor.mount} className='ProseMirror box-border min-h-full px-[max(4rem,_calc(50%-20rem))] py-8 outline-none outline-0 [&_span[data-mention="user"]]:text-blue-500 [&_span[data-mention="tag"]]:text-violet-500'></div>
      </div>
    </ProseKit>
  )
}

Working with Markdown

While ProseKit doesn’t directly support Markdown as a storage format, you can add Markdown support using additional libraries.

Markdown Example

Here’s an example of using Markdown for saving and loading. It uses the remark and rehype libraries to convert between Markdown and HTML.

import 'prosekit/basic/style.css'
import 'prosekit/basic/typography.css'

import type { Editor } from 'prosekit/core'
import {
  ProseKit,
  useDocChange,
} from 'prosekit/react'

export default function EditorComponent({
  editor,
  onDocChange,
}: {
  editor: Editor
  onDocChange: () => void
}) {
  useDocChange(onDocChange, { editor })

  return (
    <ProseKit editor={editor}>
      <div className='relative w-full flex-1 box-border overflow-y-scroll'>
        <div ref={editor.mount} className='ProseMirror box-border min-h-full px-[max(4rem,_calc(50%-20rem))] py-8 outline-none outline-0 [&_span[data-mention="user"]]:text-blue-500 [&_span[data-mention="tag"]]:text-violet-500'></div>
      </div>
    </ProseKit>
  )
}

Conversion Utilities

ProseKit provides utility functions for converting between plain JSON object, HTML string, and ProseMirrorNode.