0
点赞
收藏
分享

微信扫一扫

【转载】Word中使用代码高亮插件

南陵王梁枫 2022-03-30 阅读 71


​​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中使用代码高亮插件_代码高亮

安装插件后,会在word中多一个功能区(支持word2007和word2010):

【转载】Word中使用代码高亮插件_git_02

点击"设置"按钮,弹出设置界面:

【转载】Word中使用代码高亮插件_代码高亮_03

这里简化了配置,去掉了前一个版本中的一些设置。

点击"插入代码"按钮,弹出如下界面:

【转载】Word中使用代码高亮插件_代码高亮_04

可以选择C#、Java、Xml、Javascript等多种语言。

在word效果如下:

【转载】Word中使用代码高亮插件_git_05

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

  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. namespace Kong.SyntaxHighlighter.Word

  9. {

  10.     public partial class Ribbon1

  11.     {

  12.         private void Ribbon1_Load(object sender, RibbonUIEventArgs e)

  13.         {

  14.         }

  15.     }

  16. }

    我在Word中生成这段代码的时候,用了ol和li,并且设置了ol以及li的style,这样在word中就可以显示边框以及交替行的颜色,同时给ol设了一个class=codeBlock,妄想在发布到博客后可以通过这个样式名codeBlock来自定义自己喜欢的样式。我在word中生成的代码大概是这个样子:

  17. <ol class="codeBlock" ...

    但是word把这段代码发布到博客后,会去除掉这个class,无语。。。

    所以我们在博客中,不得设置所有ol的style,幸好博客园的文章都是在一个id为cnblogs_post_body的div下的,所以我在我博客中加了下面的style:

  18. #cnblogs_post_body ol

  19.  {

  20.      border: 1px dotted #000066;

  21.      line-height: 150%;

  22.      word-break: break-word;

  23.      font-family: Consolas, Verdana !important;

  24.      border-radius: 5px;

  25.      width: 90%;

  26.      background-color: #E3E3FF;

  27.      list-style-position: outside;

  28.      margin-left: 0px;

  29.  }

  30.  #cnblogs_post_body ol font

  31.  {

  32.      font-size: 12px !important;

  33.  }

  34.  #cnblogs_post_body ol li

  35.  {

  36.      background-color: #fff;

  37.      padding-left: 5px;

  38.      border-left: 1px solid #8A8AFF;

  39.      margin-left: 5px !important;

  40.  }

  41.  #cnblogs_post_body ol li:nth-child(even)

  42.  {

  43.      background-color: #f5f5f5;

  44.  }

    补充一下,这段文本是加在这里的:

    【转载】Word中使用代码高亮插件_git_06


    插件的使用就介绍到这里,下面简单介绍一下插件的实现。

    如何开发office的add in,园子里已经有很多文章了,我就不介绍了,因为我自己也不懂。

    如何实现代码高亮?我用的是Wilco.SyntaxHighlighting,有兴趣的同学可以google一下,我提供的下载包里也有它的源码。

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

  45. private void InsertButton_Click(object sender, RibbonControlEventArgs e)

  46. {

  47.     var dialog = new MainForm();

  48.     if (dialog.ShowDialog() == DialogResult.OK)

  49.     {

  50.         dialog.CopyToClipboard();

  51.         Globals.ThisAddIn.Application.Selection.Paste();

  52.     }

  53. }

    以html格式复制到剪贴板的实现,我是从网上找了一段代码来做的,核心逻辑如下:

  54.         public static void CopyToClipboard(string htmlFragment, string title, Uri sourceUrl)

  55.         {

  56.             if (title == null) title = "From Clipboard";

  57.             System.Text.StringBuilder sb = new System.Text.StringBuilder();

  58.             string header =

  59.     @"Format:HTML Format

  60. Version:1.0

  61. StartHTML:<<<<<<<1

  62. EndHTML:<<<<<<<2

  63. StartFragment:<<<<<<<3

  64. EndFragment:<<<<<<<4

  65. StartSelection:<<<<<<<3

  66. EndSelection:<<<<<<<3

  67. ";

  68.             string pre =

  69.     @"<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.0 Transitional//EN"">

  70. <HTML><HEAD><TITLE>" + title + @"</TITLE></HEAD><BODY><!--StartFragment-->";

  71.             string post = @"<!--EndFragment--></BODY></HTML>";

  72.             sb.Append(header);

  73.             if (sourceUrl != null)

  74.             {

  75.                 sb.AppendFormat("SourceURL:{0}", sourceUrl);

  76.             }

  77.             var enc = Encoding.UTF8; //中文乱码问题

  78.             int startHTML = enc.GetByteCount(sb.ToString());

  79.             sb.Append(pre);

  80.             int fragmentStart = enc.GetByteCount(sb.ToString());

  81.             sb.Append(htmlFragment);

  82.             int fragmentEnd = enc.GetByteCount(sb.ToString());

  83.             sb.Append(post);

  84.             int endHTML = enc.GetByteCount(sb.ToString());

  85.             // Backpatch offsets

  86.             sb.Replace("<<<<<<<1", To8DigitString(startHTML));

  87.             sb.Replace("<<<<<<<2", To8DigitString(endHTML));

  88.             sb.Replace("<<<<<<<3", To8DigitString(fragmentStart));

  89.             sb.Replace("<<<<<<<4", To8DigitString(fragmentEnd));

  90.             Clipboard.Clear();

  91.             var dataObj = new DataObject();

  92.             dataObj.SetData(DataFormats.Html, new MemoryStream(enc.GetBytes(sb.ToString())));

  93.             Clipboard.SetDataObject(dataObj, true);

  94.         }

  95.         #endregion // Write to Clipboard

  96.     }

    这个类名叫做HtmlFragment,可以在我提供的下载包里找到。

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

    【转载】Word中使用代码高亮插件_html_07

    在插入后会变成这个样子:

  97. private void Test()

  98. {

  99.     var i = 0;

  100.     //do something

  101. }

    我用了几条正则表达式来实现这个功能,代码如下:

  102. private string GetHtml(string content)

  103. {

  104.     _highlighter.Parser = _htmlParser;

  105.     string html = _highlighter.Parse(content);

  106.     _highlighter.Parser = _parser;

  107.     if (html != null)

  108.     {

  109.         html = html.Replace("\t", " ");

  110.         //清除首尾空行

  111.         html = Regex.Replace(html, @"(^\s*\n)|(\n\s*$)", "", RegexOptions.Singleline);

  112.         //清除掉公共的空格

  113.         MatchCollection matches = Regex.Matches(html, @"^ *(?=\S)", RegexOptions.Multiline);

  114.         int len = matches.OfType<Match>().Select(m => m.Value.Length).Min();

  115.         html = Regex.Replace(html, @"^ {" + len + "}", "", RegexOptions.Multiline);

  116.         //把每一行开头的空格变成&nbsp;

  117.         html = Regex.Replace(html, @"^ +(?=\S)",

  118.                              new MatchEvaluator(

  119.                                  m => string.Join("", new string[m.Length].Select(s => "&nbsp;"))),

  120.                              RegexOptions.Multiline);

  121.     }

  122.     return html;

  123. }

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

     本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。


举报

相关推荐

0 条评论