// Miguel de Icaza (miguel@ximian.com)
//
// (C) 2002, Ximian, Inc.
+// Copyright 2003-2011 Novell
+// Copyright 2011 Xamarin Inc
//
// TODO:
// Each node should have a provider link
//
namespace Monodoc {
using System;
+using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Diagnostics;
using System.Configuration;
-using System.Text.RegularExpressions;
+using System.Reflection;
using System.Xml;
using System.Xml.XPath;
using ICSharpCode.SharpZipLib.Zip;
-using Monodoc.Lucene.Net.Index;
-using Monodoc.Lucene.Net.Analysis.Standard;
+using Mono.Lucene.Net.Index;
+using Mono.Lucene.Net.Analysis.Standard;
using Mono.Documentation;
if (other.position < 0)
other.LoadNode ();
- Regex digits = new Regex (@"([\d]+)|([^\d]+)");
- MatchEvaluator eval = delegate (Match m) {
- return (m.Value.Length > 0 && char.IsDigit (m.Value [0]))
- ? m.Value.PadLeft (System.Math.Max (caption.Length, other.caption.Length))
- : m.Value;
- };
- return digits.Replace (caption, eval).CompareTo (digits.Replace (other.caption, eval));
+ var cap1 = caption;
+ var cap2 = other.caption;
+
+ /* Some node (notably from ecmaspec) have number prepended to them
+ * which we need to sort better by padding them to the same number
+ * of digits
+ */
+ if (char.IsDigit (cap1[0]) && char.IsDigit (cap2[0])) {
+ int c1 = cap1.TakeWhile (char.IsDigit).Count ();
+ int c2 = cap2.TakeWhile (char.IsDigit).Count ();
+
+ if (c1 != c2) {
+ cap1 = cap1.PadLeft (cap1.Length + Math.Max (0, c2 - c1), '0');
+ cap2 = cap2.PadLeft (cap2.Length + Math.Max (0, c1 - c2), '0');
+ }
+ }
+
+ return string.Compare (cap1, cap2, StringComparison.OrdinalIgnoreCase);
}
}
int source_id;
DateTime zipFileWriteTime;
string name;
+ string basepath;
TraceLevel trace_level = TraceLevel.Warning;
- bool nozip;
- string base_dir;
+ protected bool nozip;
+ protected string base_dir;
public HelpSource (string base_filename, bool create)
{
this.name = Path.GetFileName (base_filename);
+ this.basepath = Path.GetDirectoryName (base_filename);
tree_filename = base_filename + ".tree";
zip_filename = base_filename + ".zip";
base_dir = XmlDocUtils.GetCacheDirectory (base_filename);
}
}
+ /* This gives the full path of the source/ directory */
+ public string BaseFilePath {
+ get {
+ return basepath;
+ }
+ }
+
public TraceLevel TraceLevel {
get { return trace_level; }
set { trace_level = value; }
}
+
+ public string BaseDir {
+ get {
+ return base_dir;
+ }
+ }
ZipFile zip_file;
{
if (nozip) {
Stream s = File.OpenRead (XmlDocUtils.GetCachedFileName (base_dir, id));
- string url = "monodoc:///" + SourceID + "@" + System.Web.HttpUtility.UrlEncode (id) + "@";
+ string url = "monodoc:///" + SourceID + "@" + Uri.EscapeUriString (id) + "@";
return new XmlTextReader (url, s);
}
ZipEntry entry = zip_file.GetEntry (id);
if (entry != null) {
Stream s = zip_file.GetInputStream (entry);
- string url = "monodoc:///" + SourceID + "@" + System.Web.HttpUtility.UrlEncode (id) + "@";
+ string url = "monodoc:///" + SourceID + "@" + Uri.EscapeUriString (id) + "@";
return new XmlTextReader (url, s);
}
return null;
{
if (nozip) {
Stream s = File.OpenRead (XmlDocUtils.GetCachedFileName (base_dir, id));
- string url = "monodoc:///" + SourceID + "@" + System.Web.HttpUtility.UrlEncode (id) + "@";
+ string url = "monodoc:///" + SourceID + "@" + Uri.EscapeUriString (id) + "@";
XmlReader r = new XmlTextReader (url, s);
XmlDocument ret = new XmlDocument ();
ret.Load (r);
ZipEntry entry = zip_file.GetEntry (id);
if (entry != null) {
Stream s = zip_file.GetInputStream (entry);
- string url = "monodoc:///" + SourceID + "@" + System.Web.HttpUtility.UrlEncode (id) + "@";
+ string url = "monodoc:///" + SourceID + "@" + Uri.EscapeUriString (id) + "@";
XmlReader r = new XmlTextReader (url, s);
XmlDocument ret = new XmlDocument ();
ret.Load (r);
{
return LoadTree (null);
}
+
+ const string MacMonoDocDir = "/Library/Frameworks/Mono.framework/Versions/Current/lib/monodoc";
//
// Loads the tree layout
d.Load (cfgFile);
basedir = d.SelectSingleNode ("config/path").Attributes ["docsPath"].Value;
}
+ // Temporary workaround for developers distributing a monodoc.dll themselves on Mac
+ if (Directory.Exists (MacMonoDocDir)){
+ Console.WriteLine ("MacDir exists");
+ if (!File.Exists (Path.Combine (basedir, "monodoc.xml"))){
+ basedir = MacMonoDocDir;
+ }
+ }
}
- XmlDocument doc = new XmlDocument ();
- RootTree root = new RootTree ();
- root.basedir = basedir;
-
//
// Load the layout
//
+ XmlDocument doc = new XmlDocument ();
string layout = Path.Combine (basedir, "monodoc.xml");
doc.Load (layout);
- XmlNodeList nodes = doc.SelectNodes ("/node/node");
+
+ string osxExternalDir = "/Library/Frameworks/Mono.framework/External/monodoc";
+ string[] osxExternalSources = Directory.Exists (osxExternalDir)
+ ? Directory.GetFiles (osxExternalDir, "*.source")
+ : new string[0];
+
+ return LoadTree (basedir, doc,
+ Directory.GetFiles (Path.Combine (basedir, "sources"), "*.source")
+ .Concat (osxExternalSources));
+ }
+
+ // Compatibility shim w/ Mono 2.6
+ public static RootTree LoadTree (string indexDir, XmlDocument docTree, IEnumerable sourceFiles)
+ {
+ return LoadTree (indexDir, docTree, sourceFiles.Cast<string>());
+ }
+
+ public static RootTree LoadTree (string indexDir, XmlDocument docTree, IEnumerable<string> sourceFiles)
+ {
+ if (docTree == null) {
+ docTree = new XmlDocument ();
+ using (var defTree = typeof(RootTree).Assembly.GetManifestResourceStream ("monodoc.xml"))
+ docTree.Load (defTree);
+ }
+
+
+ sourceFiles = sourceFiles ?? new string [0];
+
+ //
+ // Load the layout
+ //
+
+ RootTree root = new RootTree ();
+ root.basedir = indexDir;
+
+ XmlNodeList nodes = docTree.SelectNodes ("/node/node");
root.name_to_node ["root"] = root;
root.name_to_node ["libraries"] = root;
//
// Load the sources
//
- root.AddSource (Path.Combine (basedir, "sources"));
+ foreach (var sourceFile in sourceFiles)
+ root.AddSourceFile (sourceFile);
foreach (string path in UncompiledHelpSources) {
EcmaUncompiledHelpSource hs = new EcmaUncompiledHelpSource(path);
public void AddSource (string sources_dir)
{
- Node third_party = LookupEntryPoint ("various") ?? this;
-
string [] files = Directory.GetFiles (sources_dir);
foreach (string file in files){
if (!file.EndsWith (".source"))
continue;
+ AddSourceFile (file);
+ }
+ }
- XmlDocument doc = new XmlDocument ();
- try {
- doc.Load (file);
- } catch {
- Console.Error.WriteLine ("Error: Could not load source file {0}", file);
+ Dictionary<string,string> loadedSourceFiles = new Dictionary<string,string> ();
+
+ public void AddSourceFile (string sourceFile)
+ {
+ if (loadedSourceFiles.ContainsKey (sourceFile))
+ return;
+
+ Node third_party = LookupEntryPoint ("various") ?? this;
+
+ XmlDocument doc = new XmlDocument ();
+ try {
+ doc.Load (sourceFile);
+ }
+ catch {
+ Console.Error.WriteLine ("Error: Could not load source file {0}", sourceFile);
+ return;
+ }
+
+ XmlNodeList extra_nodes = doc.SelectNodes ("/monodoc/node");
+ if (extra_nodes.Count > 0)
+ Populate (third_party, extra_nodes);
+
+ XmlNodeList sources = doc.SelectNodes ("/monodoc/source");
+ if (sources == null){
+ Console.Error.WriteLine ("Error: No <source> section found in the {0} file", sourceFile);
+ return;
+ }
+ loadedSourceFiles [sourceFile] = sourceFile;
+ foreach (XmlNode source in sources){
+ XmlAttribute a = source.Attributes ["provider"];
+ if (a == null){
+ Console.Error.WriteLine ("Error: no provider in <source>");
continue;
}
+ string provider = a.InnerText;
+ a = source.Attributes ["basefile"];
+ if (a == null){
+ Console.Error.WriteLine ("Error: no basefile in <source>");
+ continue;
+ }
+ string basefile = a.InnerText;
+ a = source.Attributes ["path"];
+ if (a == null){
+ Console.Error.WriteLine ("Error: no path in <source>");
+ continue;
+ }
+ string path = a.InnerText;
- XmlNodeList extra_nodes = doc.SelectNodes ("/monodoc/node");
- if (extra_nodes.Count > 0)
- Populate (third_party, extra_nodes);
-
- XmlNodeList sources = doc.SelectNodes ("/monodoc/source");
- if (sources == null){
- Console.Error.WriteLine ("Error: No <source> section found in the {0} file", file);
+ string basefilepath = Path.Combine (Path.GetDirectoryName (sourceFile), basefile);
+ HelpSource hs = GetHelpSource (provider, basefilepath);
+ if (hs == null)
continue;
+ hs.RootTree = this;
+ help_sources.Add (hs);
+ name_to_hs [path] = hs;
+
+ Node parent = LookupEntryPoint (path);
+ if (parent == null){
+ Console.Error.WriteLine ("node `{0}' is not defined on the documentation map", path);
+ parent = third_party;
}
- foreach (XmlNode source in sources){
- XmlAttribute a = source.Attributes ["provider"];
- if (a == null){
- Console.Error.WriteLine ("Error: no provider in <source>");
- continue;
- }
- string provider = a.InnerText;
- a = source.Attributes ["basefile"];
- if (a == null){
- Console.Error.WriteLine ("Error: no basefile in <source>");
- continue;
- }
- string basefile = a.InnerText;
- a = source.Attributes ["path"];
- if (a == null){
- Console.Error.WriteLine ("Error: no path in <source>");
- continue;
- }
- string path = a.InnerText;
-
- string basefilepath = Path.Combine (sources_dir, basefile);
- HelpSource hs = GetHelpSource (provider, basefilepath);
- if (hs == null)
- continue;
- hs.RootTree = this;
- help_sources.Add (hs);
- name_to_hs [path] = hs;
-
- Node parent = LookupEntryPoint (path);
- if (parent == null){
- Console.Error.WriteLine ("node `{0}' is not defined on the documentation map", path);
- parent = third_party;
- }
- foreach (Node n in hs.Tree.Nodes){
- parent.AddNode (n);
- }
- parent.Sort ();
+ foreach (Node n in hs.Tree.Nodes){
+ parent.AddNode (n);
}
+ parent.Sort ();
}
}
return lastHelpSourceTime;
}
}
-
+
public static bool GetNamespaceAndType (string url, out string ns, out string type)
{
int nsidx = -1;
}
if (nsidx == -1) {
- Console.Error.WriteLine ("Did not find dot in: " + url);
ns = null;
type = null;
return false;
sb.Replace ("@@FONT_FAMILY@@", SettingsHandler.Settings.preferred_font_family);
sb.Replace ("@@FONT_SIZE@@", SettingsHandler.Settings.preferred_font_size.ToString());
//contributions
+ var visible = SettingsHandler.Settings.EnableEditing ? "block;" : "none;";
if ((oldContrib + contribs) == 0) {
sb.Replace ("@@CONTRIB_DISP@@", "display: none;");
+ sb.Replace ("@@NO_CONTRIB_DISP@@", "display: " + visible);
} else {
+ sb.Replace ("@@CONTRIB_DISP@@", "display: " + visible);
sb.Replace ("@@NO_CONTRIB_DISP@@", "display: none;");
sb.Replace ("@@CONTRIBS@@", con.ToString ());
}
+ sb.Replace ("@@EDITING_ENABLED@@", "display: " + visible);
// load the url of nodes
String add_str;
public static void MakeIndex ()
{
- RootTree root = LoadTree ();
+ MakeIndex (LoadTree ());
+ }
+
+ public static void MakeIndex (RootTree root)
+ {
if (root == null)
return;
// No octal in C#, how lame is that
chmod (path, 0x1a4);
}
- Console.WriteLine ("Documentation index updated");
+ Console.WriteLine ("Documentation index at {0} updated", path);
}
static bool IsUnix {
}
public static void MakeSearchIndex ()
+ {
+ MakeSearchIndex (LoadTree ());
+ }
+
+ public static void MakeSearchIndex (RootTree root)
{
// Loads the RootTree
Console.WriteLine ("Loading the monodoc tree...");
- RootTree root = LoadTree ();
+
if (root == null)
return;
if (!Directory.Exists (dir))
Directory.CreateDirectory (dir);
- writer = new IndexWriter(Lucene.Net.Store.FSDirectory.GetDirectory(dir, true), new StandardAnalyzer(), true);
+ writer = new IndexWriter(Mono.Lucene.Net.Store.FSDirectory.GetDirectory(dir, true), new StandardAnalyzer(), true);
} catch (UnauthorizedAccessException) {
//try in the .config directory
try {
if (!Directory.Exists (dir))
Directory.CreateDirectory (dir);
- writer = new IndexWriter(Lucene.Net.Store.FSDirectory.GetDirectory(dir, true), new StandardAnalyzer(), true);
+ writer = new IndexWriter(Mono.Lucene.Net.Store.FSDirectory.GetDirectory(dir, true), new StandardAnalyzer(), true);
} catch (UnauthorizedAccessException) {
Console.WriteLine ("You don't have permissions to write on " + dir);
return;