TinyMce是一款相对好用的富文本编辑插件。
富文本编辑器中集成数学公式是一个比较被经常提到的需求。
经过搜索得知TinyMce中集成数学公式的方案目前有三个:
1.mathType插件
2.kityformula-editor插件
3.mathjax插件
首先mathType插件个人认为是比较好用的,但致命的一点也是这个插件是付费使用的,经过一番搜索并没有找到破解方案或者续费方案。不然也不会有此文章。这三个插件都可以独立使用,至于使用方式有其他的博主介绍,本文不做过多讲解。本文主要内容为当你使用mathType插件过期后如何兼容老数据以及继续编辑数学公式的平替方案以及免费,希望存储latex格式的公式并且需要图形界面的实现思路。
分析过程:
MathType插件生成的数学公式转换为源码后为MathML格式 如下:
kityformula-editor插件: 提供图形界面可以编辑公式,但是存储后的格式为图片或base64编码的图片,保存后无法与文本形成格式上的统一,布局较乱。
mathjax插件: 可以生成Latex格式的公式存储给后台 避免了布局上的混乱,并且可编辑性强格式统一。缺点是没有图形界面来编辑公式,需要会使用Latex语法才能键入公式,对使用人员要求比较高。如下图:
所以,有什么方案可以既免费,又拥有图形编辑界面,又可以存储为通用的数学公式格式呢?
笔者的思路是结合kityformula-editor 与 tinymce-mathjax 插件。修改两插件源码,利用kityformula-editor的图形界面输入,然后调用tinymce-mathjax插件写入标准的Latex格式。这样就可以完美实现数学公式的需求了。
如果初次引入数学公式,那么至此就可以直接使用了。
但笔者曾经使用的是MathType,由于试用期到期不得不寻找平替方案,故还需要兼容数据库中已存在的MathML格式的公式。这里选择mathml2latex这个库进行latex与MathML转换,解决了这个问题。
至此,需求以及实现思路解释完成,开始Coding。。。。。
第一步:首先安装以上提到的所有插件:(笔者的项目为Element-ui模版项目,使用相同模版的话可以直接复制)
kityformula-editor插件: http://tinymce.ax-z.cn/more-plugins/kityformula-editor.php
mathJax-timyMce插件: https://github.com/dimakorotkov/tinymce-mathjax/archive/master.zip
mathml2latex插件: https://github.com/androettop/mathml2latex (不需要兼容mathml可不下载)
下载好插件后,将下载的内容放在src/public文件夹下 然后运行npm install mathjax 从node_modules中复制出mathjax文件夹,放在public下。
找到tinyMce配置,按照如下方式集成插件至TinyMce:
plugins:['kityformula-editor','mathjax',.............],
toolbar:['kityformula-editor | mathjax...........'],
mathjax: {lib:'/mathjax/es5/tex-mml-chtml.js',}
external_plugins: {'kityformula-editor':`/kityformula-editor/plugin.min.js`,'mathjax':'/tinymce-mathjax/plugin.js'},
至此,插件已安装完成,你的工具栏应该已经有mathjax以及kityformula-editor两个插件工具并可以独立使用。
第二步:融合现有的公式插件,让kityformula-editor在前台编辑公式,mathjax转入后台被调用写入公式。
打开public/kityformula-editor/plugin.js 修改var baseURL = '/kityformula-editor/kityFormula.html';如下图
打开public/kityformula-editor/kityFormula.html文件 修改第72行为 content: `<span class="math-tex">\\(${latex}\\)</span>`如下图所示,目的为使插件输出Latex格式的公式而非图片。
接下来找到public/tinymce-mathjax/plugin.js文件 开始修改tinymce-mathjax插件,重写点击事件,使其能在点击latex格式公式的时候拉起kityformula-editor实现编辑。
找到第127行, editor.on("click", function (e) {....方法,修改如下
editor.on("click", function (e) {
var sel = editor.selection.getContent();
var path = /\<span(.*?)class="math-tex"(.*?)data-latex="(.*?)">/g;
var path2 = /data-latex="(.*?)"/g;
if (sel.search(path) == 0) {
sel.replace(path2, function ($0, $1) {
const pa = $1.replace('\\\(', '')
const pa2 = pa.replace('\\\)', '')
var param = encodeURIComponent(pa2);
// param = param.replace('\\(','')
openDialog(param);
return $0;
});
}
;
// let closest = e.target.closest('.' + mathjaxClassName);
// if (closest) {
// openMathjaxEditor(closest);
// }
});
紧接着这个方法,再回到public/kityformula-editor/kityFormula.html这个文件,找到打开公式编辑器的openDialog方法并复制过来粘贴到public/tinymce-mathjax/plugin.js文件内,使得上述方法可正常调用。
var openDialog = function (param) {
var baseURL = '/kityformula-editor/kityFormula.html';
return editor.windowManager.openUrl({
title: '插入公式',
size: 'large',
width: 785,
height: 475,
url: param ? baseURL + "?c=" + param : baseURL,
buttons: [
{
type: 'cancel',
text: 'Close'
},
{
type: 'custom',
text: 'Save',
name: 'save',
primary: true
},
],
onAction: function (api, details) {
switch (details.name) {
case 'save':
api.sendMessage("save");
break;
default:
break;
}
;
}
});
};
至此,应该已经实现了两个插件的互相调用,可以用图形界面写入/编辑latex公式正常使用了。如果你没有笔者一样需要兼容MathML格式的需求,可以无需看下面的内容了。如果有,请往下看。
第三步:目前虽然兼容了latex,但是如果服务端返回了MathML的内容,依旧是不能解析成正确的公式样式进行渲染的。假如你的数据量较少,那么可以直接申请后端的同学帮忙批量转换,如果暂时做不到,可以按照我的方式读取时转换为latex,编辑过后再保存就变成了latex格式。这么做以后你的数据库中数学公式将会存在两种格式,请权衡利弊后使用。
找到public/index.html文件 加入如下脚本引入插件。
<script src="<%= BASE_URL %>mathml2latex/mathml2latex.js"></script>
找到你的代码,对tinyMce绑定的数据进行监听,输入编辑器前用如下方法转换。
convertMathmlToMathJax(value) {
let texValue = value +''
const req =/<math(([\s\S])*?)<\/math>/gi
if (!req.test(texValue)) {
return value
}
const array = texValue.match(req)
array.forEach(item => {
texValue = texValue.replace(item,`<span class="math-tex">\\( ${window.MathML2LaTeX.convert(item)} \\)</span>`)
})
return texValue
},
至此就可以平替收费的mathType插件了。但终归不如收费插件支持范围广。如果你有更好的想法 欢迎与我讨论。