FlexWiki的Topic采用Pascal单词形式,对中文的Topic无法自动进行处理,我对其进行了一些扩展以支持中文主题,
FlexWiki的设计并没有提供很好的扩展点,为了避免对原有的格式处理造成影响,采用在其对Topic内容格式化完成后进行切入,
string formattedBody = TheFederation.GetTopicFormattedContent(topic, diffVersion); // 在此处切入扩展处理程序, FormatterExtension为自定义的格式化扩展程序. if (TheFederation.FormatterExtension != null) formattedBody = TheFederation.FormatterExtension.Format(TheFederation, TheLinkMaker, topic, formattedBody);
显然,通过配置文件是最灵活的扩展设置方式,首先定义一个格式化扩展处理接口
public interface IFormatterExtension { string Format(Federation federation, LinkMaker linkMaker, AbsoluteTopicName topic, string body); }
然后在NamespaceMap.xml中加入以下定义
<FormatterExtension>FlexWiki.Extensions.ChineseFormatterExtension, FlexWiki.Extensions</FormatterExtension>
配置的处理程序就不列出了,请查看Federation.cs和FederationConfiguration.cs中的代码。
创建一个中文格式扩展类ChineseFormatterExtension, 它实现了上面的扩展接口。
1. 取出所有Namespace的Topic.
topics = new Hashtable(); // 遍历所有Namespace foreach (ContentBase cb in federation.AllNamespaces) { // 遍历所有Topic IEnumerator em = cb.AllTopics(false).GetEnumerator(); while (em.MoveNext()) { AbsoluteTopicName tp = (AbsoluteTopicName)em.Current; if (tp.Name.Equals("_ContentBaseDefinition") || tp.Name.Equals("_NormalBorders")) continue; if (!topics.ContainsKey(tp.Name)) topics[tp.Name] = new ExTopic(tp, true);//true标识这是一个存在的主题。 } }
2. 给没有链接的Topic加上链接
string content = body; string tooltips = ""; // 遍历所有Topic, 给无链接的主题加上链接. foreach (string key in topics.Keys) { // 匹配有链接和无链接的主题. string pattern = string.Format("(<a.*?>.*?{0}.*?</a>)|(?<link>{1})", key, key); Regex r = new Regex(pattern, RegexOptions.IgnoreCase|RegexOptions.Compiled); ArrayList positions = new ArrayList(); for (Match m = r.Match(content); m.Success; m = m.NextMatch()) { int index = m.Groups[2].Index; if (index > 0) { // 记录无链接的主题的位置和长度. int i = content.LastIndexOf(">", index); if (i == -1 || i > content.LastIndexOf("<", index)) positions.Add(new Position(index, m.Groups[2].Length)); } } string tooltip; // 取得主题的链接和提示文本。 string link = GetTopicLink(federation, linkMaker, (ExTopic)topics[key], out tooltip); StringBuilder sb = new StringBuilder(content); for (int i=positions.Count-1; i>=0; i--) { // 替换主题 Position pos = (Position)positions[i]; sb.Remove(pos.Index, pos.Length); sb.Insert(pos.Index, link); } content = sb.ToString(); tooltips += tooltip; } 其中: Position记录主题在正文中的位置信息, ExTopic包装TopicName对象,记录Topic是否是存在的。
因为中文无法像Pascal形式的单词那样被识别,那么我们就通过一个文件来定义它们,
在NamespaceMap.xml相同的文件夹下创建一个cntopics.dat文件,其中每行定义一个主题,
格式为Namespace.TopicName,如果省略Namespace,则以默认空间处理。例如;
Framework.程序框架 中文测试
处理程序如下:
FileInfo fi = new FileInfo(federation.FederationNamespaceMapFilename); string cntopics = fi.DirectoryName + "//cntopics.dat"; if (File.Exists(cntopics)) { StreamReader sr = new StreamReader(cntopics, Encoding.GetEncoding("GB2312")); string each = null; while ((each = sr.ReadLine()) != null) { if (each.Trim().Length == 0) continue; if (each.IndexOf('.') == -1) each = federation.DefaultNamespace + "." + each; // 创建一个主题. AbsoluteTopicName tp = new AbsoluteTopicName(each); if (!topics.ContainsKey(tp.Name)) topics[tp.Name] = new ExTopic(tp, false);//false标识这一个要创建的Topic。 } sr.Close(); }
FlexWiki1.8中文主题支持版下载 FlexWikiCore-1.8.0.1696-cn-0.1.zip