问题记录:解析 notebook 数学公式失败

工具基础

react + nextjs 项目
notebookjs 获取 notebook 的 outer html
katex 解析公式

问题描述

在线展示 .ipynb 文件的内容,在 markdown 的 cell 中出现部分数学公式未正确解析成功

如图所示
在这里插入图片描述
可以看到最后两行未被解析成数学公式

分析问题

已知 katex 在解析过程中进行了规则配置,通过引入 katex 中的
实现方式如下

import renderMathInElement from 'katex/contrib/auto-render';
 renderMathInElement(document.body, {
   // custom options
   delimiters: [
     { left: '$$', right: '$$', display: true },
     { left: '$', right: '$', display: false },
     { left: '\\(', right: '\\)', display: false },
     { left: '\\[', right: '\\]', display: true },
   ],
   throwOnError: false,
 });

可以看到这其中是缺少了 \begin{align} \end{align}这对标记的解析

解决问题

所以需要增加规则的配置
下面是一个比较完整的版本

renderMathInElement(document.body, {
        // custom options
        // • auto-render specific keys, e.g.:
        delimiters: [
          { left: '$$', right: '$$', display: true },
          { left: '$', right: '$', display: false },
          { left: '\\(', right: '\\)', display: false },
          { left: '\\[', right: '\\]', display: true },
          {
            left: '\\begin{equation}',
            right: '\\end{equation}',
            display: true,
          },
          { left: '\\begin{align}', right: '\\end{align}', display: true },
          { left: '\\begin{alignat}', right: '\\end{alignat}', display: true },
          { left: '\\begin{gather}', right: '\\end{gather}', display: true },
          { left: '\\begin{CD}', right: '\\end{CD}', display: true },
        ],
        // • rendering keys, e.g.:
        throwOnError: false,
      });

在增加了这些规则后,发现仍旧有部分数学公式未被正确解析,查看源代码
在这里插入图片描述
由于 p 元素中包含了 em 元素,导致 katex 未解析这段代码。
通过对比接口的数据发现,源数据中并未包含 em 元素,源数据 "\\begin{align}{TD}_t = r + \\gamma Q_{target}^*(s',a')\\end{align}\n"
那么 em 元素是哪儿来的呢?

原来从接口拿到数据后,调用了 notebookjs 提供的 parse 方法和 render 方法,获取到 outerHtml。然后再把这段 html 放到页面展示。
那么接下来就是修复 notebook 的解析问题

尝试解决

方法一 元素逆向替换

由于 markdown 语法转换成 html 后多出来了 em 标签,那么反过来我把这段 htmlstring 中的 em 标签手动替换回 _ 是不是就可以?
说干就干

const replaceEmTags=(htmlString)=> {
    const div = document.createElement('div');
    div.innerHTML = htmlString;

    const markdownCells = div.getElementsByClassName('nb-markdown-cell');

    for (let i = 0; i < markdownCells.length; i++) {
      const pElements = markdownCells[i].getElementsByTagName('p');
      for (let j = 0; j < pElements.length; j++) {
        const pElement = pElements[j];
        pElement.innerHTML = pElement.innerHTML.replace(/<em>/g, '_').replace(/<\/em>/g, '_');
      }
    }

    return div.innerHTML;
  }

转换后发现确实有一点作用,但同时在 markdown 中使用强调效果的文字就会消失。
且发现 这个转换会把 - 转换为 ul li 的列表,这下换成两个标签的嵌套,显然上面的替换方法是行不通的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值