zoukankan      html  css  js  c++  java
  • 解决highlightjs中纯文本被解析成HTML无法展示的问题,记一次工作中bug修复的思考

    壹 ❀ 引

    在本周迭代bug修复工作中,遇到了两个比较头疼的bug(同一个客户所提),bug问题描述也很奇怪,客户表示产品的富文本编辑器里的代码块功能,在纯文本语言模式下贴特定代码进去有的看不见,有的能看见但无法正常编辑,效果如下:

    虽然知道了问题的表象,但还是有点无从下手,毕竟这块的功能不是我做的,实现原理以及功能逻辑都不了解,当然问题到最后肯定还是解决了,不然就不会有这篇文章了,本文也只是记录从零理解问题以及解决问题的思路。

    贰 ❀ 排查思路

    前端bug排查其实无非几个出发点。接口层,bug数据来源接口是否正常,如果不确证直接甩锅后端同事,此bug直接物理层面被解决。数据层,比如我们公司用的是的react,所以数据检验可以通过chrome插件查看component数据以及redux数据是否符合预期。逻辑层,通过读代码确认逻辑是否符合功能设计,读同事的旧代码往往是一件让人暴躁的事情,我也如此,实在没办法也只能硬着头皮读。

    但此问题的表现我的第一感觉是出在渲染层面,所以处于验证,我直接点开了控制台的Elements,也算走运,一看就发现了问题,原来拷贝到代码块的代码并不是未渲染,而是代码中包含html的标签直接被解析成了页面HTML中的一部分,这才导致了不展示以及无法编辑的问题。

    客户拷贝的代码:

    /// <summary>
    /// show loading
    /// </summary>
    public void ShowLoading(){        Controller.instance.StartCoroutine(View.instance.ShowWordWarn(Model.instance.lanDic[55021], 0.2f));
    }
    

    控制台展示的结构,summary被解析成了标签

    比较幸运,原本以为是两个问题,现在只需要解决一个问题了。

    叁 ❀ 修复思路

    知道了问题所在,接下来需要了解的是富文本编辑器中的代码块的功能是如何实现的,简单看了下代码,发现实现上依赖了highlightjs,简单了解了下原理,大概如下:

    上图中表示有两个视图层,highlight的code preview也就是三方库渲染后带颜色的代码展示框,而下面还有一个textarer也就是真正记录用户输入以及编辑结果的的编辑框。code preview悬浮在textarea上,再通过样式定位让两个视图层的代码对齐,这才有了我们在编辑彩色代码的效果。

    也就是说,highlight渲染的代码数据其实依赖于textarea的输入,我们只要在输入做对应的数据转化即可。打开chrome,输入highlightjs html,点击搜索,然后第一条问题就是我们想要的答案了。highlightjs with html code - Stack Overflow,这种问题咱们肯定不是第一个遇到的,网友绝对不会让你失望。

    解决方案其实也很简单,比如以下代码我们不希望被解析html标签,要做的只是将<>转义为&lt;&gt;即可。

    <p>听风是风</p>
    // 转为
    &lt;p&gt;听风是风&lt;/p&gt;
    

    代码块是支持语言切换的,我们前面说了只有纯文本只有这个问题,所以只有当前语言类型是纯文本,就需要做标签转义,我大概定义了这样的一个方法:

    transformHtmlToText = (code, lang) => {
      return lang === 'PlainText' ? code.replace(/</g, '&lt;').replace(/>/g, '&gt;') : code;
    }
    

    如果只是作为展示,这样貌似也没什么问题了,取到textarea的值转义后传给highlightjs作为展示。但比较尴尬的是,代码块是支持用户操作的,用户可能会进行代码编辑或者语言切换,以语言切换为例,假设我们一开始的语言是纯文本,且做了转义:

    // 此时语言是纯文本
    &lt;p&gt;听风是风&lt;/p&gt;;
    

    现在用户进行了编辑,删除了部分代码,同时把语言切成了java,那么问题来了,用户编辑删除时操作的是<p>听风是风</p>还是&lt;p&gt;听风是风&lt;/p&gt,切换语言后我是不是应该将&lt;p&gt;听风是风&lt;/p&gt中的&lt;再反向转义成<呢?

    首先第一个问题我们已经很清楚了,在前面的原理分析中我们已经得知了操作的其实是textarea的值,因此删除的其实就是textarea的内容,highlight只是对textarea的值在做实时渲染而已。

    第二个问题是我们常常会遇到的场景,一个值A因为某个原因被加工成了A+,在经历了一系列操作后已经变得面目全非,用户又在某种场景下又需要切回原有的数据A,那么要在A+的基础上做还原操作吗?很明显是不要的。

    我在18年就遇到了类似的问题,用户输入时需要对文本中相同的文字进行标红匹配,我在利用正则匹配做了一系列的替换后达到了该效果,现在用户把输入的内容删除了,我当时的第一反应就是对已标红的文字再做反向还原,但我觉得这太复杂了,数据也极难维护。

    当时我同学就说,为什么不把数据当一次性的呢,加工的时候就是一份副本,操作完了自然就遗弃了,你不是本来就有最初的数据吗,为何要还原呢?

    没错,在前面的highlight原理分析中,highlight本来就是实时拿textarea的数据,自己进行加工得到了一份彩色代码的副本,这份副本就是纯给我们看的,我们删除新增代码时,操作的其实是textarea的值。而我们切换代码块语言时textarea的值其实是没变化的,变化的是highlight需要再拿一次textarea的值按照当前选择的语言再生产一份对应的彩色代码而已。

    我想表达的大概是下图这个意思,这是在编程中其实是很重要的一点,保证数据的唯一性,这会让你的数据变得更可控,在代码书写时也会变得相应的简单。

    我在修复此bug的过程中,通过阅读代码发现原有逻辑不管是编辑代码还是切换语言,在对应的监听方法中都对state的textarea的值,代码语言类型,以及highlight所需要的值加工都做了实时更新,但我觉得后者值的实时获取分散在这么多的方法中没必要的,因为前面说了textarer的值是才是理论上唯一数据源,在state中制好它的更新即可,考虑了一下,我将这些方法中的highlight值操作的代码都删除了,并统一到了render中根据textarer与语言类型进行统一加工,bug改了代码量也相应的减少了一部分,神清气爽。

    那么这大概就是最近一次修bug的经历,可能是太想写博客了,所以写了点东西,那么本文结束。

  • 相关阅读:
    ZeptoLab Code Rush 2015
    UVa 10048 Audiophobia【Floyd】
    POJ 1847 Tram【Floyd】
    UVa 247 Calling Circles【传递闭包】
    UVa 1395 Slim Span【最小生成树】
    HDU 4006 The kth great number【优先队列】
    UVa 674 Coin Change【记忆化搜索】
    UVa 10285 Longest Run on a Snowboard【记忆化搜索】
    【NOIP2016提高A组模拟9.28】求导
    【NOIP2012模拟10.9】电费结算
  • 原文地址:https://www.cnblogs.com/echolun/p/14540880.html
Copyright © 2011-2022 走看看