修改UEditor默认高亮代码插件为 highlight.js

UEditor 是由百度「FEX前端研发团队」开发的所见即所得富文本 web 编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码。这里贴上该项目在 Github 上的链接地址: https://github.com/fex-team/ueditor

虽然说 UEditor 是 6 年前的老项目了,但是放在今天来看在 PC 端能比 UEditor 更加优秀的编辑器确实没有几个。广大前端程序员朋友对该编辑器也是喜爱有加,唯一的不足就是官方团队现在对该项目基本上处于停止维护的状态。其中一些插件及功能显得有点过时。现在,我们就来将其默认的代码高亮插件 SyntaxHighlighter 修改成时下非常流行并且用户众多的 highlight.js。

首先,我们需要下载 UEditor 的项目源码至本地计算机:

您可以手动下载或使用 git 命令克隆项目至本地,本文示例代码基于 UEditor dev-1.5.0 版本进行修改

git clone https://github.com/fex-team/ueditor.git  // 克隆项目
npm install  // 安装项目依赖
grunt default  // 按照默认设置进行打包,打包完成后最终代码在 /dist/ 目录下

下面是 UEditor 项目的源码包目录结构:

├── /_example/                              ueditor 的使用演示及示例
├── /_parse/                                ueditor.parse.js 的源码
├── /_src/                                  ueditor.all.js 的源码
├── /_test/                                 测试目录
├── /dialogs/                               弹出对话框对应的资源和JS文件
├── /lang/                                  编辑器国际化语言包
├── /themes/                                主题样式和相关图片文件
├── /third-party/                           第三方插件(包括代码高亮,源码编辑等组件)
├── /.editorconfig  
├── /.gitignore 
├── /Gruntfile.js   
├── /ISSUE_TEMPLATE.md  
├── /LICENSE    
├── /README.md  
├── /changelog.md   
├── /package.json   
├── /ueditor.config.js  
├── /ueditor.parse.js


下载 highlight.js 代码高亮插件

插件下载地址:https://highlightjs.org/
下载完成后,将 highlight.js 放置在 UEditor 源码目录的 /third-party/ 目录下。

两款插件的结构区别

UEditor 默认代码高亮插件结构如下:

<pre class="brush:javascript;toolbar:false;">
    // 这里是 javascript 代码
</pre>

highlight.js 高亮插件要求的结构如下:

<pre>
    <code class="javascript">
    // 这里是 javascript 代码
    </code>
</pre>


下面我们来正式开始修改:

第一步,打开 /_src/plugins/insertcode.js 文件

1、将第 16 行 me.setOpt("insertcode", { ... }) 这里修改为 highlight.js 高亮插件支持的语言,设置示例:

me.setOpt("insertcode", {
    Apache: "Apache",
    Bash: "Bash",
    CSharp: "C#",
    Cpp: "C++",
    CSS: "CSS",
    HTML: "HTML, XML",
    HTTP: "HTTP",
    Ini: "Ini, TOML",
    JSON: "JSON",
    Java: "Java",
    JavaScript: "JavaScript",
    Makefile: "Makefile",
    Markdown: "Markdown",
    Nginx: "Nginx",
    "Objective-C": "Objective-C",
    PHP: "PHP",
    Perl: "Perl",
    Python: "Python",
    Ruby: "Ruby",
    SQL: "SQL",
    Shell: "Shell",
    Session: "Session"
});



2、源码第 71 行,将 pre 改为 code (注意:是源码源文件第 71 行,请复制一份对照源码文件进行修改)

pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);

改为

pre = domUtils.findParentByTagName(rng.startContainer, "code", true);



3、源码第 73 行的代码进行修改

if (pre) {
    pre.className = "brush:" + lang + ";toolbar:false;";
}

改为

if (pre) {
    pre.className = lang;
}



4、源码第 157 - 165 行进行修改

me.execCommand(
          "inserthtml",
          '<pre id="coder"class="brush:' +
            lang +
            ';toolbar:false">' +
            code +
            "</pre>",
          true
        );

改为

me.execCommand(
    "inserthtml",
    '<pre><code id="coder" class="' + lang + '">' + code + "</code></pre>",
    true
);



5、源码第 193 - 197 行进行修改

if (node.nodeName == "PRE") {
      var match = node.className.match(/brush:([^;]+)/);
          lang = match && match[1] ? match[1] : "";
          return false;
        }

改为

if (node.nodeName == "CODE") {
    lang = node.className;
    return false;
}



6、源码第 204 行进行修改

utils.each(root.getNodesByTagName("pre"), function(pre) {

改为

utils.each(root.getNodesByTagName("code"), function(pre) {



7、源码第 229 行需要做同样的修改

utils.each(root.getNodesByTagName("pre"), function(pre) {

改为

utils.each(root.getNodesByTagName("code"), function(pre) {



8、源码第 280 行

var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);

改为

var pre = domUtils.findParentByTagName(rng.startContainer, "code", true);



9、源码第 406 行

var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);

改为

var pre = domUtils.findParentByTagName(rng.startContainer, "code", true);



10、源码第 471 行

pre = domUtils.findParentByTagName(rng.startContainer, "pre", true);

改为

pre = domUtils.findParentByTagName(rng.startContainer, "code", true);



11、源码第 575 行

if (
        rng.collapsed &&
        (pre = domUtils.findParentByTagName(rng.startContainer, "pre", true)) &&
        !pre.nextSibling
      ) {

改为

if (
                rng.collapsed &&
                (pre = domUtils.findParentByTagName(rng.startContainer, "code", true)) &&
                !pre.nextSibling
            ) {



12、源码第 599 行

if (
      domUtils.isTagNode(start, "pre") &&
      rng.collapsed &&
      domUtils.isStartInblock(rng)
    ) {

改为

if (
      domUtils.isTagNode(start, "code") &&
      rng.collapsed &&
      domUtils.isStartInblock(rng)
    ) {



第二步,打开 /_src/plugins/source.js 文件

源码第 180 行

case "pre":
    node.innerText(node.innerText().replace(/&nbsp;/g, " "));

改为

case "code":
    node.innerText(node.innerText().replace(/&nbsp;/g, " "));

至此 UEditor 编辑器部分修改完成,下面是查看预览的部分。


第三步,打开 /_parse/insertcode.js 进行修改。该文件主要负责动态引入 highlight.js 的样式及脚本文件,并且执行代码高亮
此文件由于代码量非常少,所以直接贴上修改后的代码。代码中的 jsurl 与 cssurl 变量对应 UEditor 源码目录下 /third-party/ 里面 highlight.js 的路径

UE.parse.register("insertcode", function(utils) {
    var pres = this.root.getElementsByTagName("pre");
    if (pres.length) {
        var jsurl, cssurl;
        if (this.rootPath !== undefined) {
            jsurl = utils.removeLastbs(this.rootPath) + "/third-party/highlight/highlight.pack.js"; // 高亮脚本
            cssurl = utils.removeLastbs(this.rootPath) + "/third-party/highlight/styles/a11y-dark.css"; // 样式文件,这里可以修改成自己喜欢的主题样式
        } else {
            jsurl = this.highlightJsUrl;
            cssurl = this.highlightCssUrl;
        }
        utils.loadFile(document, {
            id: "syntaxhighlighter_css",
            tag: "link",
            rel: "stylesheet",
            type: "text/css",
            href: cssurl
        });
        utils.loadFile(
            document, {
                id: "syntaxhighlighter_js",
                src: jsurl,
                tag: "script",
                type: "text/javascript",
                defer: "defer"
            },
            function() {
                hljs.initHighlightingOnLoad();
            }
        );
    }
});

最后,执行以下命令进行整体打包

grunt default

打包完成后将 /dist/ 目录下的最终文件拷贝到自己的项目中进行部署即可,关于部署这里不再进行赘述,参考官方文档进行部署即可。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容