解决highlightjs中纯文本被解析成HTML无法展示的问题,记一次工作中bug修复的思考

摘要:
也就是说,高亮渲染的代码数据实际上取决于textarea的输入。我们只需要对输入进行相应的数据转换。打开chrome,输入highlightjshtml,单击搜索,第一个问题就是我们想要的答案。Highlightjswithhtmlcode StackOverflow,我们肯定不是第一个遇到这个问题的人,网友们永远不会让你失望。是的,在前面的高光原理分析中,高光最初实时获取文本区域数据,并自行处理以获得颜色代码的副本。这份副本仅供我们查看。当我们删除新代码时,我们实际上对textarea值进行操作。
解决highlightjs中纯文本被解析成HTML无法展示的问题,记一次工作中bug修复的思考第1张
壹 ❀ 引

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

解决highlightjs中纯文本被解析成HTML无法展示的问题,记一次工作中bug修复的思考第2张
解决highlightjs中纯文本被解析成HTML无法展示的问题,记一次工作中bug修复的思考第3张

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

贰 ❀ 排查思路

前端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中纯文本被解析成HTML无法展示的问题,记一次工作中bug修复的思考第4张

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

叁 ❀ 修复思路

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

解决highlightjs中纯文本被解析成HTML无法展示的问题,记一次工作中bug修复的思考第5张

上图中表示有两个视图层,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的值按照当前选择的语言再生产一份对应的彩色代码而已。

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

解决highlightjs中纯文本被解析成HTML无法展示的问题,记一次工作中bug修复的思考第6张

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

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

免责声明:文章转载自《解决highlightjs中纯文本被解析成HTML无法展示的问题,记一次工作中bug修复的思考》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇复杂对象类型的WebService高级部分cookie插件——cookie下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

django学习-29.表单提交方式之一:post请求(注册/登录/改密)

目录结构 1.写这篇博客的目的 2.完整操作流程 2.1.第一步:新增相关html页面 2.1.1.新增一个【index_html.html】 2.1.2.新增一个【login_html.html】 2.1.3.新增一个【register_html.html】 2.1.4.新增一个【register_success_html.html】 2.1.5.新增一...

HTML自定义标签与标签自定义属性

大部分浏览器支持自定义HTML标签和为标准标签自定义属性,而且很多浏览器对这两种自定义行为的支持都很直接了当。 自定义HTML标签 在firefox、chrome这种现代浏览器里,自定义标签很简单,就像标准的标签那样写就可以了,而且CSS和JavaScript存取自定义标签和标准标签并无二致。 1 2 3 4 5 6 7 8 9 <foo...

Javascript 刷新框架及页面的方法总集

项目中会用到很多关于框架页面刷新的方法。先来看一个简单的例子:下面以三个页面分别命名为frame.html、top.html、bottom.html为例来具体说明如何做。frame.html 由上(top.html)下(bottom.html)两个页面组成,代码如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4...

jQuery根据ID、CLASS、等获取对象

Jquery是继prototype之后又一个优秀的Javascrīpt框架。它是轻量级的js库(压缩后只有21k) , 它兼容CSS3,还兼容各种浏览器 (IE 6.0+, FF 1.5+, Safari 2.0+, Opera 9.0+)。 jQuery使用户能更方便地处理HTML documents、events、实现动画效果,并且方便地为网站提供AJ...

angular.js

AngularJS是一款为了克服HTML在构建应用上的不足而设计的优秀的前端JS框架。AngularJS有着诸多特性,最为核心的是:MVC、模块化、自动化双向数据绑定、语义化标签、依赖注入等等。 前段框架:前后台分离(pc端,移动端都可以使用) vue:中小型项目,较灵活 angular:中大型项目,安全性较高 react:原生开发,混合开发,中小型  1...

带你由浅入深探索webpack4(一)

 相信你或多或少也听说过webpack、gulp等这些前端构建工具。近年来webpack越来越火,可以说成为了前端开发者必备的工具。如果你有接触过vue或者react项目,我想你应该对它有所了解。 这几天我重新整理了一下webpack中知识点,把一些常用到的总结出来,希望能帮助到大家以及加深自己对webpack的理解。 (由于我在写这篇文章的时候webpa...