前面介绍过,tiptap是一个headless的编辑器,所以他自己是没有样式的,我们需要手动给他添加一些样式。文档中介绍了三种美化编辑器的方式,听我一一道来。
整个编辑器都是被一个class为ProseMirror的div所包裹,所以你可以直接在样式表中对class为ProseMirror的样式进行修饰。比如:
- /* Scoped to the editor */
- .ProseMirror p {
- margin: 1em 0;
- }
你可以自定义一些class,然后将这些class通过配置项载入到对应扩展或editor本身中。如果是editor本身,则如下所示
- new Editor({
- editorProps: {
- attributes: {
- class: 'prose prose-sm sm:prose lg:prose-lg xl:prose-2xl mx-auto focus:outline-none',
- },
- },
- })
如果是一些扩展,如下所示
- new Editor({
- extensions: [
- Document,
- Paragraph.configure({
- HTMLAttributes: {
- class: 'my-custom-paragraph',
- },
- }),
- Heading.configure({
- HTMLAttributes: {
- class: 'my-custom-heading',
- },
- }),
- Text,
- ],
- })
你也可以在原来扩展的基础上做一些样式上的修改,成为一个新的扩展
- import Bold from '@tiptap/extension-bold'
-
- const CustomBold = Bold.extend({
- renderHTML({ HTMLAttributes }) {
- // Original:
- // return ['strong', HTMLAttributes, 0]
- return ['b', HTMLAttributes, 0]
- },
- })
-
- new Editor({
- extensions: [
- // …
- CustomBold,
- ],
- })
这三种方式,我比较推荐第二种,一方面这种配置的方式比较灵活,另一方面,可以操作到node上,比第一种方式更精细也不容易出错。
这一节主要讲,如何将编辑器里的内容转化为json字符串或者html字符串存储起来,以及如何把这两种格式的字符串传给编辑器并呈现内容。
如何得到当前编辑器文本内容的json字符串?
const json = editor.getJSON()
同理对于html字符串:
const html = editor.getHTML()
如何将json字符串传给编辑器并显示内容?
首先,你要知道,getJSON()返回的json字符串是类似以下的格式:
- {
- "type": "doc",
- "content": [
- {
- "type": "paragraph",
- "content": [
- {
- "type": "text",
- "text": "Wow, this editor instance exports its content as JSON."
- }
- ]
- }
- ]
- }
符合这样的格式,且最外层的"type"为"doc",那么将该字符串content传入以下方法
editor.commands.setContent(content)
同理对于html字符串
editor.commands.setContent(`
Example Text
`)如果你想监听内容的改变,那么可以这么做
- const editor = new Editor({
- // intial content
- content: `
Example Content
`, -
- // triggered on every change
- onUpdate: ({ editor }) => {
- const json = editor.getJSON()
- // send the content to an API here
- },
- })
在某些场景下,需要对内容的格式进行转换。比如,用户在web端的某个tiptap编辑器内写了内容并以json格式保存至远程服务器中,而远程服务器需要根据这段内容生成html并返回,那么就需要用到这个功能。
JSON转HTML
- <pre><code>{{ output }}code>pre>
-
- <script>
- // Option 1: Browser + server-side
- import Bold from '@tiptap/extension-bold'
- // Option 2: Browser-only (lightweight)
- // import { generateHTML } from '@tiptap/core'
- import Document from '@tiptap/extension-document'
- import Paragraph from '@tiptap/extension-paragraph'
- import Text from '@tiptap/extension-text'
- import { generateHTML } from '@tiptap/html'
-
- const json = {
- type: 'doc',
- content: [
- {
- type: 'paragraph',
- content: [
- {
- type: 'text',
- text: 'Example ',
- },
- {
- type: 'text',
- marks: [
- {
- type: 'bold',
- },
- ],
- text: 'Text',
- },
- ],
- },
- ],
- }
-
- export default {
- computed: {
- output() {
- return generateHTML(json, [
- Document,
- Paragraph,
- Text,
- Bold,
- // other extensions …
- ])
- },
- },
- }
- script>
显示结果:
Example Text
HTML转JSON
- <pre><code>{{ output }}code>pre>
-
- <script>
- // Option 1: Browser + server-side
- import Bold from '@tiptap/extension-bold'
- // Option 2: Browser-only (lightweight)
- // import { generateHTML } from '@tiptap/core'
- import Document from '@tiptap/extension-document'
- import Paragraph from '@tiptap/extension-paragraph'
- import Text from '@tiptap/extension-text'
- import { generateHTML } from '@tiptap/html'
-
- const json = {
- type: 'doc',
- content: [
- {
- type: 'paragraph',
- content: [
- {
- type: 'text',
- text: 'Example ',
- },
- {
- type: 'text',
- marks: [
- {
- type: 'bold',
- },
- ],
- text: 'Text',
- },
- ],
- },
- ],
- }
-
- export default {
- computed: {
- output() {
- return generateHTML(json, [
- Document,
- Paragraph,
- Text,
- Bold,
- // other extensions …
- ])
- },
- },
- }
- script>
显示结果:
Example Text