为论坛和Blog添加代码高亮显示的功能。
在cnblogs和许多其他论坛、Blog上都有插入程序代码高亮显示的功能。现参考cnblogs的为例,以discuz!NT 2.0 rc2为例,说明如何增加插入代码高亮功能。
cnblogs的代码高亮功能是通过一个共享软件实现的,可以到以下网址下载使用
http://www.actiprosoftware.com/Download/Freeware.aspx
此软件的Api很简单,就是一个Asp.net的控件。可以在网页上输出高亮显示的代码。但我们不想让高亮代码在网页上输出,而是插入到文章中。可以对discuz自带的Editor进行改造,以达到响应的功能。
首先将 ActiproSoftware.CodeHighlighter.Net20.dll、ActiproSoftware.Shared.Net20.dll、CodeHighlighterTest.dll Copy到discuz的bin目录。然后在discuz的页面文件价(aspx/1)下添加InsertCode.aspx文件,内容如下
1<%@ Page Language="C#" %>
2<%@ Import Namespace="ActiproSoftware.CodeHighlighter" %>
3<%@ Import Namespace="System.Reflection" %>
4
5<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6
7<script runat="server">
8 protected string ReturnCode;
9
10 protected override void OnLoad(EventArgs e)
11 {
12 if (!IsPostBack)
13 {
14 //绑定列表,显示所有支持的语言 CodeHighlighterConfiguration config = (CodeHighlighterConfiguration)ConfigurationManager.GetSection("codeHighlighter");
15 string[] keys = new string[config.LanguageConfigs.Keys.Count];
16 config.LanguageConfigs.Keys.CopyTo(keys, 0);
17 Array.Sort(keys);
18 foreach (string key in keys)
19 {
20 LanguageDropDownList.Items.Add(key);
21 }
22 LanguageDropDownList.SelectedIndex = LanguageDropDownList.Items.IndexOf(LanguageDropDownList.Items.FindByText("C#"));
23 }
24
25 base.OnLoad(e);
26 }
27
28 protected void Insert_Click(object sender, EventArgs e)
29 {
30 ActiproSoftware.CodeHighlighter.CodeHighlighter ch = new ActiproSoftware.CodeHighlighter.CodeHighlighter();
31 ch.LanguageKey = LanguageDropDownList.SelectedValue;
32 ch.Text = Code.Text;
33 ch.Page = this;
34 Type t = ch.GetType();
35
36 //通过反射运行控件的处理代码的私有方法
37 MethodInfo method = t.GetMethod("a", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
38 method.Invoke(ch, null);
39
40 //通过反射处理后的代码
41 FieldInfo field = t.GetField("i", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
42 ReturnCode = (string)field.GetValue(ch);
43
44 //将代码放入pre标签中以保持代码格式,并将代码以JavaScript字符串的格式编码,以输出到浏览器
45 ReturnCode = JStringEncode("<pre style='background-color:#eeeeee;font-size:13px;BORDER:1px solid #CCCCCC;PADDING-RIGHT: 5px;PADDING-BOTTOM: 4px;PADDING-left: 4px;PADDING-TOP: 4px;WIDTH: 98%;word-break:break-all'>" + ReturnCode + "</pre>");
46 ReturnPanel.Visible = true;
47 }
48 /// <summary>
49 /// 替换掉字符串中的特殊字符,如把 " 替换成 \"
50 /// </summary>
51 /// <param name="str"></param>
52 /// <returns></returns>
53 public static string JStringEncode( string str )
54 {
55 if( str == null )
56 {
57 return string.Empty;
58 }
59 //替换反斜杠
60 str = str.Replace( @"\", @"\\" );
61 //替换回车
62 str = str.Replace( "\r", @"\r" );
63 str = str.Replace( "\n", @"\n" );
64 //替换 " 号
65 str = str.Replace( "\"", "\\\"" );
66 return str;
67 }
68</script>
69
70<html xmlns="http://www.w3.org/1999/xhtml">
71
72<head runat="server">
73 <title>插入源代码</title>
74</head>
75<body>
76 <form id="form1" runat="server">
77 <div>
78 <table id="Table1" class="tb" cellspacing="0" cellpadding="3" border="0">
79 <tr>
80 <th align="right" style="width: 80px;">
81 编程语言:</th>
82 <td>
83 <asp:DropDownList ID="LanguageDropDownList" runat="server" Width="100px">
84 </asp:DropDownList></td>
85 </tr>
86 <!--tr>
87 <th align="right">
88 选项:</th>
89 <td>
90 <input id="chkLineNumberMarginVisible" type="checkbox" name="chkLineNumberMarginVisible" /><label
91 for="chkLineNumberMarginVisible">显示行号</label> <input id="chkOutliningEnabled"
92 type="checkbox" name="chkOutliningEnabled" checked="checked" /><label for="chkOutliningEnabled">允许代码折叠</label> <input
93 id="ckbIsCollapse" type="checkbox" name="ckbIsCollapse" /><label for="ckbIsCollapse">全部折叠</label> 折叠标题:
94 <input name="txbCollapseText" type="text" id="txbCollapseText" style="width: 70" /></td>
95 </tr-->
96 <tr>
97 <th valign="top" align="right">
98 代码:</th>
99 <td>
100 <asp:TextBox ID="Code" runat="server" Height="200px" TextMode="MultiLine" Width="500px"></asp:TextBox></td>
101 </tr>
102 <tr>
103 <td>
104 </td>
105 <td>
106 <asp:Button ID="Insert" runat="server" OnClick="Insert_Click" Text="确定" /> <input
107 onclick="return window.close()" type="button" value="关闭"></td>
108 </tr>
109 </table>
110 </div>
111 <asp:Panel ID="ReturnPanel" runat="server" Visible="false">
112 <script language="javascript">
113 //在Opener页面中插入处理后的Html文本
114 window.opener.insertText("<% = ReturnCode %>");
115 window.close();
116 </script>
117 </asp:Panel>
118 </form>
119</body>
120</html>
121
2<%@ Import Namespace="ActiproSoftware.CodeHighlighter" %>
3<%@ Import Namespace="System.Reflection" %>
4
5<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6
7<script runat="server">
8 protected string ReturnCode;
9
10 protected override void OnLoad(EventArgs e)
11 {
12 if (!IsPostBack)
13 {
14 //绑定列表,显示所有支持的语言 CodeHighlighterConfiguration config = (CodeHighlighterConfiguration)ConfigurationManager.GetSection("codeHighlighter");
15 string[] keys = new string[config.LanguageConfigs.Keys.Count];
16 config.LanguageConfigs.Keys.CopyTo(keys, 0);
17 Array.Sort(keys);
18 foreach (string key in keys)
19 {
20 LanguageDropDownList.Items.Add(key);
21 }
22 LanguageDropDownList.SelectedIndex = LanguageDropDownList.Items.IndexOf(LanguageDropDownList.Items.FindByText("C#"));
23 }
24
25 base.OnLoad(e);
26 }
27
28 protected void Insert_Click(object sender, EventArgs e)
29 {
30 ActiproSoftware.CodeHighlighter.CodeHighlighter ch = new ActiproSoftware.CodeHighlighter.CodeHighlighter();
31 ch.LanguageKey = LanguageDropDownList.SelectedValue;
32 ch.Text = Code.Text;
33 ch.Page = this;
34 Type t = ch.GetType();
35
36 //通过反射运行控件的处理代码的私有方法
37 MethodInfo method = t.GetMethod("a", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
38 method.Invoke(ch, null);
39
40 //通过反射处理后的代码
41 FieldInfo field = t.GetField("i", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
42 ReturnCode = (string)field.GetValue(ch);
43
44 //将代码放入pre标签中以保持代码格式,并将代码以JavaScript字符串的格式编码,以输出到浏览器
45 ReturnCode = JStringEncode("<pre style='background-color:#eeeeee;font-size:13px;BORDER:1px solid #CCCCCC;PADDING-RIGHT: 5px;PADDING-BOTTOM: 4px;PADDING-left: 4px;PADDING-TOP: 4px;WIDTH: 98%;word-break:break-all'>" + ReturnCode + "</pre>");
46 ReturnPanel.Visible = true;
47 }
48 /// <summary>
49 /// 替换掉字符串中的特殊字符,如把 " 替换成 \"
50 /// </summary>
51 /// <param name="str"></param>
52 /// <returns></returns>
53 public static string JStringEncode( string str )
54 {
55 if( str == null )
56 {
57 return string.Empty;
58 }
59 //替换反斜杠
60 str = str.Replace( @"\", @"\\" );
61 //替换回车
62 str = str.Replace( "\r", @"\r" );
63 str = str.Replace( "\n", @"\n" );
64 //替换 " 号
65 str = str.Replace( "\"", "\\\"" );
66 return str;
67 }
68</script>
69
70<html xmlns="http://www.w3.org/1999/xhtml">
71
72<head runat="server">
73 <title>插入源代码</title>
74</head>
75<body>
76 <form id="form1" runat="server">
77 <div>
78 <table id="Table1" class="tb" cellspacing="0" cellpadding="3" border="0">
79 <tr>
80 <th align="right" style="width: 80px;">
81 编程语言:</th>
82 <td>
83 <asp:DropDownList ID="LanguageDropDownList" runat="server" Width="100px">
84 </asp:DropDownList></td>
85 </tr>
86 <!--tr>
87 <th align="right">
88 选项:</th>
89 <td>
90 <input id="chkLineNumberMarginVisible" type="checkbox" name="chkLineNumberMarginVisible" /><label
91 for="chkLineNumberMarginVisible">显示行号</label> <input id="chkOutliningEnabled"
92 type="checkbox" name="chkOutliningEnabled" checked="checked" /><label for="chkOutliningEnabled">允许代码折叠</label> <input
93 id="ckbIsCollapse" type="checkbox" name="ckbIsCollapse" /><label for="ckbIsCollapse">全部折叠</label> 折叠标题:
94 <input name="txbCollapseText" type="text" id="txbCollapseText" style="width: 70" /></td>
95 </tr-->
96 <tr>
97 <th valign="top" align="right">
98 代码:</th>
99 <td>
100 <asp:TextBox ID="Code" runat="server" Height="200px" TextMode="MultiLine" Width="500px"></asp:TextBox></td>
101 </tr>
102 <tr>
103 <td>
104 </td>
105 <td>
106 <asp:Button ID="Insert" runat="server" OnClick="Insert_Click" Text="确定" /> <input
107 onclick="return window.close()" type="button" value="关闭"></td>
108 </tr>
109 </table>
110 </div>
111 <asp:Panel ID="ReturnPanel" runat="server" Visible="false">
112 <script language="javascript">
113 //在Opener页面中插入处理后的Html文本
114 window.opener.insertText("<% = ReturnCode %>");
115 window.close();
116 </script>
117 </asp:Panel>
118 </form>
119</body>
120</html>
121
然后修改discuz的webconfig,如下所示
1<?xml version="1.0" encoding="utf-8" ?>
2<configuration>
3 <configSections>
4 <section name="codeHighlighter" requirePermission="false" type="ActiproSoftware.CodeHighlighter.CodeHighlighterConfigurationSectionHandler, ActiproSoftware.CodeHighlighter.Net20"/>
5 </configSections>
6
7 <system.web>
8
9 <compilation
10 defaultLanguage="c#"
11 debug="false"
12 />
13
14 <authorization>
15 <allow users="*" /> <!-- 允许所有用户 -->
16 </authorization>
17
18 <trace
19 enabled="false"
20 requestLimit="10"
21 pageOutput="false"
22 traceMode="SortByTime"
23 localOnly="true"
24 />
25
26 <!-- 以下为Discuz!NT相关的一些系统设置, 如果有疑问, 请访问 http://nt.discuz.net/config 获得更详细的说明
27 -->
28
29
30
31 <!-- 注意:此节设置错误信息的显示
32
33 "On" 始终显示自定义(友好的)信息。
34 "Off" 始终显示详细的 ASP.NET 错误信息。
35 "RemoteOnly" 只对不在本地 Web 服务器上运行的
36 -->
37 <customErrors
38 mode="RemoteOnly"
39 />
40
41 <!-- 注意:此节设置全球化,Discuz!NT由此支持多语言。
42 -->
43 <globalization
44 requestEncoding="utf-8"
45 responseEncoding="utf-8"
46 fileEncoding="utf-8"
47 />
48
49 <!-- 注意:此节设置是否使用ASP.net表单安全验证,Discuz!NT使用自己的验证。
50 -->
51 <pages
52 validateRequest="false"
53 enableEventValidation="false"
54 enableViewStateMac="false"
55 viewStateEncryptionMode ="Never"
56 />
57
58 <!-- 注意:此节设置由Discuz!NT接管http请求。不会干涉对非Discuz!NT论坛路径下的请求。
59 -->
60 <httpModules>
61 <add type="Discuz.Forum.HttpModule, Discuz.Forum" name="HttpModule" />
62 </httpModules>
63
64 <xhtmlConformance mode="Legacy"/>
65
66 <httpRuntime maxRequestLength="2097151" executionTimeout="3600"/>
67
68 <webServices>
69 <protocols>
70 <add name="HttpGet" />
71 <add name="HttpPost"/>
72 </protocols>
73 </webServices>
74
75
76 </system.web>
77
78 <codeHighlighter>
79 <cache languageTimeout="3"/>
80 <keywordLinking enabled="true" target="_blank" defaultKeywordCollectionKey="ActiproKeywords">
81 <keywordCollection key="ActiproKeywords">
82 <explicitKeyword tokenKey="IdentifierToken" patternValue="Actipro" url="http://www.actiprosoftware.com" caseSensitive="false"/>
83 <explicitKeyword tokenKey="IdentifierToken" patternValue="CodeHighlighter" url="http://www.codehighlighter.com" caseSensitive="false"/>
84 </keywordCollection>
85 </keywordLinking>
86 <languages>
87 <language key="Assembly" definitionPath="~/Languages/Lexers/ActiproSoftware.Assembly.xml"/>
88 <language key="BatchFile" definitionPath="~/Languages/Lexers/ActiproSoftware.BatchFile.xml"/>
89 <language key="C#" definitionPath="~/Languages/Lexers/ActiproSoftware.CSharp.xml"/>
90 <language key="CSS" definitionPath="~/Languages/Lexers/ActiproSoftware.CSS.xml"/>
91 <language key="HTML" definitionPath="~/Languages/Lexers/ActiproSoftware.HTML.xml"/>
92 <language key="INIFile" definitionPath="~/Languages/Lexers/ActiproSoftware.INIFile.xml"/>
93 <language key="Java" definitionPath="~/Languages/Lexers/ActiproSoftware.Java.xml"/>
94 <language key="JScript" definitionPath="~/Languages/Lexers/ActiproSoftware.JScript.xml"/>
95 <language key="Lua" definitionPath="~/Languages/Lexers/ActiproSoftware.Lua.xml"/>
96 <language key="MSIL" definitionPath="~/Languages/Lexers/ActiproSoftware.MSIL.xml"/>
97 <language key="Pascal" definitionPath="~/Languages/Lexers/ActiproSoftware.Pascal.xml"/>
98 <language key="Perl" definitionPath="~/Languages/Lexers/ActiproSoftware.Perl.xml"/>
99 <language key="PHP" definitionPath="~/Languages/Lexers/ActiproSoftware.PHP.xml"/>
100 <language key="PowerShell" definitionPath="~/Languages/Lexers/ActiproSoftware.PowerShell.xml"/>
101 <language key="Python" definitionPath="~/Languages/Lexers/ActiproSoftware.Python.xml"/>
102 <language key="SQL" definitionPath="~/Languages/Lexers/ActiproSoftware.SQL.xml"/>
103 <language key="VB.NET" definitionPath="~/Languages/Lexers/ActiproSoftware.VBDotNet.xml"/>
104 <language key="VBScript" definitionPath="~/Languages/Lexers/ActiproSoftware.VBScript.xml"/>
105 <language key="XAML" definitionPath="~/Languages/Lexers/ActiproSoftware.XAML.xml"/>
106 <language key="XML" definitionPath="~/Languages/Lexers/ActiproSoftware.XML.xml"/>
107 </languages>
108 <lineNumberMargin foreColor="Teal" paddingCharacter=" " visible="true"/>
109 <outlining enabled="true" imagesPath="~/Images/OutliningIndicators/"/>
110 <spacesInTabs count="4"/>
111 </codeHighlighter>
112
113</configuration>
2<configuration>
3 <configSections>
4 <section name="codeHighlighter" requirePermission="false" type="ActiproSoftware.CodeHighlighter.CodeHighlighterConfigurationSectionHandler, ActiproSoftware.CodeHighlighter.Net20"/>
5 </configSections>
6
7 <system.web>
8
9 <compilation
10 defaultLanguage="c#"
11 debug="false"
12 />
13
14 <authorization>
15 <allow users="*" /> <!-- 允许所有用户 -->
16 </authorization>
17
18 <trace
19 enabled="false"
20 requestLimit="10"
21 pageOutput="false"
22 traceMode="SortByTime"
23 localOnly="true"
24 />
25
26 <!-- 以下为Discuz!NT相关的一些系统设置, 如果有疑问, 请访问 http://nt.discuz.net/config 获得更详细的说明
27 -->
28
29
30
31 <!-- 注意:此节设置错误信息的显示
32
33 "On" 始终显示自定义(友好的)信息。
34 "Off" 始终显示详细的 ASP.NET 错误信息。
35 "RemoteOnly" 只对不在本地 Web 服务器上运行的
36 -->
37 <customErrors
38 mode="RemoteOnly"
39 />
40
41 <!-- 注意:此节设置全球化,Discuz!NT由此支持多语言。
42 -->
43 <globalization
44 requestEncoding="utf-8"
45 responseEncoding="utf-8"
46 fileEncoding="utf-8"
47 />
48
49 <!-- 注意:此节设置是否使用ASP.net表单安全验证,Discuz!NT使用自己的验证。
50 -->
51 <pages
52 validateRequest="false"
53 enableEventValidation="false"
54 enableViewStateMac="false"
55 viewStateEncryptionMode ="Never"
56 />
57
58 <!-- 注意:此节设置由Discuz!NT接管http请求。不会干涉对非Discuz!NT论坛路径下的请求。
59 -->
60 <httpModules>
61 <add type="Discuz.Forum.HttpModule, Discuz.Forum" name="HttpModule" />
62 </httpModules>
63
64 <xhtmlConformance mode="Legacy"/>
65
66 <httpRuntime maxRequestLength="2097151" executionTimeout="3600"/>
67
68 <webServices>
69 <protocols>
70 <add name="HttpGet" />
71 <add name="HttpPost"/>
72 </protocols>
73 </webServices>
74
75
76 </system.web>
77
78 <codeHighlighter>
79 <cache languageTimeout="3"/>
80 <keywordLinking enabled="true" target="_blank" defaultKeywordCollectionKey="ActiproKeywords">
81 <keywordCollection key="ActiproKeywords">
82 <explicitKeyword tokenKey="IdentifierToken" patternValue="Actipro" url="http://www.actiprosoftware.com" caseSensitive="false"/>
83 <explicitKeyword tokenKey="IdentifierToken" patternValue="CodeHighlighter" url="http://www.codehighlighter.com" caseSensitive="false"/>
84 </keywordCollection>
85 </keywordLinking>
86 <languages>
87 <language key="Assembly" definitionPath="~/Languages/Lexers/ActiproSoftware.Assembly.xml"/>
88 <language key="BatchFile" definitionPath="~/Languages/Lexers/ActiproSoftware.BatchFile.xml"/>
89 <language key="C#" definitionPath="~/Languages/Lexers/ActiproSoftware.CSharp.xml"/>
90 <language key="CSS" definitionPath="~/Languages/Lexers/ActiproSoftware.CSS.xml"/>
91 <language key="HTML" definitionPath="~/Languages/Lexers/ActiproSoftware.HTML.xml"/>
92 <language key="INIFile" definitionPath="~/Languages/Lexers/ActiproSoftware.INIFile.xml"/>
93 <language key="Java" definitionPath="~/Languages/Lexers/ActiproSoftware.Java.xml"/>
94 <language key="JScript" definitionPath="~/Languages/Lexers/ActiproSoftware.JScript.xml"/>
95 <language key="Lua" definitionPath="~/Languages/Lexers/ActiproSoftware.Lua.xml"/>
96 <language key="MSIL" definitionPath="~/Languages/Lexers/ActiproSoftware.MSIL.xml"/>
97 <language key="Pascal" definitionPath="~/Languages/Lexers/ActiproSoftware.Pascal.xml"/>
98 <language key="Perl" definitionPath="~/Languages/Lexers/ActiproSoftware.Perl.xml"/>
99 <language key="PHP" definitionPath="~/Languages/Lexers/ActiproSoftware.PHP.xml"/>
100 <language key="PowerShell" definitionPath="~/Languages/Lexers/ActiproSoftware.PowerShell.xml"/>
101 <language key="Python" definitionPath="~/Languages/Lexers/ActiproSoftware.Python.xml"/>
102 <language key="SQL" definitionPath="~/Languages/Lexers/ActiproSoftware.SQL.xml"/>
103 <language key="VB.NET" definitionPath="~/Languages/Lexers/ActiproSoftware.VBDotNet.xml"/>
104 <language key="VBScript" definitionPath="~/Languages/Lexers/ActiproSoftware.VBScript.xml"/>
105 <language key="XAML" definitionPath="~/Languages/Lexers/ActiproSoftware.XAML.xml"/>
106 <language key="XML" definitionPath="~/Languages/Lexers/ActiproSoftware.XML.xml"/>
107 </languages>
108 <lineNumberMargin foreColor="Teal" paddingCharacter=" " visible="true"/>
109 <outlining enabled="true" imagesPath="~/Images/OutliningIndicators/"/>
110 <spacesInTabs count="4"/>
111 </codeHighlighter>
112
113</configuration>
Copy高亮组件的 Languages\Lexers、Images\OutliningIndicators 目录到discuz的指定目录
在discuz的编辑器文件 editor\editor.js,在function discuzcode(cmd, arg)函数中if else组里添加处理insertcode的代码
if (cmd == "insertcode")
{
window.open('../InsertCode.aspx', null, 'height=500, width=600, toolbar=no, menubar=no, scrollbars=no, resizable=no,location=no, status=no');
}
{
window.open('../InsertCode.aspx', null, 'height=500, width=600, toolbar=no, menubar=no, scrollbars=no, resizable=no,location=no, status=no');
}
修改discuz编辑器文件 editor\cp_editor.htm 在插入图片后变添加插入代码的命令
<a id="posteditor_cmd_insertcode">插入代码</a>
现在,discuz的blog里就有插入高亮代码的功能了。