• 作者:老汪软件技巧
  • 发表时间:2024-09-22 15:00
  • 浏览量:

项目地址:tiptap-editor

效果展示:lify.app/

持续更新中

技术栈实现功能操作准备工作初始化Nextjs

为了能快速的看到效果,先在Nextjs项目中直接开发编辑器

初始化一个Nextjs项目,命名为tiptap-editor

初始化时配置使用ts、tailwindcss、app router、alias为@/、使用src目录

之后删除page.tsx,layout.tsx,global.css中无用的部分,获得一个干净的项目。

安装Shadcn/ui

按照Shadcn/ui官网指示,使用以下命令初始化

pnpm dlx shadcn@latest init

Shadcn/ui配置如下

{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "default",
  "rsc": true,
  "tsx": true,
  "tailwind": {
    "config": "tailwind.config.ts",
    "css": "src/app/globals.css",
    "baseColor": "neutral",
    "cssVariables": true,
    "prefix": ""
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils",
    "ui": "@/components/ui",
    "lib": "@/lib",
    "hooks": "@/hooks"
  }
}

安装 lucide-icon

pnpm install lucide-react

安装tiptap

按照tiptap官网,安装命令如下

pnpm install @tiptap/react @tiptap/pm @tiptap/starter-kit

之后在src目录下新建components/editor目录,新建index.tsx文件,存放编辑器组件

'use client'
import { useEditor, EditorContent } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
const TiptapEditor = () => {
  const editor = useEditor({
    extensions: [StarterKit],
    content: '

Hello World! ️

'
, }) return <EditorContent editor={editor} /> } export default TiptapEditor

之后在page.tsx中引入组件并编写一些样式

import TiptapEditor from '@/components/editor'
export default function Home() {
  return (
    <main>
      <div className="max-w-2xl mx-auto py-16 px-12">
        <TiptapEditor />
      div>
    main>
  )
}

这样启动项目后就可以看到编辑器了

至此,准备工作就完成了,之后就该实现各类功能了。

配置样式

由于Tiptap是一个无头的编辑器,所以所有的内容样式都要由我们自己编写,随着内置功能的增加,我们的样式也会逐渐增加,所以我们在添加插件的时候同步添加样式,这里先配置好样式的文件。

新建文件src/components/editor/index.css

.tiptap {
  @apply focus-visible:outline-none;
}
.tiptap :first-child {
  margin-top: 0;
}

在Editor组件中引入

import './index.css'

Tiptap的内容都是由.tiptap类包括的,所以在编写样式的时候都要在前面添加.tiptap,这样的样式才会只作用于编辑器内容,而不会影响页面其他元素。

/* Scoped to the editor */
.tiptap p {
  margin: 1em 0;
}

创建基于文本文档的程序__文本建立

由于我们要用的是tailwindcss,并且用了TailwindCSS Intellisense插件,所以可以在.vscode/setting.json中添加下面的配置,以在配置tiptap的时候使用到插件的自动提示功能(tiptap在配置插件的时候可以给内容块添加自定义类)

"tailwindCSS.experimental.classRegex": [
  "class:\\s*?[\"'`]([^\"'`]*).*?,"
]

Tiptap的插件

插件是Tiptap的核心功能,基本上所有的功能和内容都是由插件提供,甚至最基础的段落都是由插件提供,可以说没有插件,tiptap就没有任何功能。

tiptap官方提供了大量的插件供开发者使用,其中有一些可以直接用的插件和一些Pro插件,但是这个Pro插件不是付费才可以使用,而是注册tiptap的应用就可以使用。

starter-kit

对于一些基础的插件,tiptap封装了一个包供开发者快速使用@tiptap/starter-kit

这个插件在上面我们初始化编辑器的时候已经添加了,之后就是配置对应的样式

.tiptap {
  @apply focus-visible:outline-none;
}
.tiptap :first-child {
  margin-top: 0;
}
.tiptap blockquote {
  @apply border-l-2 border-gray-300 pl-4 my-4;
}
.tiptap pre {
  @apply bg-gray-600 p-4 my-4 rounded-md text-white;
}
.tiptap pre code {
  @apply bg-gray-600 p-1 my-1 rounded-md text-white;
}
.tiptap h1,
h2,
h3,
h4,
h5,
h6 {
  @apply my-4 font-bold leading-tight;
}
.tiptap h1 {
  @apply text-4xl;
}
.tiptap h2 {
  @apply text-3xl;
}
.tiptap h3 {
  @apply text-2xl;
}
.tiptap h4,
h5,
h6 {
  @apply text-xl;
}
.tiptap hr {
  @apply my-6 border-t border-gray-300;
}
.tiptap ul,
ol {
  @apply mx-4 mt-4 mb-4;
}
.tiptap ul {
  @apply list-disc;
}
.tiptap ul ul {
  @apply m-0 ml-5 list-[circle];
}
.tiptap ul ul ul {
  @apply m-0 ml-5 list-[square];
}
.tiptap ol {
  @apply list-decimal;
}
.tiptap ol ol {
  @apply m-0 ml-5;
}
.tiptap ul p,
ol p {
  @apply my-0;
}
.tiptap code {
  @apply bg-gray-600 px-1 my-1 mx-1 rounded-md text-white text-sm;
}
.tiptap p {
  @apply my-2;
}

这样不同内容的样式就可以展示出来了

这里包括了

下划线

需要安装@tiptap/extension-underline插件

pnpm install @tiptap/extension-underline

之后在编辑器中安装插件

const editor = useEditor({
  extensions: [StarterKit, Underline],
  // ...
})

todo列表

需要安装@tiptap/extension-task-list和@tiptap/extension-task-item插件

pnpm install @tiptap/extension-task-list @tiptap/extension-task-item

之后在编辑器中安装插件

const editor = useEditor({
  extensions: [
    StarterKit,
    Underline,
    TaskList,
    TaskItem.configure({
      nested: true,
    }),
  ],
  // ...
})

这样还不够,因为任务列表的实现是基于ul的,必须设置额外的样式

在index.css中添加

.tiptap ul[data-type="taskList"] {
  @apply list-none ml-0 p-0;
}
.tiptap ul[data-type="taskList"] li {
  @apply items-start flex;
}
.tiptap ul[data-type="taskList"] li>label {
  @apply flex-shrink-0 mr-2 select-none;
}
.tiptap ul[data-type="taskList"] li>div {
  @apply flex-auto;
}
.tiptap ul[data-type="taskList"] input[type="checkbox"] {
  @apply cursor-pointer;
}
.tiptap ul[data-type="taskList"] ul[data-type="taskList"] {
  @apply m-0;
}

超链接

实现超链接需要安装@tiptap/extension-link

pnpm install @tiptap/extension-link

之后添加插件,并自定义插件的配置

const editor = useEditor({
  extensions: [
    StarterKit,
    Underline,
    TaskList,
    TaskItem.configure({
      nested: true,
    }),
    Link.configure({
      openOnClick: true,
      autolink: true,
      defaultProtocol: 'https',
    }),
    // ...
  ],
})

之后需要添加超链接的样式

.tiptap a {
  @apply text-blue-500 underline cursor-pointer;
}
.tiptap a:hover {
  @apply text-blue-600;
}

总结

通过上文的配置,我们就得到了一个可以展示和编辑一些常用元素的富文本编辑器,接下来就是对编辑器继续优化,添加更多的内容支持,包括公式、图片等;以及添加编辑内容时用到的控件,让使用者可以方便地编辑内容。