zoukankan      html  css  js  c++  java
  • Latex 公式在线可视化编辑器

    寻觅

    最近的一个demo需要用到Latex公式在线编辑器,从搜索引擎一般会得到类似http://latex.codecogs.com/eqneditor/editor.php的结果,这个编辑器的问题在于使用成本高,并且界面不美观。
    codecogs

    继续探寻,发现了wiris Editor
    wiris Editor

    支持mathml和latex:
    wiris Editor

    那么就它了!

    选型

    首先,我们不会直接使用这个编辑器,只是在编辑公式的时候才使用,所以要选择合适的版本。
    wiris Editor
    以前用过CKEditor,所以就这它了!选用java版本
    我们的数据已经是latex的,在wiris 编辑器显示需要注意latex需要用两个$$包括起来
    例如:

    The history of $$sqrt(2)$$.
    

    但是CK版本的wiris对latex的支持是非可视化支持,在编辑器里输入latex还是显示为latex:
    enter description here

    将焦点移动到$$内部,再点击按钮出现wiris的公式编辑器:

    enter description here
    这种设计适合对latex熟悉的人员,可以裸写latex,同时对不熟悉的人来说,可以使用公式编辑器。但是,这样不直观啊!你让不会latex的看到的就一堆符号!

    适配

    简单试用可以发现,如果直接使用公式编辑器插入公式,是直观显示的:
    enter description here

    可以看到保存的时候,mathml是:

    <math class="wrs_chemistry" xmlns="http://www.w3.org/1998/Math/MathML">
    	<msqrt>
    		<mn>2</mn>
    	</msqrt>
    </math>
    

    那么在latex输入情况下呢:

    <math xmlns="http://www.w3.org/1998/Math/MathML">
    	<semantics>
    		<mrow>
    			<msqrt><mo>(</mo></msqrt><mn>2</mn><mo>)</mo>
    		</mrow>
    		<annotation encoding="LaTeX">sqrt(2)</annotation>
    	</semantics>
    </math>
    

    原来问题在这里,正是mathML的区别导致处理的区别。也就是说一开始就生成不带LaTeX的mathML,然后再放入编辑器。简单查看代码,可以知道先调用wrs_endParse,再wrs_initParse就可以了。

    CKEDITOR.on("instanceReady", function(event)
    	{
    		CKEDITOR.instances.example.focus();
    		var mathxml = wrs_endParse("已知向量$$\vec{a}=(\sqrt{3},2)$$,$$\vec{b}=(0,-2)$$,向量$$\vec{c}=(k,\sqrt{2})$$.$$\vec{a}-1\vec{b}$$与$$\vec{d}$$共线,$$k=$$__.");
    		CKEDITOR.instances.example.setData(wrs_initParse(mathxml));
    		// 等待完成
    		window.setTimeout(updateFunction,0);
    	});
    

    Latex

    直观显示没问题了,但是mathml如何再转换成Latex呢?core.js里的wrs_parseMathmlToLatex函数是直接从mathml里将。。。里的内容提取出来:

    function wrs_parseMathmlToLatex(content, characters){
        ....
        var openTarget = characters.tagOpener + 'annotation encoding=' + characters.doubleQuote + 'LaTeX' + characters.doubleQuote + characters.tagCloser;
     
            mathml = content.substring(start, end);
    
            startAnnotation = mathml.indexOf(openTarget);
    		// 包含 encoding=latex,保留latex
            if (startAnnotation != -1){
                startAnnotation += openTarget.length;
                closeAnnotation = mathml.indexOf(closeTarget);
                var latex = mathml.substring(startAnnotation, closeAnnotation);
                if (characters == _wrs_safeXmlCharacters) {
                    latex = wrs_mathmlDecode(latex);
                }
                output += '$$' + latex + '$$';
                // Populate latex into cache.
                wrs_populateLatexCache(latex, mathml);
            }else{
                output += mathml;
            }
       ......
    }
    

    但是现在的mathml不包含这个信息,如何处理?查看官方文档,发现有一个mathml2latex的服务,查看官方给的java demo里servlet并不包含这个服务,但是jar包里存在代码,于是自己封装一个servlet即可:

    public class ServiceServlet extends com.wiris.plugin.dispatchers.MainServlet {
    
        @Override
        public void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
                throws ServletException, IOException {
            PluginBuilder pb = newPluginBuilder(request);
            String origin = request.getHeader("origin");
            HttpResponse res = new HttpResponse(response);
            pb.addCorsHeaders(res, origin);
            String pathInfo = request.getServletPath();
            if (pathInfo.equals("/mathml2latex")) {
                response.setContentType("text/plain; charset=utf-8");
                ParamsProvider provider = pb.getCustomParamsProvider();
                String mml = provider.getParameter("mml", (String)null);
                String r = pb.newTextService().mathml2latex(mml);
                PrintWriter out = response.getWriter();
                out.print(r);
                out.close();
            }
    

    js里,调用这个服务:

    var _wrs_mathmlCache = {};
    function wrs_getLatexFromMathML(mml) {
        if (_wrs_mathmlCache.hasOwnProperty(mml)) {
            return _wrs_mathmlCache[mml];
        }
        var data = {
            'service': 'mathml2latex',
            'mml': mml
        };
    
        var latex = wrs_getContent(_wrs_conf_servicePath, data);
        // Populate LatexCache.
        if (!_wrs_mathmlCache.hasOwnProperty(mml)) {
            _wrs_mathmlCache[mml] = latex;
        }
        return latex.split("
    ").join('').split("
    ").join(' ');
    }
    

    wrs_getLatexFromMathML只能将一个mathml转换为latex,对于编辑器里的内容来说,需要将mathML抽取出来逐一转换:

    function wrs_parseRawMathmlToLatex(content, characters){
        var output = '';
        var mathTagBegin = characters.tagOpener + 'math';
        var mathTagEnd = characters.tagOpener + '/math' + characters.tagCloser;
        var start = content.indexOf(mathTagBegin);
        var end = 0;
        var mathml, startAnnotation, closeAnnotation;
    
        while (start != -1) {
            output += content.substring(end, start);
            end = content.indexOf(mathTagEnd, start);
    
            if (end == -1) {
                end = content.length - 1;
            }
            else {
                end += mathTagEnd.length;
            }
    
            mathml = content.substring(start, end);
    
            output += wrs_getLatexFromMathML(mathml);
    
            start = content.indexOf(mathTagBegin, end);
        }
    
        output += content.substring(end, content.length);
        return output;
    }
    function wrs_getLatex(code) {
        return wrs_parseRawMathmlToLatex(code, _wrs_xmlCharacters);
    }
    

    末了,为了方便获取,可以将latex放到_current_latex变量里:

    	// 获取数据
    	editor.on('getData', function (e) {
    		e.data.dataValue = wrs_endParse(e.data.dataValue || "");
    		_current_latex = wrs_getLatex(e.data.dataValue || "");
    	});
    
    

    再简单修改下网页,显示latex:
    enter description here

    收官!

  • 相关阅读:
    vue使用watch 观察路由变化,重新获取内容
    Intellij IDEA 最新旗舰版注册激活破解(2018亲测,可用)
    前端开发浏览器兼容问题
    基于Docker搭建MySQL主从复制
    js获取计算后的样式表
    js对象取值的两种方式
    js中的style与jQuery中的css
    js页面加载函数
    代码中jndi数据源的支持
    Oracle中的sid与servicename
  • 原文地址:https://www.cnblogs.com/xiaoqi/p/latex-editor.html
Copyright © 2011-2022 走看看