Word中使用代碼高亮插件


一年前我寫了一個word2010的代碼高亮插件,但當時那個版本有一個問題:在用word發布博客的時候,高亮的代碼在博客中的格式亂了。今天有空改了一下這個插件,雖然還是有些瑕疵,但至少發布到博客后,格式不會亂了。主要改進是用ol和li代替了pre,雖然發布到博客后,ol中設置的style和class依然會被改動,但可以在博客中用css來糾正。

下載插件和源代碼:SyntaxHighlighter4Word.zip

下面說一下這個插件的用法。

下載文件后,解壓,然后雙擊bin\word2010\Kong.SyntaxHighlighter.Word2010.vsto或bin\word2007\Kong.SyntaxHighlighter.Word2007.vsto,即可完成安裝,當然前提是你裝了.net framework 4.0。安裝成功后的提示如下:

安裝插件后,會在word中多一個功能區(支持word2007和word2010):

點擊"設置"按鈕,彈出設置界面:

這里簡化了配置,去掉了前一個版本中的一些設置。

點擊"插入代碼"按鈕,彈出如下界面:

可以選擇C#、Java、Xml、Javascript等多種語言。

在word效果如下:

發布到博客后的效果如下:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Windows.Forms;
  6. using Kong.SyntaxHighlighter.Winform;
  7. using Microsoft.Office.Tools.Ribbon;
  8.  
  9. namespace Kong.SyntaxHighlighter.Word
  10. {
  11.     public partial class Ribbon1
  12.     {
  13.         private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
  14.         {
  15.  
  16.         }
  17.     }
  18. }

我在Word中生成這段代碼的時候,用了ol和li,並且設置了ol以及li的style,這樣在word中就可以顯示邊框以及交替行的顏色,同時給ol設了一個class=codeBlock,妄想在發布到博客后可以通過這個樣式名codeBlock來自定義自己喜歡的樣式。我在word中生成的代碼大概是這個樣子:

  1. <ol class="codeBlock" ...

但是word把這段代碼發布到博客后,會去除掉這個class,無語。。。

所以我們在博客中,不得設置所有ol的style,幸好博客園的文章都是在一個id為cnblogs_post_body的div下的,所以我在我博客中加了下面的style:

  1. #cnblogs_post_body ol
  2.  {
  3.      border: 1px dotted #000066;
  4.      line-height: 150%;
  5.      word-break: break-word;
  6.      font-family: Consolas, Verdana !important;
  7.      border-radius: 5px;
  8.      width: 90%;
  9.      background-color: #E3E3FF;
  10.      list-style-position: outside;
  11.      margin-left: 0px;
  12.  }
  13.  #cnblogs_post_body ol font
  14.  {
  15.      font-size: 12px !important;
  16.  }
  17.  #cnblogs_post_body ol li
  18.  {
  19.      background-color: #fff;
  20.      padding-left: 5px;
  21.      border-left: 1px solid #8A8AFF;
  22.      margin-left: 5px !important;
  23.  }
  24.  #cnblogs_post_body ol li:nth-child(even)
  25.  {
  26.      background-color: #f5f5f5;
  27.  }

補充一下,這段文本是加在這里的:

 

插件的使用就介紹到這里,下面簡單介紹一下插件的實現。

如何開發office的add in,園子里已經有很多文章了,我就不介紹了,因為我自己也不懂。

如何實現代碼高亮?我用的是Wilco.SyntaxHighlighting,有興趣的同學可以google一下,我提供的下載包里也有它的源碼。

代碼高亮后,如何粘帖到word里?原理就是把代碼高亮后的文本以html格式復制到剪貼板里,然后調用word的方法去粘帖:

  1. private void InsertButton_Click(object sender, RibbonControlEventArgs e)
  2. {
  3.     var dialog = new MainForm();
  4.     if (dialog.ShowDialog() == DialogResult.OK)
  5.     {
  6.         dialog.CopyToClipboard();
  7.         Globals.ThisAddIn.Application.Selection.Paste();
  8.     }
  9. }

以html格式復制到剪貼板的實現,我是從網上找了一段代碼來做的,核心邏輯如下:

  1.         public static void CopyToClipboard(string htmlFragment, string title, Uri sourceUrl)
  2.         {
  3.             if (title == null) title = "From Clipboard";
  4.  
  5.             System.Text.StringBuilder sb = new System.Text.StringBuilder();
  6.  
  7.             string header =
  8.     @"Format:HTML Format
  9. Version:1.0
  10. StartHTML:<<<<<<<1
  11. EndHTML:<<<<<<<2
  12. StartFragment:<<<<<<<3
  13. EndFragment:<<<<<<<4
  14. StartSelection:<<<<<<<3
  15. EndSelection:<<<<<<<3
  16. ";
  17.  
  18.             string pre =
  19.     @"<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.0 Transitional//EN"">
  20. <HTML><HEAD><TITLE>" + title + @"</TITLE></HEAD><BODY><!--StartFragment-->";
  21.  
  22.             string post = @"<!--EndFragment--></BODY></HTML>";
  23.  
  24.             sb.Append(header);
  25.             if (sourceUrl != null)
  26.             {
  27.                 sb.AppendFormat("SourceURL:{0}", sourceUrl);
  28.             }
  29.             var enc = Encoding.UTF8; //中文亂碼問題
  30.             int startHTML = enc.GetByteCount(sb.ToString());
  31.  
  32.             sb.Append(pre);
  33.             int fragmentStart = enc.GetByteCount(sb.ToString());
  34.  
  35.             sb.Append(htmlFragment);
  36.             int fragmentEnd = enc.GetByteCount(sb.ToString());
  37.  
  38.             sb.Append(post);
  39.             int endHTML = enc.GetByteCount(sb.ToString());
  40.  
  41.             // Backpatch offsets
  42.             sb.Replace("<<<<<<<1", To8DigitString(startHTML));
  43.             sb.Replace("<<<<<<<2", To8DigitString(endHTML));
  44.             sb.Replace("<<<<<<<3", To8DigitString(fragmentStart));
  45.             sb.Replace("<<<<<<<4", To8DigitString(fragmentEnd));
  46.  
  47.             Clipboard.Clear();
  48.             var dataObj = new DataObject();
  49.             dataObj.SetData(DataFormats.Html, new MemoryStream(enc.GetBytes(sb.ToString())));
  50.             Clipboard.SetDataObject(dataObj, true);
  51.         }
  52.  
  53.         #endregion // Write to Clipboard
  54.     }

這個類名叫做HtmlFragment,可以在我提供的下載包里找到。

另外,我這個插件在生成高亮代碼時,可以清除掉代碼段首尾的空行,也可以清除掉每一行的公共空格,比如下面的代碼:

在插入后會變成這個樣子:

  1. private void Test()
  2. {
  3.     var i = 0;
  4.     //do something
  5. }

我用了幾條正則表達式來實現這個功能,代碼如下:

  1. private string GetHtml(string content)
  2. {
  3.     _highlighter.Parser = _htmlParser;
  4.     string html = _highlighter.Parse(content);
  5.     _highlighter.Parser = _parser;
  6.     if (html != null)
  7.     {
  8.         html = html.Replace("\t", " ");
  9.         //清除首尾空行
  10.         html = Regex.Replace(html, @"(^\s*\n)|(\n\s*$)", "", RegexOptions.Singleline);
  11.  
  12.         //清除掉公共的空格
  13.         MatchCollection matches = Regex.Matches(html, @"^ *(?=\S)", RegexOptions.Multiline);
  14.         int len = matches.OfType<Match>().Select(m => m.Value.Length).Min();
  15.         html = Regex.Replace(html, @"^ {" + len + "}", "", RegexOptions.Multiline);
  16.  
  17.         //把每一行開頭的空格變成&nbsp;
  18.         html = Regex.Replace(html, @"^ +(?=\S)",
  19.                              new MatchEvaluator(
  20.                                  m => string.Join("", new string[m.Length].Select(s => "&nbsp;"))),
  21.                              RegexOptions.Multiline);
  22.     }
  23.     return html;
  24. }

有興趣的同學可以下載源碼看一下。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM