本文為開發開源項目的真實開發經歷,感興趣的可以來給我的項目點個star,謝謝啦~
具體博文介紹:
開源|Documind協同文檔(接入deepseek-r1、支持實時聊天)Documind 🚀 一個支持實時聊天和接入 - 掘金
我干了什么
我定義了兩個插件:
font-size
:支持通過setFontSize
設置tiptap
編輯器字體大小,通過unsetFontSize
重置為默認大小。line-height
:支持通過設置setLineHeight
設置tiptap
編輯器行高,通過unsetLineHeight
重置為默認行高。
源碼參考
這里就不一點一點講解了,注釋看不懂的話可以叫AI幫你解析。
font-size
插件:
import { Extension } from "@tiptap/core";
import "@tiptap/extension-text-style";// 聲明類型
declare module "@tiptap/core" {interface Commands<ReturnType> {fontSize: {/** 設置字體大小(支持CSS單位如12px/1.2rem等) */setFontSize: (fontSize: string) => ReturnType;/** 清除字體大小設置 */unsetFontSize: () => ReturnType;};}
}// 創建擴展
export const FontSizeExtension = Extension.create({name: "fontSize",// 擴展配置項addOptions() {return {types: ["textStyle"], // 作用對象為文本樣式標記};},// 注冊全局屬性addGlobalAttributes() {return [{types: this.options.types, // 應用范圍(textStyle類型)attributes: {fontSize: {default: null, // 默認無字體大小// 從DOM解析字體大小(讀取style屬性)parseHTML: (element) => element.style.fontSize,// 渲染到DOM時生成樣式renderHTML: (attributes) => {if (!attributes.fontSize) {return {}; // 無設置時返回空對象}return {style: `font-size: ${attributes.fontSize};`, // 生成內聯樣式};},},},},];},// 注冊編輯器命令addCommands() {return {/** 設置字體大小命令 */setFontSize:(fontSize: string) =>({ chain }) => {return chain().setMark("textStyle", { fontSize }) // 更新文本樣式標記.run();},/** 清除字體大小命令 */unsetFontSize:() =>({ chain }) => {return chain().setMark("textStyle", { fontSize: null }) // 清除字體大小屬性.removeEmptyTextStyle() // 移除空文本樣式標記.run();},};},
});
line-height插件:
import { Extension } from "@tiptap/core";// 類型聲明:擴展Tiptap的命令接口
declare module "@tiptap/core" {interface Commands<ReturnType> {lineHeight: {/** 設置行高(支持CSS單位如1.5/2/24px等) */setLineHeight: (lineHeight: string) => ReturnType;/** 重置為默認行高 */unsetLineHeight: () => ReturnType;};}
}export const LineHeightExtension = Extension.create({name: "lineHeight",// 擴展配置項addOptions() {return {types: ["paragraph", "heading"], // 應用行高樣式的節點類型defaultLineHeight: null, // 默認行高(null表示不設置)};},// 添加全局屬性處理addGlobalAttributes() {return [{types: this.options.types, // 應用到的節點類型attributes: {lineHeight: {// 默認值(從配置項獲取)default: this.options.defaultLineHeight,// 渲染到HTML時的處理renderHTML: (attributes) => {if (!attributes.lineHeight) {return {};}// 將行高轉換為行內樣式return {style: `line-height: ${attributes.lineHeight};`,};},// 從HTML解析時的處理parseHTML: (element) => {return {// 獲取行高樣式或使用默認值lineHeight: element.style.lineHeight || this.options.defaultLineHeight,};},},},},];},// 添加自定義命令addCommands() {return {setLineHeight:(lineHeight) =>({ tr, state, dispatch }) => {// 創建事務副本以保持不可變性tr = tr.setSelection(state.selection);// 遍歷選區內的所有節點state.doc.nodesBetween(state.selection.from, state.selection.to, (node, pos) => {// 只處理配置的類型節點if (this.options.types.includes(node.type.name)) {tr = tr.setNodeMarkup(pos, undefined, {...node.attrs,lineHeight, // 更新行高屬性});}});// 提交事務更新if (dispatch) {dispatch(tr);}return true;},unsetLineHeight:() =>({ tr, state, dispatch }) => {tr = tr.setSelection(state.selection);// 遍歷選區節點重置行高state.doc.nodesBetween(state.selection.from, state.selection.to, (node, pos) => {if (this.options.types.includes(node.type.name)) {tr = tr.setNodeMarkup(pos, undefined, {...node.attrs,lineHeight: this.options.defaultLineHeight, // 重置為默認值});}});if (dispatch) {dispatch(tr);}return true;},};},
});
使用案例
首先我們在extensions中添加擴展以激活
extensions: [/*......*/FontSizeExtension,LineHeightExtension.configure({types: ["paragraph", "heading"],}),/*......*/
];