wordpress导入UI框架,优化大师软件大全,wordpress 写php代码,amon wordpress一、背景概述
项目有自定义样式模板的需求#xff0c;WangEditor没有。若直接把样式的html插入WangEditor中#xff0c;无法解析#xff0c;且会被自动过滤。因此#xff0c;需要基于WangEditor提供的API进行二次开发。 例如#xff0c;需要新增以下样式#xff1a; 该…一、背景概述
项目有自定义样式模板的需求WangEditor没有。若直接把样式的html插入WangEditor中无法解析且会被自动过滤。因此需要基于WangEditor提供的API进行二次开发。 例如需要新增以下样式 该样式的html为
div stylepadding: 10px; margin: 5px 0px 0px; max-width: 100%; line-height: 25px;
font-size: 16px; font-family: 微软雅黑; border-top-left-radius: 4px;
border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px;
color: rgb(255, 255, 255); border-left-color: rgb(0, 187, 236); border-left-width: 10px;
border-left-style: solid; box-shadow: rgb(153, 153, 153) 2px 2px 4px;
text-shadow: rgb(34, 95, 135) 0px 1px 0px; word-wrap: break-word; box-sizing: border-box;
background-color: rgb(55, 57, 57);1、在这里输入标题/div二、基于WangEditor扩展新功能
官方文档https://www.wangeditor.com/v5/development.html 根据官方提供的文档介绍wangEditor的元素都需要定义其对应的节点数据结构否则无法渲染。 我们根据官方文档的步骤从定义类型、在编辑器渲染新元素、把新元素转换为 HTML、解析新元素 HTML 到编辑器四个步骤来介绍。 一般我们会创建一个文件夹用于存放这个自定义元素的代码。
1. 定义节点的类型
这里定义的方式比较固定这是为后面插入节点准备的。WangEditor采用数据驱动视图要想显示什么必须先定义相应的数据结构。 要注意元素节点例如 { type: header1, children: [ { text: hello } ] } 必须有两个属性 type 和 children 属性。还可以自定义其他属性。参考官方文档中节点数据结构这一部分。 这里我们的数据结构只有样式里面的文本没有别的信息因此定义一个children即可。
创建文件custom-types.ts写入代码
import { Text } from slateexport type TitleBlackElement {type: title-blackchildren: Text[]
}后续我们插入元素的时候就可以这样写
const myResume: TitleBlackElement {type: title-black,children: [{ text: 1、在这里插入标题 }]
}当然现在WangEditor还无法识别因为我们还没定义这个类型所对应的节点是什么样的。我们在下面定义。
2、在编辑器渲染新元素
编辑器的内部渲染使用了 虚拟DOM 技术。我们主要会用到它的 h 函数来创建虚拟DOM对象。 这里我们的节点为一个div包着里面的文字。当然div上还夹带着样式。 创建一个文件render-elem.ts
import { h, VNode } from snabbdom
import { IDomEditor, SlateElement } from wangeditor/editor
import { IRenderElemConf } from wangeditor/core;function renderTitleBlack(elemNode: SlateElement,children: VNode[] | null,editor: IDomEditor
): VNode {const vnode h(div, {style: { padding: 10px, margin: 5px 0px 0px, // whiteSpace: normal, maxWidth: 100%, lineHeight: 25px, fontSize: 16px, fontFamily: 微软雅黑, borderTopLeftRadius: 4px, borderTopRightRadius: 4px, borderBottomRightRadius: 4px,borderBottomLeftRadius: 4px, color: rgb(255, 255, 255), borderLeftColor: rgb(0, 187, 236), borderLeftWidth: 10px, borderLeftStyle: solid, boxShadow: rgb(153, 153, 153) 2px 2px 4px, textShadow: rgb(34, 95, 135) 0px 1px 0px, wordWrap: break-word, boxSizing: border-box, backgroundColor: rgb(55, 57, 57)},}, children)return vnode;
}export const renderElemConf:IRenderElemConf {type: title-black,renderElem: renderTitleBlack,
}定义了这个之后执行editor.insertNode(myResume)即可插入自定义节点当然得先注册可参考官网本文在都定义完后一次性注册
3、解析新元素 HTML 到编辑器
只定义上面的部分此时执行 editor.getHtml() 获取的HTML是无法获取到对应的html的这个也需要自己定义。 创建文件elemToHtml.ts定义元素对应的html. 注意这里在你自定义元素的html的基础上增加一个名为data-w-e-type的属性值为你这个节点的类型这里是title-black.
import { Element } from slatefunction titleBlackToHtml(elem: Element, childrenHtml: string): string {return div data-w-e-typetitle-black stylepadding: 10px; margin: 5px 0px 0px; max-width: 100%; line-height: 25px; font-size: 16px; font-family: 微软雅黑; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; color: rgb(255, 255, 255); border-left-color: rgb(0, 187, 236); border-left-width: 10px; border-left-style: solid; box-shadow: rgb(153, 153, 153) 2px 2px 4px; text-shadow: rgb(34, 95, 135) 0px 1px 0px; word-wrap: break-word; box-sizing: border-box; background-color: rgb(55, 57, 57);${childrenHtml}/div
}export const elemToHtmlConf {type: title-black,elemToHtml: titleBlackToHtml
}此时通过 const html editor.getHtml() 可以得到正确的 HTML。但再去设置HTML editor.setHtml(html)却无效。而我们通常在存储富文本数据时存的是对应的html。想要让wangEditor能够直接识别html需要你自定义解析 HTML 的逻辑。
4、解析新元素 HTML 到编辑器
创建parseElemHtml.ts这里的编写思路就是从html标签中获取里面的内容然后手动创建您自定义元素的数据结构格式同第一节一致。这里指定type为text-graychildren是一个text数组填入这个div样式里面的文字内容。
import { IDomEditor, SlateDescendant, SlateElement } from wangeditor/editorfunction parseTitleBlackHtml(domElem: Element, children: SlateDescendant[], editor: IDomEditor): SlateElement { const text domElem.firstChild?.textContentconst myResume {type: title-black,children: [{text: text || }]}return myResume
}export const parseHtmlConf {selector: div[data-w-e-typetitle-black], // data-w-e-type 属性留给自定义元素保证扩展性parseElemHtml: parseTitleBlackHtml,
}5、注册自定义元素到wangEditor
将custom-types、render-elem、elemToHtml、parseElemHtml注册到wangEditor中。 这里我们把这四个文件放在title-black文件夹中并创建一个入口文件index.ts
import { IModuleConf } from wangeditor/core
import { renderElemConf } from ./render-elem
import { elemToHtmlConf } from ./elem-to-html
import { parseHtmlConf } from ./parse-elem-htmlconst TitleBlack: PartialIModuleConf {renderElems: [renderElemConf],elemsToHtml: [elemToHtmlConf],parseElemsHtml: [parseHtmlConf]
}export default TitleBlack接着使用registerModule注册到wangEditor中。
import { Boot } from wangeditor/editor
import TitleBlack from ./editor-module/title-black; // 这个路径根据你的配置来Boot.registerModule(TitleBlack)这里插件就注册好啦
使用
这里我们要往编辑器中插入新的样式时可以先定义节点数据结构再使用editor.insertNode插入。可以自己写一个按钮、触发回调的方式执行以下代码 const node {type: title-black,children: [{text: 1、在这里插入标题}]}editor?.insertNode(node);但是使用时还出现一个问题在插入样式后想换行无法回到正常编辑的模式会一直待着样式换行。如图 要解决这个问题需要自定义一个插件拦截回车事件。
三、定义插件解决换行问题
要解决上面这个问题就需要拦截回车事件在用户输入回车时手动处理这一情况这里我参考的是wangEditor中引用功能blockquote的源码。 这里需要重写insertBreak首先判断用户输入换行的位置如果是在title-black我们自定义的元素中换行的则需要自定义一些动作 这里首先判断光标是否位于元素的最后如果是第一次输入换行时让其在元素中正常换行。如果是第二次输入换行连续两次判定规则为前一个字符扔为换行符此时我们将上一个换行符删去然后插入一个p/p标签即回到正常样式。 在title-black文件夹中创建ts文件insertBreakPlugin.ts写入插件代码
import { Editor, Transforms, Node, Point } from slate
import { IDomEditor, DomEditor } from wangeditor/editorfunction insertBreakPluginT extends IDomEditor(editor: T): T {const { insertBreak, insertText } editorconst newEditor editor// 重写 insertBreak - 换行时插入 pnewEditor.insertBreak () {const { selection } newEditorif (selection null) return insertBreak()const [nodeEntry] Editor.nodes(editor, {match: n {return DomEditor.checkNodeType(n, title-black)},universal: true,})if (!nodeEntry) return insertBreak()const elem nodeEntry[0]const elemPath DomEditor.findPath(editor, elem)const elemEndLocation Editor.end(editor, elemPath)if (Point.equals(elemEndLocation, selection.focus)) {// 光标位于节点最后const str Node.string(elem)if (str str.slice(-1) \n) {// 节点的文本最后一个是 \neditor.deleteBackward(character) // 删除最后一个 \n// 则插入一个 paragraphconst p { type: paragraph, children: [{ text: }] }Transforms.insertNodes(newEditor, p, { mode: highest })return}}// 正常情况插入换行符insertText(\n)}// 返回 editor 重要return newEditor
}export default insertBreakPlugin;在index.ts中引入
import { IModuleConf } from wangeditor/core
import { renderElemConf } from ./render-elem
import { elemToHtmlConf } from ./elem-to-html
import { parseHtmlConf } from ./parse-elem-html
import insertBreakPlugin from ./insertBreakPluginconst TitleBlack: PartialIModuleConf {renderElems: [renderElemConf],elemsToHtml: [elemToHtmlConf],parseElemsHtml: [parseHtmlConf],editorPlugin: insertBreakPlugin
}export default TitleBlack将这个模块注册到wangEditor中。 附上代码链接 https://github.com/tguzxz/wangEditor-DIY/tree/main