• 00
  • :
  • 00
  • :
  • 00

CKeditor插件开发流程(二)SyntaxHighlighter

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;

 

posted @ 2014-10-30 15:05  Garson_Zhang  阅读(1013)  评论(0编辑  收藏  举报