前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Word中使用代码高亮插件

Word中使用代码高亮插件

作者头像
明年我18
发布2019-09-18 11:51:24
1.4K0
发布2019-09-18 11:51:24
举报
文章被收录于专栏:明年我18明年我18

一年前我写了一个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. 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中生成的代码大概是这个样子:

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

这个类名叫做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. MatchCollection matches = Regex.Matches(html, @"^ *(?=\S)", RegexOptions.Multiline);
  13. int len = matches.OfType<Match>().Select(m => m.Value.Length).Min();
  14. html = Regex.Replace(html, @"^ {" + len + "}", "", RegexOptions.Multiline);
  15. //把每一行开头的空格变成&nbsp;
  16. html = Regex.Replace(html, @"^ +(?=\S)",
  17. new MatchEvaluator(
  18. m => string.Join("", new string[m.Length].Select(s => "&nbsp;"))),
  19. RegexOptions.Multiline);
  20. }
  21. return html;
  22. }

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2012-06-05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档