a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
194 lines
5.2 KiB
C#
194 lines
5.2 KiB
C#
//
|
|
// The ecmaspec provider is for ECMA specifications
|
|
//
|
|
// Authors:
|
|
// John Luke (jluke@cfl.rr.com)
|
|
// Ben Maurer (bmaurer@users.sourceforge.net)
|
|
//
|
|
// Use like this:
|
|
// mono assembler.exe --ecmaspec DIRECTORY --out name
|
|
//
|
|
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Xml.XPath;
|
|
using System.Xml.Xsl;
|
|
using System.Xml;
|
|
using System.Collections.Generic;
|
|
using Lucene.Net.Index;
|
|
using Lucene.Net.Documents;
|
|
|
|
namespace Monodoc.Providers
|
|
{
|
|
public class EcmaSpecProvider : Provider
|
|
{
|
|
string basedir;
|
|
|
|
public EcmaSpecProvider (string base_directory)
|
|
{
|
|
basedir = base_directory;
|
|
if (!Directory.Exists (basedir))
|
|
throw new DirectoryNotFoundException (String.Format ("The directory `{0}' does not exist", basedir));
|
|
}
|
|
|
|
public override void PopulateTree (Tree tree)
|
|
{
|
|
XPathNavigator n = new XPathDocument (Path.Combine (basedir, "toc.xml")).CreateNavigator ();
|
|
n.MoveToRoot ();
|
|
n.MoveToFirstChild ();
|
|
PopulateNode (n.SelectChildren ("node", ""), tree.RootNode);
|
|
}
|
|
|
|
void PopulateNode (XPathNodeIterator nodes, Node treeNode)
|
|
{
|
|
foreach (XPathNavigator n in nodes) {
|
|
string secNumber = n.GetAttribute ("number", "");
|
|
string secName = n.GetAttribute ("name", "");
|
|
|
|
var storage = treeNode.Tree.HelpSource.Storage;
|
|
using (var file = File.OpenRead (Path.Combine (basedir, secNumber + ".xml")))
|
|
storage.Store (secNumber, file);
|
|
|
|
Node thisNode = treeNode.GetOrCreateNode (secNumber + ": " + secName, "ecmaspec:" + secNumber);
|
|
|
|
if (n.HasChildren)
|
|
PopulateNode (n.SelectChildren ("node", ""), thisNode);
|
|
}
|
|
}
|
|
|
|
public override void CloseTree (HelpSource hs, Tree tree)
|
|
{
|
|
}
|
|
}
|
|
|
|
public class EcmaSpecHelpSource : HelpSource
|
|
{
|
|
const string EcmaspecPrefix = "ecmaspec:";
|
|
const string TocPart = "%toc"; // What is returned as TocXml
|
|
const string SpecPart = "%spec"; // What is returned as Ecmaspec
|
|
|
|
public EcmaSpecHelpSource (string base_file, bool create) : base (base_file, create)
|
|
{
|
|
}
|
|
|
|
public override DocumentType GetDocumentTypeForId (string id)
|
|
{
|
|
return id.EndsWith (TocPart) ? DocumentType.TocXml : DocumentType.EcmaSpecXml;
|
|
}
|
|
|
|
public override bool IsGeneratedContent (string id)
|
|
{
|
|
return id == "root:" || id.EndsWith (TocPart);
|
|
}
|
|
|
|
public override bool IsMultiPart (string id, out IEnumerable<string> parts)
|
|
{
|
|
if (id == "root:" || id.EndsWith (TocPart) || id.EndsWith (SpecPart)) {
|
|
parts = null;
|
|
return false;
|
|
}
|
|
parts = MakeMultiPart (id);
|
|
return true;
|
|
}
|
|
|
|
IEnumerable<string> MakeMultiPart (string baseId)
|
|
{
|
|
yield return baseId + SpecPart;
|
|
yield return baseId + TocPart;
|
|
}
|
|
|
|
public override string GetText (string id)
|
|
{
|
|
Node n = id == "root:" ? Tree.RootNode : MatchNode (EcmaspecPrefix + id.Substring (0, id.Length - TocPart.Length));
|
|
if (n == null)
|
|
throw new ArgumentException ("id", string.Format ("{0} -> {1}", id, EcmaspecPrefix + id.Substring (0, id.Length - TocPart.Length)));
|
|
return TreeDumper.ExportToTocXml (n, "C# Language Specification", "In this section:");
|
|
}
|
|
|
|
public override Stream GetHelpStream (string id)
|
|
{
|
|
return id.EndsWith (SpecPart) ? base.GetHelpStream (id.Substring (0, id.IndexOf (SpecPart))) : base.GetHelpStream (id);
|
|
}
|
|
|
|
public override void PopulateSearchableIndex (IndexWriter writer)
|
|
{
|
|
foreach (Node n in Tree.RootNode.ChildNodes)
|
|
AddDocuments (writer, n);
|
|
}
|
|
|
|
protected override string UriPrefix {
|
|
get {
|
|
return EcmaspecPrefix;
|
|
}
|
|
}
|
|
|
|
void AddDocuments (IndexWriter writer, Node node)
|
|
{
|
|
string url = node.PublicUrl;
|
|
Stream file_stream = GetHelpStream (url.Substring (9));
|
|
if (file_stream == null) //Error
|
|
return;
|
|
XmlDocument xdoc = new XmlDocument ();
|
|
xdoc.Load (new XmlTextReader (file_stream));
|
|
|
|
//Obtain the title
|
|
XmlNode nelem = xdoc.DocumentElement;
|
|
string title = nelem.Attributes["number"].Value + ": " + nelem.Attributes["title"].Value;
|
|
|
|
//Obtain the text
|
|
StringBuilder s = new StringBuilder ();
|
|
GetTextNode (nelem, s);
|
|
string text = s.ToString ();
|
|
|
|
//Obtain the examples
|
|
StringBuilder s2 = new StringBuilder ();
|
|
GetExamples (nelem, s2);
|
|
string examples = s2.ToString ();
|
|
|
|
//Write to the Lucene Index all the parts
|
|
SearchableDocument doc = new SearchableDocument ();
|
|
doc.Title = title;
|
|
doc.HotText = title.Substring (title.IndexOf (':'));
|
|
doc.Url = url;
|
|
doc.Text = text;
|
|
doc.Examples = examples;
|
|
writer.AddDocument (doc.LuceneDoc);
|
|
|
|
if (node.IsLeaf)
|
|
return;
|
|
|
|
foreach (Node n in node.ChildNodes)
|
|
AddDocuments (writer, n);
|
|
}
|
|
|
|
void GetTextNode (XmlNode n, StringBuilder s)
|
|
{
|
|
//dont include c# code
|
|
if (n.Name == "code_example")
|
|
return;
|
|
//include all text from nodes
|
|
if (n.NodeType == XmlNodeType.Text)
|
|
s.Append (n.Value);
|
|
|
|
//recursively explore all nodes
|
|
if (n.HasChildNodes)
|
|
foreach (XmlNode n_child in n.ChildNodes)
|
|
GetTextNode (n_child, s);
|
|
}
|
|
|
|
void GetExamples (XmlNode n, StringBuilder s)
|
|
{
|
|
if (n.Name == "code_example") {
|
|
if (n.FirstChild.Name == "#cdata-section")
|
|
s.Append (n.FirstChild.Value);
|
|
} else {
|
|
if (n.HasChildNodes)
|
|
foreach (XmlNode n_child in n.ChildNodes)
|
|
GetExamples (n_child, s);
|
|
}
|
|
}
|
|
}
|
|
}
|