7b157413c22594db13f236138015732f330de68b
[mono.git] / mcs / class / monodoc / Monodoc / generators / HtmlGenerator.cs
1 using System;
2 using System.IO;
3 using System.Text;
4 using System.Linq;
5 using System.Collections.Generic;
6
7 using Monodoc;
8
9 namespace Monodoc.Generators
10 {
11         using Html;
12
13         interface IHtmlExporter
14         {
15                 string CssCode { get; }
16                 string Export (Stream input, Dictionary<string, string> extras);
17                 string Export (string input, Dictionary<string, string> extras);
18         }
19
20         public class HtmlGenerator : IDocGenerator<string>
21         {
22                 const string cachePrefix = "htmlcached#";
23
24                 static string css_code;
25
26                 IDocCache defaultCache;
27                 static Dictionary<DocumentType, IHtmlExporter> converters;
28
29                 static HtmlGenerator ()
30                 {
31                         converters = new Dictionary<DocumentType, IHtmlExporter> {
32                                 { DocumentType.EcmaXml, new Ecma2Html () },
33                                 { DocumentType.Man, new Man2Html () },
34                                 { DocumentType.TocXml, new Toc2Html () },
35                                 { DocumentType.EcmaSpecXml, new Ecmaspec2Html () },
36                                 { DocumentType.ErrorXml, new Error2Html () },
37                                 { DocumentType.Html, new Idem () },
38                                 { DocumentType.MonoBook, new MonoBook2Html () },
39                                 { DocumentType.AddinXml, new Addin2Html () },
40                                 { DocumentType.PlainText, new Idem () },
41                         };
42                 }
43
44                 public HtmlGenerator (IDocCache defaultCache)
45                 {
46                         this.defaultCache = defaultCache;
47                 }
48
49                 public string Generate (HelpSource hs, string id, Dictionary<string, string> context)
50                 {
51                         string specialPage = null;
52                         if (context != null && context.TryGetValue ("specialpage", out specialPage) && specialPage == "master-root")
53                                 return GenerateMasterRootPage (hs != null ? hs.RootTree : null);
54
55                         if (id == "root:" && hs == null)
56                                 return MakeEmptySummary ();
57
58                         if (hs == null || string.IsNullOrEmpty (id))
59                                 return MakeHtmlError (string.Format ("Your request has found no candidate provider [hs=\"{0}\", id=\"{1}\"]",
60                                                                      hs == null ? "(null)" : hs.Name, id ?? "(null)"));
61
62                         var cache = defaultCache ?? hs.Cache;
63                         if (cache != null && cache.IsCached (MakeCacheKey (hs, id, null)))
64                                 return cache.GetCachedString (MakeCacheKey (hs, id, null));
65
66                         IEnumerable<string> parts;
67                         if (hs.IsMultiPart (id, out parts))
68                                 return GenerateMultiPart (hs, parts, id, context);
69
70                         if (hs.IsRawContent (id))
71                                 return hs.GetText (id) ?? string.Empty;
72
73                         DocumentType type = hs.GetDocumentTypeForId (id);
74                         if (cache != null && context != null && cache.IsCached (MakeCacheKey (hs, id, context)))
75                                 return cache.GetCachedString (MakeCacheKey (hs, id, context));
76
77                         IHtmlExporter exporter;
78                         if (!converters.TryGetValue (type, out exporter))
79                                 return MakeHtmlError (string.Format ("Input type '{0}' not supported",
80                                                                      type.ToString ()));
81                         var result = hs.IsGeneratedContent (id) ? 
82                                 exporter.Export (hs.GetCachedText (id), context) :
83                                 exporter.Export (hs.GetCachedHelpStream (id), context);
84
85                         if (cache != null)
86                                 cache.CacheText (MakeCacheKey (hs, id, context), result);
87                         return result;
88                 }
89
90                 string GenerateMultiPart (HelpSource hs, IEnumerable<string> ids, string originalId, Dictionary<string, string> context)
91                 {
92                         var sb = new StringBuilder ();
93                         foreach (var id in ids)
94                                 sb.AppendLine (Generate (hs, id, context));
95
96                         var cache = defaultCache ?? hs.Cache;
97                         if (cache != null)
98                                 cache.CacheText (MakeCacheKey (hs, originalId, null), sb.ToString ());
99                         return sb.ToString ();
100                 }
101
102                 string GenerateMasterRootPage (RootTree rootTree)
103                 {
104                         if (rootTree == null)
105                                 return string.Empty;
106                         var assembly = System.Reflection.Assembly.GetAssembly (typeof (HtmlGenerator));
107                         var hpStream = assembly.GetManifestResourceStream ("home.html");
108                         var home = new StreamReader (hpStream).ReadToEnd ();
109                         var links = string.Join (Environment.NewLine,
110                                                  rootTree.RootNode.ChildNodes.Select (n => string.Format ("<li><a href=\"{0}\">{1}</a></li>", n.Element, n.Caption)));
111                         return home.Replace ("@@API_DOCS@@", links);
112                 }
113
114                 public static string InlineCss {
115                         get {
116                                 if (css_code != null)
117                                         return css_code;
118
119                                 System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly (typeof (HtmlGenerator));
120                                 Stream str_css = assembly.GetManifestResourceStream ("base.css");
121                                 StringBuilder sb = new StringBuilder ((new StreamReader (str_css)).ReadToEnd());
122                                 sb.Replace ("@@FONT_FAMILY@@", "Sans Serif");
123                                 sb.Replace ("@@FONT_SIZE@@", "100%");
124                                 css_code = sb.ToString () + converters.Values
125                                         .Select (c => c.CssCode)
126                                         .Where (css => !string.IsNullOrEmpty (css))
127                                         .DefaultIfEmpty (string.Empty)
128                                         .Aggregate (string.Concat);
129                                 return css_code;
130                         }
131                         set { 
132                                 css_code = value;
133                         }
134                 }
135
136                 string MakeHtmlError (string error)
137                 {
138                         return string.Format ("<html><head></head><body><p><em>Error:</em> {0}</p></body></html>", error);
139                 }
140
141                 string MakeEmptySummary ()
142                 {
143                         return @"<html><head></head><body><p><em>This node doesn't have a summary available</p></body></html>";
144                 }
145
146                 string MakeCacheKey (HelpSource hs, string page, IDictionary<string,string> extraParams)
147                 {
148                         var key = cachePrefix + hs.SourceID + page;
149                         if (extraParams != null && extraParams.Count > 0) {
150                                 var paramPart = string.Join ("-", extraParams.Select (kvp => kvp.Key + kvp.Value));
151                                 key += '_' + paramPart;
152                         }
153                         return key;
154                 }
155         }
156 }