2 // The ecmaspec provider is for ECMA specifications
5 // John Luke (jluke@cfl.rr.com)
6 // Ben Maurer (bmaurer@users.sourceforge.net)
9 // mono assembler.exe --ecmaspec DIRECTORY --out name
13 using System.Diagnostics;
16 using System.Xml.XPath;
19 using System.Collections.Generic;
20 using Mono.Lucene.Net.Index;
21 using Mono.Lucene.Net.Documents;
23 namespace MonkeyDoc.Providers
25 public class EcmaSpecProvider : Provider
29 public EcmaSpecProvider (string base_directory)
31 basedir = base_directory;
32 if (!Directory.Exists (basedir))
33 throw new DirectoryNotFoundException (String.Format ("The directory `{0}' does not exist", basedir));
36 public override void PopulateTree (Tree tree)
38 XPathNavigator n = new XPathDocument (Path.Combine (basedir, "toc.xml")).CreateNavigator ();
40 n.MoveToFirstChild ();
41 PopulateNode (n.SelectChildren ("node", ""), tree.RootNode);
44 void PopulateNode (XPathNodeIterator nodes, Node treeNode)
46 foreach (XPathNavigator n in nodes) {
47 string secNumber = n.GetAttribute ("number", "");
48 string secName = n.GetAttribute ("name", "");
50 var storage = treeNode.Tree.HelpSource.Storage;
51 using (var file = File.OpenRead (Path.Combine (basedir, secNumber + ".xml")))
52 storage.Store (secNumber, file);
54 Node thisNode = treeNode.GetOrCreateNode (secNumber + ": " + secName, "ecmaspec:" + secNumber);
57 PopulateNode (n.SelectChildren ("node", ""), thisNode);
61 public override void CloseTree (HelpSource hs, Tree tree)
66 public class EcmaSpecHelpSource : HelpSource
68 const string EcmaspecPrefix = "ecmaspec:";
69 const string TocPart = "%toc"; // What is returned as TocXml
70 const string SpecPart = "%spec"; // What is returned as Ecmaspec
72 public EcmaSpecHelpSource (string base_file, bool create) : base (base_file, create)
76 public override DocumentType GetDocumentTypeForId (string id, out Dictionary<string, string> extraParams)
79 return id.EndsWith (TocPart) ? DocumentType.TocXml : DocumentType.EcmaSpecXml;
82 public override bool IsGeneratedContent (string id)
84 return id == "root:" || id.EndsWith (TocPart);
87 public override bool IsMultiPart (string id, out IEnumerable<string> parts)
89 if (id == "root:" || id.EndsWith (TocPart) || id.EndsWith (SpecPart)) {
93 parts = MakeMultiPart (id);
97 IEnumerable<string> MakeMultiPart (string baseId)
99 yield return baseId + SpecPart;
100 yield return baseId + TocPart;
103 public override string GetText (string id)
105 Node n = id == "root:" ? Tree.RootNode : MatchNode (EcmaspecPrefix + id.Substring (0, id.Length - TocPart.Length));
107 throw new ArgumentException ("id", string.Format ("{0} -> {1}", id, EcmaspecPrefix + id.Substring (0, id.Length - TocPart.Length)));
108 return TreeDumper.ExportToTocXml (n, "C# Language Specification", "In this section:");
111 public override Stream GetHelpStream (string id)
113 return id.EndsWith (SpecPart) ? base.GetHelpStream (id.Substring (0, id.IndexOf (SpecPart))) : base.GetHelpStream (id);
116 public override void PopulateSearchableIndex (IndexWriter writer)
118 foreach (Node n in Tree.RootNode.Nodes)
119 AddDocuments (writer, n);
122 protected override string UriPrefix {
124 return EcmaspecPrefix;
128 void AddDocuments (IndexWriter writer, Node node)
130 string url = node.PublicUrl;
131 Stream file_stream = GetHelpStream (url.Substring (9));
132 if (file_stream == null) //Error
134 XmlDocument xdoc = new XmlDocument ();
135 xdoc.Load (new XmlTextReader (file_stream));
138 XmlNode nelem = xdoc.DocumentElement;
139 string title = nelem.Attributes["number"].Value + ": " + nelem.Attributes["title"].Value;
142 StringBuilder s = new StringBuilder ();
143 GetTextNode (nelem, s);
144 string text = s.ToString ();
146 //Obtain the examples
147 StringBuilder s2 = new StringBuilder ();
148 GetExamples (nelem, s2);
149 string examples = s2.ToString ();
151 //Write to the Lucene Index all the parts
152 SearchableDocument doc = new SearchableDocument ();
154 doc.hottext = title.Substring (title.IndexOf (':'));
157 doc.examples = examples;
158 writer.AddDocument (doc.LuceneDoc);
163 foreach (Node n in node.Nodes)
164 AddDocuments (writer, n);
167 void GetTextNode (XmlNode n, StringBuilder s)
169 //dont include c# code
170 if (n.Name == "code_example")
172 //include all text from nodes
173 if (n.NodeType == XmlNodeType.Text)
176 //recursively explore all nodes
178 foreach (XmlNode n_child in n.ChildNodes)
179 GetTextNode (n_child, s);
182 void GetExamples (XmlNode n, StringBuilder s)
184 if (n.Name == "code_example") {
185 if (n.FirstChild.Name == "#cdata-section")
186 s.Append (n.FirstChild.Value);
189 foreach (XmlNode n_child in n.ChildNodes)
190 GetExamples (n_child, s);