Example: typography
Install this example with
shadcn:npx shadcn@latest add @prosekit/react-example-typographynpx shadcn@latest add @prosekit/preact-example-typographynpx shadcn@latest add @prosekit/svelte-example-typographynpx shadcn@latest add @prosekit/vue-example-typographyimport 'prosekit/basic/style.css'
import 'prosekit/basic/typography.css'
import { useMemo } from 'preact/hooks'
import { defineBasicExtension } from 'prosekit/basic'
import {
createEditor,
type NodeJSON,
} from 'prosekit/core'
import { ProseKit } from 'prosekit/preact'
import { sampleContent } from '../../sample/sample-doc-typography'
interface EditorProps {
initialContent?: NodeJSON
}
export default function Editor(props: EditorProps) {
const defaultContent = props.initialContent ?? sampleContent
const editor = useMemo(() => {
return createEditor({ extension: defineBasicExtension(), defaultContent })
}, [defaultContent])
return (
<ProseKit editor={editor}>
<div className="box-border h-full w-full min-h-36 overflow-y-hidden overflow-x-hidden rounded-md border border-solid border-gray-200 dark:border-gray-700 shadow-sm flex flex-col bg-white dark:bg-gray-950 text-black dark:text-white">
<div className="relative w-full flex-1 box-border overflow-y-auto">
<div ref={editor.mount} className="ProseMirror box-border min-h-full px-[max(4rem,calc(50%-20rem))] py-8 outline-hidden outline-0 [&_span[data-mention=user]]:text-blue-500 [&_span[data-mention=tag]]:text-violet-500"></div>
</div>
</div>
</ProseKit>
)
}export { default as ExampleEditor } from './editor'import type { NodeJSON } from 'prosekit/core'
export const sampleContent: NodeJSON = {
type: 'doc',
content: [
{
type: 'heading',
attrs: {
level: 1,
},
content: [
{
type: 'text',
text: 'ProseKit Typography',
},
],
},
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'This example shows the typography styles provided by ',
},
{
type: 'text',
marks: [
{
type: 'code',
},
],
text: 'prosekit/basic/typography.css',
},
{
type: 'text',
text: '.',
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Inline marks',
},
],
},
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Text can be formatted in different ways: ',
},
{
type: 'text',
marks: [
{
type: 'bold',
},
],
text: 'bold text',
},
{
type: 'text',
text: ', ',
},
{
type: 'text',
marks: [
{
type: 'italic',
},
],
text: 'italic text',
},
{
type: 'text',
text: ', ',
},
{
type: 'text',
marks: [
{
type: 'underline',
},
],
text: 'underlined text',
},
{
type: 'text',
text: ', ',
},
{
type: 'text',
marks: [
{
type: 'strike',
},
],
text: 'strikethrough text',
},
{
type: 'text',
text: ', ',
},
{
type: 'text',
marks: [
{
type: 'code',
},
],
text: 'inline code',
},
{
type: 'text',
text: ' and ',
},
{
type: 'text',
marks: [
{
type: 'link',
attrs: {
href: 'https://example.com',
target: null,
rel: null,
},
},
],
text: 'links',
},
{
type: 'text',
text: '.',
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Lists',
},
],
},
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Here are different types of lists:',
},
],
},
{
type: 'list',
attrs: {
kind: 'bullet',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Unordered list item 1',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'bullet',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Unordered list item 2',
},
],
},
{
type: 'list',
attrs: {
kind: 'bullet',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Nested item A',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'bullet',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Nested item B',
},
],
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'ordered',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'First ordered item',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'ordered',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Second ordered item',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'task',
order: null,
checked: true,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Completed task',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'task',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Pending task',
},
],
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Blockquotes',
},
],
},
{
type: 'blockquote',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'This is a blockquote demonstrating how quoted content appears in the editor. It can span multiple lines and maintains proper formatting.',
},
],
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Code Blocks',
},
],
},
{
type: 'codeBlock',
attrs: {
language: '',
},
content: [
{
type: 'text',
text: "function example() {\n const greeting = 'Hello ProseKit!';\n console.log(greeting);\n return greeting;\n}",
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Horizontal Rule',
},
],
},
{
type: 'horizontalRule',
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Images',
},
],
},
{
type: 'image',
attrs: {
src: 'https://static.photos/blurred/640x360/42',
},
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Tables',
},
],
},
{
type: 'table',
content: [
{
type: 'tableRow',
content: [
{
type: 'tableHeaderCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Header 1',
},
],
},
],
},
{
type: 'tableHeaderCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Header 2',
},
],
},
],
},
],
},
{
type: 'tableRow',
content: [
{
type: 'tableCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Cell 1',
},
],
},
],
},
{
type: 'tableCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Cell 2',
},
],
},
],
},
],
},
{
type: 'tableRow',
content: [
{
type: 'tableCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Cell 3',
},
],
},
],
},
{
type: 'tableCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Cell 4',
},
],
},
],
},
],
},
],
},
],
}import 'prosekit/basic/style.css'
import 'prosekit/basic/typography.css'
import { defineBasicExtension } from 'prosekit/basic'
import {
createEditor,
type NodeJSON,
} from 'prosekit/core'
import { ProseKit } from 'prosekit/react'
import { useMemo } from 'react'
import { sampleContent } from '../../sample/sample-doc-typography'
interface EditorProps {
initialContent?: NodeJSON
}
export default function Editor(props: EditorProps) {
const defaultContent = props.initialContent ?? sampleContent
const editor = useMemo(() => {
return createEditor({ extension: defineBasicExtension(), defaultContent })
}, [defaultContent])
return (
<ProseKit editor={editor}>
<div className="box-border h-full w-full min-h-36 overflow-y-hidden overflow-x-hidden rounded-md border border-solid border-gray-200 dark:border-gray-700 shadow-sm flex flex-col bg-white dark:bg-gray-950 text-black dark:text-white">
<div className="relative w-full flex-1 box-border overflow-y-auto">
<div ref={editor.mount} className="ProseMirror box-border min-h-full px-[max(4rem,calc(50%-20rem))] py-8 outline-hidden outline-0 [&_span[data-mention=user]]:text-blue-500 [&_span[data-mention=tag]]:text-violet-500"></div>
</div>
</div>
</ProseKit>
)
}'use client'
export { default as ExampleEditor } from './editor'import type { NodeJSON } from 'prosekit/core'
export const sampleContent: NodeJSON = {
type: 'doc',
content: [
{
type: 'heading',
attrs: {
level: 1,
},
content: [
{
type: 'text',
text: 'ProseKit Typography',
},
],
},
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'This example shows the typography styles provided by ',
},
{
type: 'text',
marks: [
{
type: 'code',
},
],
text: 'prosekit/basic/typography.css',
},
{
type: 'text',
text: '.',
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Inline marks',
},
],
},
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Text can be formatted in different ways: ',
},
{
type: 'text',
marks: [
{
type: 'bold',
},
],
text: 'bold text',
},
{
type: 'text',
text: ', ',
},
{
type: 'text',
marks: [
{
type: 'italic',
},
],
text: 'italic text',
},
{
type: 'text',
text: ', ',
},
{
type: 'text',
marks: [
{
type: 'underline',
},
],
text: 'underlined text',
},
{
type: 'text',
text: ', ',
},
{
type: 'text',
marks: [
{
type: 'strike',
},
],
text: 'strikethrough text',
},
{
type: 'text',
text: ', ',
},
{
type: 'text',
marks: [
{
type: 'code',
},
],
text: 'inline code',
},
{
type: 'text',
text: ' and ',
},
{
type: 'text',
marks: [
{
type: 'link',
attrs: {
href: 'https://example.com',
target: null,
rel: null,
},
},
],
text: 'links',
},
{
type: 'text',
text: '.',
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Lists',
},
],
},
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Here are different types of lists:',
},
],
},
{
type: 'list',
attrs: {
kind: 'bullet',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Unordered list item 1',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'bullet',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Unordered list item 2',
},
],
},
{
type: 'list',
attrs: {
kind: 'bullet',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Nested item A',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'bullet',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Nested item B',
},
],
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'ordered',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'First ordered item',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'ordered',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Second ordered item',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'task',
order: null,
checked: true,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Completed task',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'task',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Pending task',
},
],
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Blockquotes',
},
],
},
{
type: 'blockquote',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'This is a blockquote demonstrating how quoted content appears in the editor. It can span multiple lines and maintains proper formatting.',
},
],
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Code Blocks',
},
],
},
{
type: 'codeBlock',
attrs: {
language: '',
},
content: [
{
type: 'text',
text: "function example() {\n const greeting = 'Hello ProseKit!';\n console.log(greeting);\n return greeting;\n}",
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Horizontal Rule',
},
],
},
{
type: 'horizontalRule',
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Images',
},
],
},
{
type: 'image',
attrs: {
src: 'https://static.photos/blurred/640x360/42',
},
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Tables',
},
],
},
{
type: 'table',
content: [
{
type: 'tableRow',
content: [
{
type: 'tableHeaderCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Header 1',
},
],
},
],
},
{
type: 'tableHeaderCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Header 2',
},
],
},
],
},
],
},
{
type: 'tableRow',
content: [
{
type: 'tableCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Cell 1',
},
],
},
],
},
{
type: 'tableCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Cell 2',
},
],
},
],
},
],
},
{
type: 'tableRow',
content: [
{
type: 'tableCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Cell 3',
},
],
},
],
},
{
type: 'tableCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Cell 4',
},
],
},
],
},
],
},
],
},
],
}<script lang="ts">
import 'prosekit/basic/style.css'
import 'prosekit/basic/typography.css'
import { defineBasicExtension } from 'prosekit/basic'
import {
createEditor,
type NodeJSON,
} from 'prosekit/core'
import { ProseKit } from 'prosekit/svelte'
import { sampleContent } from '../../sample/sample-doc-typography'
const props: {
initialContent?: NodeJSON
} = $props()
const extension = defineBasicExtension()
const defaultContent = props.initialContent ?? sampleContent
const editor = createEditor({ extension, defaultContent })
const mount = (element: HTMLElement) => {
editor.mount(element)
return { destroy: () => editor.unmount() }
}
</script>
<ProseKit {editor}>
<div class="box-border h-full w-full min-h-36 overflow-y-hidden overflow-x-hidden rounded-md border border-solid border-gray-200 dark:border-gray-700 shadow-sm flex flex-col bg-white dark:bg-gray-950 text-black dark:text-white">
<div class="relative w-full flex-1 box-border overflow-y-auto">
<div use:mount class="ProseMirror box-border min-h-full px-[max(4rem,calc(50%-20rem))] py-8 outline-hidden outline-0 [&_span[data-mention=user]]:text-blue-500 [&_span[data-mention=tag]]:text-violet-500"></div>
</div>
</div>
</ProseKit>export { default as ExampleEditor } from './editor.svelte'import type { NodeJSON } from 'prosekit/core'
export const sampleContent: NodeJSON = {
type: 'doc',
content: [
{
type: 'heading',
attrs: {
level: 1,
},
content: [
{
type: 'text',
text: 'ProseKit Typography',
},
],
},
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'This example shows the typography styles provided by ',
},
{
type: 'text',
marks: [
{
type: 'code',
},
],
text: 'prosekit/basic/typography.css',
},
{
type: 'text',
text: '.',
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Inline marks',
},
],
},
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Text can be formatted in different ways: ',
},
{
type: 'text',
marks: [
{
type: 'bold',
},
],
text: 'bold text',
},
{
type: 'text',
text: ', ',
},
{
type: 'text',
marks: [
{
type: 'italic',
},
],
text: 'italic text',
},
{
type: 'text',
text: ', ',
},
{
type: 'text',
marks: [
{
type: 'underline',
},
],
text: 'underlined text',
},
{
type: 'text',
text: ', ',
},
{
type: 'text',
marks: [
{
type: 'strike',
},
],
text: 'strikethrough text',
},
{
type: 'text',
text: ', ',
},
{
type: 'text',
marks: [
{
type: 'code',
},
],
text: 'inline code',
},
{
type: 'text',
text: ' and ',
},
{
type: 'text',
marks: [
{
type: 'link',
attrs: {
href: 'https://example.com',
target: null,
rel: null,
},
},
],
text: 'links',
},
{
type: 'text',
text: '.',
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Lists',
},
],
},
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Here are different types of lists:',
},
],
},
{
type: 'list',
attrs: {
kind: 'bullet',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Unordered list item 1',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'bullet',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Unordered list item 2',
},
],
},
{
type: 'list',
attrs: {
kind: 'bullet',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Nested item A',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'bullet',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Nested item B',
},
],
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'ordered',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'First ordered item',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'ordered',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Second ordered item',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'task',
order: null,
checked: true,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Completed task',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'task',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Pending task',
},
],
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Blockquotes',
},
],
},
{
type: 'blockquote',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'This is a blockquote demonstrating how quoted content appears in the editor. It can span multiple lines and maintains proper formatting.',
},
],
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Code Blocks',
},
],
},
{
type: 'codeBlock',
attrs: {
language: '',
},
content: [
{
type: 'text',
text: "function example() {\n const greeting = 'Hello ProseKit!';\n console.log(greeting);\n return greeting;\n}",
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Horizontal Rule',
},
],
},
{
type: 'horizontalRule',
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Images',
},
],
},
{
type: 'image',
attrs: {
src: 'https://static.photos/blurred/640x360/42',
},
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Tables',
},
],
},
{
type: 'table',
content: [
{
type: 'tableRow',
content: [
{
type: 'tableHeaderCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Header 1',
},
],
},
],
},
{
type: 'tableHeaderCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Header 2',
},
],
},
],
},
],
},
{
type: 'tableRow',
content: [
{
type: 'tableCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Cell 1',
},
],
},
],
},
{
type: 'tableCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Cell 2',
},
],
},
],
},
],
},
{
type: 'tableRow',
content: [
{
type: 'tableCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Cell 3',
},
],
},
],
},
{
type: 'tableCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Cell 4',
},
],
},
],
},
],
},
],
},
],
}<script setup lang="ts">
import 'prosekit/basic/style.css'
import 'prosekit/basic/typography.css'
import { defineBasicExtension } from 'prosekit/basic'
import {
createEditor,
type NodeJSON,
} from 'prosekit/core'
import { ProseKit } from 'prosekit/vue'
import {
ref,
watchPostEffect,
} from 'vue'
import { sampleContent } from '../../sample/sample-doc-typography'
const props = defineProps<{
initialContent?: NodeJSON
}>()
const extension = defineBasicExtension()
const defaultContent = props.initialContent ?? sampleContent
const editor = createEditor({ extension, defaultContent })
const editorRef = ref<HTMLDivElement | null>(null)
watchPostEffect((onCleanup) => {
editor.mount(editorRef.value)
onCleanup(() => editor.unmount())
})
</script>
<template>
<ProseKit :editor="editor">
<div class="box-border h-full w-full min-h-36 overflow-y-hidden overflow-x-hidden rounded-md border border-solid border-gray-200 dark:border-gray-700 shadow-sm flex flex-col bg-white dark:bg-gray-950 text-black dark:text-white">
<div class="relative w-full flex-1 box-border overflow-y-auto">
<div ref="editorRef" class="ProseMirror box-border min-h-full px-[max(4rem,calc(50%-20rem))] py-8 outline-hidden outline-0 [&_span[data-mention=user]]:text-blue-500 [&_span[data-mention=tag]]:text-violet-500" />
</div>
</div>
</ProseKit>
</template>export { default as ExampleEditor } from './editor.vue'import type { NodeJSON } from 'prosekit/core'
export const sampleContent: NodeJSON = {
type: 'doc',
content: [
{
type: 'heading',
attrs: {
level: 1,
},
content: [
{
type: 'text',
text: 'ProseKit Typography',
},
],
},
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'This example shows the typography styles provided by ',
},
{
type: 'text',
marks: [
{
type: 'code',
},
],
text: 'prosekit/basic/typography.css',
},
{
type: 'text',
text: '.',
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Inline marks',
},
],
},
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Text can be formatted in different ways: ',
},
{
type: 'text',
marks: [
{
type: 'bold',
},
],
text: 'bold text',
},
{
type: 'text',
text: ', ',
},
{
type: 'text',
marks: [
{
type: 'italic',
},
],
text: 'italic text',
},
{
type: 'text',
text: ', ',
},
{
type: 'text',
marks: [
{
type: 'underline',
},
],
text: 'underlined text',
},
{
type: 'text',
text: ', ',
},
{
type: 'text',
marks: [
{
type: 'strike',
},
],
text: 'strikethrough text',
},
{
type: 'text',
text: ', ',
},
{
type: 'text',
marks: [
{
type: 'code',
},
],
text: 'inline code',
},
{
type: 'text',
text: ' and ',
},
{
type: 'text',
marks: [
{
type: 'link',
attrs: {
href: 'https://example.com',
target: null,
rel: null,
},
},
],
text: 'links',
},
{
type: 'text',
text: '.',
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Lists',
},
],
},
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Here are different types of lists:',
},
],
},
{
type: 'list',
attrs: {
kind: 'bullet',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Unordered list item 1',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'bullet',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Unordered list item 2',
},
],
},
{
type: 'list',
attrs: {
kind: 'bullet',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Nested item A',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'bullet',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Nested item B',
},
],
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'ordered',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'First ordered item',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'ordered',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Second ordered item',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'task',
order: null,
checked: true,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Completed task',
},
],
},
],
},
{
type: 'list',
attrs: {
kind: 'task',
order: null,
checked: false,
collapsed: false,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Pending task',
},
],
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Blockquotes',
},
],
},
{
type: 'blockquote',
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'This is a blockquote demonstrating how quoted content appears in the editor. It can span multiple lines and maintains proper formatting.',
},
],
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Code Blocks',
},
],
},
{
type: 'codeBlock',
attrs: {
language: '',
},
content: [
{
type: 'text',
text: "function example() {\n const greeting = 'Hello ProseKit!';\n console.log(greeting);\n return greeting;\n}",
},
],
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Horizontal Rule',
},
],
},
{
type: 'horizontalRule',
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Images',
},
],
},
{
type: 'image',
attrs: {
src: 'https://static.photos/blurred/640x360/42',
},
},
{
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'Tables',
},
],
},
{
type: 'table',
content: [
{
type: 'tableRow',
content: [
{
type: 'tableHeaderCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Header 1',
},
],
},
],
},
{
type: 'tableHeaderCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Header 2',
},
],
},
],
},
],
},
{
type: 'tableRow',
content: [
{
type: 'tableCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Cell 1',
},
],
},
],
},
{
type: 'tableCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Cell 2',
},
],
},
],
},
],
},
{
type: 'tableRow',
content: [
{
type: 'tableCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Cell 3',
},
],
},
],
},
{
type: 'tableCell',
attrs: {
colspan: 1,
rowspan: 1,
colwidth: null,
},
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Cell 4',
},
],
},
],
},
],
},
],
},
],
}