zoukankan      html  css  js  c++  java
  • 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. }

    有兴趣的同学可以下载源码看一下。

  • 相关阅读:
    报告论文:数字图像噪音处理研究
    报告论文:汽车GPS调度系统车载终端设计技术方案
    疾病研究:我是一名34岁的进行性肌营养不良症患者
    08年最热门七大技术和最紧缺的IT人才
    C#序列化
    网络游戏的数据管理
    2008年3月Google占美国搜索请求量市场份额达67.3%
    C#反转字符串效率最高的方法
    何时应该使用极限编程
    几种字符串反转方法效率比较
  • 原文地址:https://www.cnblogs.com/default/p/2537225.html
Copyright © 2011-2022 走看看