CKEditor整合SyntaxHighlighter实现代码高亮显示

1,版本说明

CKEditor:ckeditor_4.0.1_standard.zip
SyntaxHighlighter:syntaxhighlighter_3.0.83.zip

2,解压syntaxhighlighter_3.0.83.zip,将得到的目录syntaxhighlighter_3.0.83复制到站点目录下,我的是放在/plugins目录下(可以是其它目录,或者根目录),结果得到目录结构/plugins/syntaxhighlighter_3.0.83。

3,在CKEditor中配置插件(安装方法在《CKEditor安装》有介绍,这里就不介绍了)。在ckeditor/plugins目录下创建一个目录syntaxhighlighter,此目录名即为插件名,这点要注意。在syntaxhighlighter目录下创建icons、dialogs两个目录和plugin.js一个文件。icons目录用于存放插件在编辑器工具栏上相应按钮的图标,dialogs用于存放该插件对话框相关类,plugin.js是严格要求这样命名的。因此在CKEditor中新增的目录结构如下:

  • ckeditor/

    • plugins/

      • syntaxhighlighter/

        • icons/

          • syntaxhighlighter.png
        • dialogs/
          • syntaxhighlighter.js
        • plugin.js

4,编辑plugin.js文件,内容如下:

// mo_yq5 在编辑器中定义一个插件,注意,插件名称与插件目录名要保持一致
CKEDITOR.plugins.add( 'syntaxhighlighter', {
// mo_yq5 初始化插件
init: function( editor ) {
//mo_yq5 引入对话框的定义,所引入的文件的内容是对话框的具体逻辑定义
CKEDITOR.dialog.add( 'shDialog', this.path + 'dialogs/syntaxhighlighter.js' );
//mo_yq5 在编辑器中追加一条指令
editor.addCommand( 'shDialog', new CKEDITOR.dialogCommand( 'shDialog' ) );
//mo_yq5 在编辑器中追加一个工具栏按钮
editor.ui.addButton( 'shButton', {
//mo_yq5 鼠标移到按钮上时的提示文本
label: '插入代码',
//mo_yq5 点击按钮时要执行的指令,即上面添加的指令
command: 'shDialog',
//mo_yq5 在编辑器工具栏中嵌入按钮的方式
toolbar: 'insert',
//mo_yq5 工具栏上按钮的图标
icon: this.path + 'icons/syntaxhighlighter.png'
}); }
});

5,编辑syntaxhighlighter.js文件,定义对话框的实现逻辑,代码如下:

//mo_yq5 定义一个对话框。
CKEDITOR.dialog.add( 'shDialog', function ( editor ) {
return {
//mo_yq5 对话框标题。
title: '插入代码',
//mo_yq5 对话框最小宽度。
minWidth: 400,
//mo_yq5 对话框最小高度。
minHeight: 200,
//mo_yq5 对话框内容,一个元素对应一个选项卡。
contents: [
{
//mo_yq5 选项卡标识id。
id: 'tab_hightlighterCode',
//mo_yq5 选项卡标题。
label: '代码内容',
//mo_yq5 选项卡内容,一个元素对应一个表单项。
elements: [
{
//mo_yq5 表单类型。
type: 'select',
//mo_yq5 表单名。
label: '语言:',
//mo_yq5 表单标识id。
id: 'lang',
//mo_yq5 是否为必填项。
required: true,
//mo_yq5 表单默认值。
'default': 'java',
items: [['ActionScript3', 'as3'], ['Bash/shell', 'bash'], ['ColdFusion', 'cf'], ['C#', 'csharp'], ['C++', 'cpp'], ['CSS', 'css'], ['Delphi', 'delphi'], ['Diff', 'diff'], ['Groovy', 'groovy'], ['JavaScript', 'js'], ['Java', 'java'], ['JavaFX', 'jfx'], ['Perl', 'perl'], ['PHP', 'php'], ['Plain Text', 'plain'], ['PowerShell', 'ps'], ['Python', 'py'], ['Ruby', 'rails'], ['Scala', 'scala'], ['SQL', 'sql'], ['Visual Basic', 'vb'], ['XML', 'xml']]
},
{
type: 'textarea',
style: 'width:418px;height:250px',
label: '代码:',
required: true,
id: 'code',
rows: 13,
'default': ''
}
]
}
],
//mo_yq5 定义提交事件。
onOk: function(){
//mo_yq5 从下拉列表获取到的语言类型。
var lang = this.getValueOf('tab_hightlighterCode', 'lang');
//mo_yq5 将要被渲染成高亮显示的内容(代码)。
var code = this.getValueOf('tab_hightlighterCode', 'code');
//mo_yq5 在当前页面上创建的一个用于存放代码的容器,因为渲染器SyntaxHighlighter是取页面内容来渲染的。该容器不显示。
if($("#brushContainer").length==0){
$("body").append('<div id="brushContainer" style="display:none;"></div>');
}
//mo_yq5 主要目的是将‘<’这样的标签转换成实体。
code = CKEDITOR.tools.htmlEncode(code);
//mo_yq5 将要渲染的代码放入容器。
$("#brushContainer").html('<pre class="brush:'+ lang +';">'+code+'</pre>');
//mo_yq5 将渲染各种语言的类准备好 。
SyntaxHighlighter.autoloader.apply(null,shBrushArray);
//mo_yq5 开始渲染。
SyntaxHighlighter.all();
//mo_yqr@163.com 等待2秒(因为渲染是异步的,可能需要点时间),将渲染后的内容插入编辑器。
setTimeout(function(){
//mo_yq5 将类似‘<’等的实体标识为文本内容,不然下次用编辑器打开时会被认为是html标签,造成编辑器上看不到该字符。
code = $("#brushContainer").html().replace(/(&){1}(lt;){1}/g,"<code>&"+"lt;</code>");
code = code.replace(/(&){1}(amp;){1}/g,"<code>&"+"amp;</code>");
//mo_yq5 将渲染后的内容插入编辑器,加‘<p/>’是为了让光标移出被渲染后的代码块。
editor.insertHtml(code+"<p/>");
},2000);
}
};
});

代码说明:此代码虽然是在CKEditor插件syntaxhighlighter中定义,但使用到了一些全局对象,比如59行的SyntaxHighlighterSyntaxHighlighter组件中定义的对象,‘shBrushArray’是我在页面上定义的全局数组对象,以及代码中使用了JQuery类库,这些对象的引入将在后面进行说明。重点说明65、66行之目的所在:1,将内容的标签实体用code标签包装(ckeditor内部机制决定),是为了防止编辑器显示内容时,将内容中的标签实体转换为html标签,造成内容在编辑器显示结果与保存结果跟预想的不一致;2,将标签实体(如“&”与“lt;”的连接串)拆分成如代码所示的形式,是为了保证即使在编辑器中编辑上面的代码时显示结果也是正确的;这两点也是我纠结了两三天才写出来,其它问题有待发现。

6,至此,syntaxhighlighter插件在CKEditor上的配置已经完成,效果如下图:

7,完成以上步骤,已经可以将代码插入到编辑器中,但代码还不能在编辑器上高亮显示。要达到这个目的,我们需要考虑被渲染后的代码引用的样式起效情况。被渲染后,代码内容已经定义上SyntaxHighlighter组件中定义的样式,因此我们需要将SyntaxHighlighter组件定义的样式文件引入到编辑器所在页面中来。经过深入,我们了解到,编辑器的编辑框是定义在编辑器所在页面的一个iframe标签下的(即在不同的document对象中),所以直接在编辑器所在页面引入SyntaxHighlighter组件定义的样式文件,是不起作用,因为样式影响不到iframe下的内容。我们需要想法办能够在编辑框所在iframe(即document对象)中引入SyntaxHighlighter组件定义的样式文件。通过用火狐浏览器访问编辑器所在的页面,鼠标右键查看页面元素可以发现,编辑框所在iframe中引入了ckeditor/contents.css这个样式文件。经过测试,引入SyntaxHighlighter组件定义的样式比较简便的方法就是在ckeditor/contents.css中追加SyntaxHighlighter组件定义的样式。具体方法就是加入以下两行(根据自己SyntaxHighlighter的实际路径进行变动):

@IMPORT url("../plugin/syntaxhighlighter_3.0.83/styles/shCoreEclipse.css");
@IMPORT url("../plugin/syntaxhighlighter_3.0.83/styles/shThemeEclipse.css");

8,要体验最终效果,需要在编辑器所在页面引入一些必要的类库,如下(包括之前CKEditor安装所引入的):

  • 在需要显示编辑器的位置贴入
  • <textarea name="article.body">${article.body }</textarea>
  • 在页面底部引入类库
  • <script src="${pageContext.request.contextPath}/include/js/jquery-1.4.1.min.js"></script>
    <script src="${pageContext.request.contextPath}/plugin/syntaxhighlighter_3.0.83/scripts/shCore.js"></script>
    <script src="${pageContext.request.contextPath}/plugin/syntaxhighlighter_3.0.83/scripts/shAutoloader.js"></script>
    <script src="${pageContext.request.contextPath}/ckeditor/ckeditor.js"></script>
    <script>
    var g_contextPath="${pageContext.request.contextPath}";
    //mo_yq5 syntaxhighlighter插件的定义中需要到此对象,具体请看dialogs/syntaxhighlighter.js。
    var shBrushArray = (function(){
    var args = arguments,result = [];
    for(var i = 0; i < args.length; i++)
    result.push(args[i].replace('@', g_contextPath+'/plugin/syntaxhighlighter_3.0.83/scripts/'));
    return result;
    })(
    'applescript @shBrushAppleScript.js',
    'actionscript3 as3 @shBrushAS3.js',
    'bash shell @shBrushBash.js',
    'coldfusion cf @shBrushColdFusion.js',
    'cpp c @shBrushCpp.js',
    'c# c-sharp csharp @shBrushCSharp.js',
    'css @shBrushCss.js',
    'delphi pascal @shBrushDelphi.js',
    'diff patch pas @shBrushDiff.js',
    'erl erlang @shBrushErlang.js',
    'groovy @shBrushGroovy.js',
    'java @shBrushJava.js',
    'jfx javafx @shBrushJavaFX.js',
    'js jscript javascript @shBrushJScript.js',
    'perl pl @shBrushPerl.js',
    'php @shBrushPhp.js',
    'text plain @shBrushPlain.js',
    'py python @shBrushPython.js',
    'ruby rails ror rb @shBrushRuby.js',
    'sass scss @shBrushSass.js',
    'scala @shBrushScala.js',
    'sql @shBrushSql.js',
    'vb vbnet @shBrushVb.js',
    'xml xhtml xslt html @shBrushXml.js');
    //mo_yq5 指定编辑的显示高度
    CKEDITOR.config.height=450;
    //mo_yq5 启用代码高亮显示插件
    CKEDITOR.config.extraPlugins="syntaxhighlighter";
    //mo_yq5 初始化页面上的编辑器
    var editor = CKEDITOR.replace( 'article.body'); </script>

    代码说明:“article.body”是表单名。第4到27行是针对各种语言渲染类;按照官方文档上意思,定义第30到61行即可(syntaxhighlighter.js文件中有调用)。但实际测试结果是,如果只定义30到61行的代码,在编辑器中插入代码时只是第一次插入有效,第二次插入时如果选择的语言类型与上次插入的不同,将会报“Can't find brush for XXX”的错误,所以在我看来4到27行也是需要的(至少目前当作是SyntaxHighlighter的bug来处理),根据需要提供的语言类型进行增减即可。

    9,编辑器配置完成,代码在编辑器中高亮显示的效果,如图:

10,以上是针对编辑器的配置,当编辑后的文章需要在页面中显示时,我们需要在显示文章的页面引入样式文件即可(不需要SyntaxHighlighter的类库),如(也可点击鼠标右键来查看本页面的源代码):

<link rel=stylesheet type=text/css href="${pageContext.request.contextPath}/plugin/syntaxhighlighter_3.0.83/styles/shCoreEclipse.css" />
<link rel=stylesheet type=text/css href="${pageContext.request.contextPath}/plugin/syntaxhighlighter_3.0.83/styles/shThemeEclipse.css" />

以上内容来自:http://www.moyq5.me/article/1/detail/32

补充:

1、在"ckeditor\"目录下找到“config.js”文件,这是CKEditor的配置文件,添加如下代码

config.extraPlugins = 'syntaxhighlighter';//这里只能出现一次,如果之前有加过,用,隔开

2.如果出现中文乱码问题,是页面编码不对,我是ASP.NET,折腾了一番,最终解决,修改Web.config文件

-----旧的
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
<customErrors mode="Off" />
<globalization fileEncoding="GB2312" requestEncoding="GB2312" responseEncoding="GB2312"/>
</system.web>
</configuration>
--乱码问题新的解决办法,,原来是新增的那两个JS文件编码不对,重新打开编码另存为UTF-8格式即可

3.如果CkEditor 添加源码后没有 高亮颜色等,需要 添加配置

config.allowedContent = true;

CKeditor插件开发流程(二)SyntaxHighlighter的更多相关文章

  1. CKeditor插件开发流程(一)

    1.放在多文件中 第一步:config.js中 config.extraPlugins = '插件名称';//注册插件,extraPlugins只允许出现一次,你如果之前有新增别的插件,那么用逗号分隔 ...

  2. CKEditor插件开发

    以前做过一个教育项目,是有关在线考试的.其中对编辑器CKEditor做了扩充,增加了插入客观题.主观题.选择题和判断题的功能.这里记述下CKEditor插件开发的过程. CKEditor以前叫FCKE ...

  3. 【 VS 插件开发 】二、了解Vs插件结构

    [ VS 插件开发 ]二.了解Vs插件结构

  4. Android系统分析之运营商显示流程分析之运营商信息的读取流程二

    运营商显示流程分析之运营商信息的读取流程 一. SIM卡运营商信息的读取 从前面的 运营商信息的获取和赋值 可以知道SIM卡运营商的赋值最终是在 SIMRecords 中完成的, 而SIM卡信息的相关 ...

  5. wordpress插件开发流程梳理

    1.声明一个插件 首先我们必须明白,wordpress的插件可以是单文件,也可以是多文件,css/html都不是必须的,以下举例暂且在单文件模式下 比如我们要创建一个名为 hellophp的插件,那我 ...

  6. wordpress插件开发流程梳理-二

    开发插件的最佳实践 避免命名冲突 当您的插件对变量,函数或类使用相同的名称作为另一个插件时,会发生命名冲突. 幸运的是,您可以使用以下方法避免命名冲突. 程序性 默认情况下,所有变量,函数和类都在全局 ...

  7. jira的插件开发流程实践

    怎么开头呢,由于自己比较懒,博客一直不怎么弄,以后克己一点,多传点自己遇到的问题和经历上来,供自己以后记忆,也供需要的小伙伴少走点弯路吧 最近公司项目需要竞标一个运维项目,甲方给予了既定的几种比较常用 ...

  8. PhoneGap插件开发流程

    前几天写了一个PhoneGap插件,这个插件的功能很简单,就是开启viewport设置.不过与其它插件相比,有好几个有意思的地方,仔细读了PhoneGap的源码才搞定.这里记录一下PhoneGap插件 ...

  9. CkEditor 插件开发

    CKEditor的插件开发其实很简单只需要两步.1.通过CKEditor.plugins.add()方法编写插件的逻辑主体, 2.告诉CKEditor我们有一个自定义插件需要添加进来. //创建插件逻 ...

随机推荐

  1. 杂(三)-The type java.lang.Object cannot be resolved It is indirectly referenced ...

    The type java.lang.Object cannot be resolved. It is indirectly referenced from required .class files ...

  2. 优化MyDb

    import pymysqlclass MyDb(object): #新式类 def __del__(self):#析构函数 self.cur.close() self.coon.close() pr ...

  3. java中获取文件路径的几种方式

    http://xyzroundo.iteye.com/blog/1116159关于绝对路径和相对路径: 绝对路径就是你的主页上的文件或目录在硬盘上真正的路径,(URL和物理路径)例如:C:xyz es ...

  4. angular中使用daterangepicker完全能用版

    angular版本:angular5 先看效果图: 最新版是这样的: 附上插件的网址: http://www.daterangepicker.com/ 1 安装: daterangepicker依赖于 ...

  5. CLR 完全介绍

    From: http://msdn.microsoft.com/zh-cn/magazine/cc164193.aspx http://msdn.microsoft.com/en-us/magazin ...

  6. 微软“小冰”识狗与人工神经网络(I)

    2014年8月21日,微软"小冰"网络机器人推出了一项图像识别技能:"小冰识狗". "小冰"怎么会"识狗"呢? 依据微软 ...

  7. vim 批处理

    一.使用args , argdo 进行文件批处理 1. :args ./src/**/*.js         利用args命令标记所要处理的文件 2. :argdo %s/tabindex/tabI ...

  8. Android的View 事件传递

    欢迎转载,请附出处: http://blog.csdn.net/as02446418/article/details/47422891 1.基础知识 (1) 全部 Touch 事件都被封装成了 Mot ...

  9. SRIO常用缩写

    HELLO:Header Encoded Logical Layer Optimized (HELLO) format FTYPE:format type TTYPE:transaction type ...

  10. unittest 单元测试框架

    引入 unittest 框架 相想使用unittest 框架,首先要引入unittest 包 import unittest class Baidu(unittest.TestCase): Baidu ...