Merge pull request #496 from nicolas-raoul/unit-test-for-issue2907
[mono.git] / mcs / tools / monkeydoc / Monkeydoc / providers / xhtml-provider.cs
1 //
2 // A provider that uses Windows help file xhtml TOC files and looks for the
3 // referenced documents to create the help source. 
4 //
5 // Authors:
6 // Copyright 2003 Lee Mallabone <gnome@fonicmonkey.net>
7 //   Johannes Roith <johannes@roith.de>
8 //   Miguel de Icaza <miguel@ximian.com>
9
10 using System;
11 using System.IO;
12 using System.Collections.Generic;
13 using System.Text;
14 using System.Text.RegularExpressions;
15 using System.Xml;
16
17 namespace MonkeyDoc.Providers
18 {
19         public class XhtmlProvider : Provider
20         {
21                 string tocFile;
22         
23                 public XhtmlProvider (string handbookTocFile)
24                 {
25                         tocFile = handbookTocFile;
26                         if (!File.Exists (tocFile))
27                                 throw new FileNotFoundException (String.Format ("The table of contents, `{0}' does not exist", tocFile));               
28                 }
29
30                 public override void PopulateTree (Tree tree)
31                 {
32                         //new SimpleHandbookTOCParser(tree, tocFile);
33                         // TODO: port it
34                 }
35
36                 public override void CloseTree (HelpSource hs, Tree tree)
37                 {
38                 }
39         }
40
41         public class XhtmlHelpSource : HelpSource
42         {
43                 public XhtmlHelpSource (string base_file, bool create) : base (base_file, create)
44                 {
45
46                 }
47
48                 const string XhtmlPrefix = "xhtml:";
49
50                 protected override string UriPrefix {
51                         get {
52                                 return XhtmlPrefix;
53                         }
54                 }
55                 
56                 public override DocumentType GetDocumentTypeForId (string id, out Dictionary<string, string> extraArgs)
57                 {
58                         extraArgs = null;
59                         return id == "root:" ? DocumentType.TocXml : DocumentType.MonoBook;
60                 }
61
62                 public override bool IsGeneratedContent (string id)
63                 {
64                         return id == "root:";
65                 }
66         
67                 public override string GetText (string url)
68                 {
69                         return TreeDumper.ExportToTocXml (Tree.RootNode, "Mono Handbook", string.Empty);
70                 }
71
72                 public static string GetAbsoluteLink(string target, string url)
73                 {
74                         
75                         string value = null;
76                 
77                         if (target.StartsWith ("#") ||
78                             target.StartsWith ("T:") ||
79                             target.StartsWith ("M:") ||
80                             target.StartsWith ("P:") ||
81                             target.StartsWith ("T:") ||
82                             target.StartsWith ("E:") ||
83                             target.StartsWith ("F:") ||
84                             target.StartsWith ("O:") ||
85                             target.StartsWith ("N:") ||
86                             target.StartsWith ("api:"))
87                                 return null;
88                 
89                         int endp = target.IndexOf(':');
90                 
91                         if (endp == -1)
92                                 endp = 0;
93                         string protocol = target.Substring(0, endp);
94                         switch (protocol) {
95                         case "mailto": 
96                         case "http":
97                         case "https":
98                         case "ftp":
99                         case "news":
100                         case "irc":
101                                 break;
102                         default:
103                                 // handle absolute urls like: /html/en/images/empty.png
104                                 if (!target.StartsWith("/")) {
105                                 
106                                         // url is something like "gnome/bindings/mono.html"
107                                         // This will get the path "gnome/bindings"
108                                 
109                                         int slash = url.LastIndexOf ("/");
110                                         string tmpurl = url;
111                                 
112                                         if (slash != -1)
113                                                 tmpurl  = url.Substring(0, slash);
114                                 
115                                         // Count "../" in target and go one level down
116                                         // for each in tmpurl, eventually, then remove "../".
117                                 
118                                         Regex reg1 = new Regex("../");
119                                         MatchCollection matches = reg1.Matches(target);
120                                 
121                                         for(int i = 1; i < matches.Count; i++) {
122                                                 slash = tmpurl.LastIndexOf ("/");
123                                                 if (slash != -1) 
124                                                         tmpurl  = tmpurl.Substring(0, slash);
125                                         }
126                                 
127                                         target = target.Replace("../", "");
128                                 
129                                         value = tmpurl + "/" + target;
130                                 
131                                 } else {
132                                         value = target.Substring(1, target.Length - 1);
133                                 }
134                                 break;
135                         }
136                         return value;
137                 }
138         
139                 XmlDocument RewriteLinks(XmlDocument docToProcess, string url)
140                 {
141                         XmlNodeList nodeList = docToProcess.GetElementsByTagName("a");
142                 
143                         foreach(XmlNode node in nodeList) {
144                         
145                                 XmlElement element = (XmlElement) node;
146                         
147                                 if (element.HasAttribute("href") ){
148                                 
149                                         XmlAttribute href = element.GetAttributeNode("href");
150                                         string target = href.Value;
151                                 
152                                         target = GetAbsoluteLink(target, url);
153                                         if (target != null) {
154                                                 string newtarget = String.Format ("source-id:{0}:xhtml:{1}", SourceID, target);
155                                                 href.Value = newtarget;
156                                         }
157                                 }
158                         }
159
160                         nodeList = docToProcess.GetElementsByTagName("img");
161
162                         foreach(XmlNode node in nodeList) {
163                                                                                                                                     
164                                 XmlElement element = (XmlElement) node;
165                                                                                                                                     
166                                 if (element.HasAttribute("src") ){
167                                                                                                                                     
168                                         XmlAttribute href = element.GetAttributeNode("src");
169                                         string target = href.Value;
170                                                                                                                                     
171                                         target = GetAbsoluteLink(target, url);
172                                         if (target != null) {
173                                                 string newtarget = String.Format ("source-id:{0}:xhtml:{1}", SourceID, target);
174                                                 href.Value = newtarget;
175                                         }
176                                 }               
177                         }
178
179                         return docToProcess;
180                 }
181
182                 public override void PopulateIndex (IndexMaker index_maker)
183                 {
184                         PopulateIndexFromNodes (Tree.RootNode);
185                 }
186
187                 void PopulateIndexFromNodes (Node start)
188                 {
189                         var nodes = start.Nodes;
190                 
191                         if (nodes == null)
192                                 Console.WriteLine ("Leaf: " + start.Caption);
193                         else {
194                                 Console.WriteLine ("Root: " + start.Caption);
195                                 foreach (Node n in nodes)
196                                         PopulateIndexFromNodes (n);
197                         }
198                 }
199         }
200 }