ni_nitdoc: Content to Full-Index page
[nit.git] / src / ni_nitdoc.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2008 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 module ni_nitdoc
18
19 import model_utils
20 import abstract_compiler
21 import html
22
23 class Nitdoc
24 private var toolcontext: ToolContext
25 private var model: Model
26 private var modelbuilder: ModelBuilder
27 private var mainmodule: MModule
28 private var arguments: Array[String]
29 private var destinationdir: nullable String
30 private var sharedir: nullable String
31
32 private var opt_dir = new OptionString("Directory where doc is generated", "-d", "--dir")
33 private var opt_source = new OptionString("What link for source (%f for filename, %l for first line, %L for last line)", "--source")
34 private var opt_sharedir = new OptionString("Directory containing the nitdoc files", "--sharedir")
35 private var opt_nodot = new OptionBool("Do not generate graphes with graphiviz", "--no-dot")
36
37 init(toolcontext: ToolContext) do
38 # We need a model to collect stufs
39 self.toolcontext = toolcontext
40 self.arguments = toolcontext.option_context.rest
41 toolcontext.option_context.add_option(opt_dir)
42 toolcontext.option_context.add_option(opt_source)
43 toolcontext.option_context.add_option(opt_sharedir)
44 toolcontext.option_context.add_option(opt_nodot)
45 process_options
46
47 if arguments.length < 1 then
48 toolcontext.option_context.usage
49 exit(1)
50 end
51
52 model = new Model
53 modelbuilder = new ModelBuilder(model, toolcontext)
54
55 # Here we load an process std modules
56 var mmodules = modelbuilder.parse_and_build([arguments.first])
57 if mmodules.is_empty then return
58 modelbuilder.full_propdef_semantic_analysis
59 assert mmodules.length == 1
60 self.mainmodule = mmodules.first
61 end
62
63 private fun process_options do
64 if not opt_dir.value is null then
65 destinationdir = opt_dir.value
66 else
67 destinationdir = "nitdoc_directory"
68 end
69 if not opt_sharedir.value is null then
70 sharedir = opt_sharedir.value
71 else
72 var dir = "NIT_DIR".environ
73 if dir.is_empty then
74 dir = "{sys.program_name.dirname}/../share/nitdoc"
75 else
76 dir = "{dir}/share/nitdoc"
77 end
78 sharedir = dir
79 if sharedir is null then
80 print "Error: Cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
81 abort
82 end
83 dir = "{sharedir.to_s}/scripts/js-facilities.js"
84 if sharedir is null then
85 print "Error: Invalid nitdoc share files. Check --sharedir or envvar NIT_DIR"
86 abort
87 end
88 end
89 end
90
91 fun start do
92 if arguments.length == 1 then
93 # Create destination dir if it's necessary
94 if not destinationdir.file_exists then destinationdir.mkdir
95 sys.system("cp -r {sharedir.to_s}/* {destinationdir.to_s}/")
96 overview
97 fullindex
98 end
99 end
100
101 fun overview do
102 var overviewpage = new NitdocOverview.with(modelbuilder.nmodules, self.opt_nodot.value, destinationdir.to_s)
103 overviewpage.save("{destinationdir.to_s}/index.html")
104 end
105
106 fun fullindex do
107 var fullindex = new NitdocFullindex.with(model.mmodules)
108 fullindex.save("{destinationdir.to_s}/full-index.html")
109 end
110
111 end
112
113 class NitdocOverview
114 super NitdocPage
115
116 var amodules: Array[AModule]
117
118 # Init with Array[AModule] to get all ifnormations about each MModule containt in a program
119 # opt_nodot to inform about the graph gen
120 # destination: to know where will be saved dot files
121 init with(modules: Array[AModule], opt_nodot: Bool, destination: String) do
122 self.amodules = modules
123 self.opt_nodot = opt_nodot
124 self.destinationdir = destination
125 end
126
127 redef fun head do
128 super
129 add("title").text("Overview | Nit Standard Library")
130 end
131
132 redef fun header do
133 open("header")
134 open("nav").add_class("main")
135 open("ul")
136 add("li").add_class("current").text("Overview")
137 open("li")
138 add_html("<a href=\"full-index.html\">Full Index</a>")
139 close("li")
140 open("li").attr("id", "liGitHub")
141 open("a").add_class("btn").attr("id", "logGitHub")
142 add("img").attr("id", "imgGitHub").attr("src", "resources/icons/github-icon.png")
143 close("a")
144 open("div").add_class("popover bottom")
145 add("div").add_class("arrow").text(" ")
146 open("div").add_class("githubTitle")
147 add("h3").text("Github Sign In")
148 close("div")
149 open("div")
150 add("label").attr("id", "lbloginGit").text("Username")
151 add("input").attr("id", "loginGit").attr("name", "login").attr("type", "text")
152 open("label").attr("id", "logginMessage").text("Hello ")
153 open("a").attr("id", "githubAccount")
154 add("strong").attr("id", "nickName").text(" ")
155 close("a")
156 close("label")
157 close("div")
158 open("div")
159 add("label").attr("id", "lbpasswordGit").text("Password")
160 add("input").attr("id", "passwordGit").attr("name", "password").attr("type", "password")
161 open("div").attr("id", "listBranches")
162 add("label").attr("id", "lbBranches").text("Branch")
163 add("select").add_class("dropdown").attr("id", "dropBranches").attr("name", "dropBranches").attr("tabindex", "1").text(" ")
164 close("div")
165 close("div")
166 open("div")
167 add("label").attr("id", "lbrepositoryGit").text("Repository")
168 add("input").attr("id", "repositoryGit").attr("name", "repository").attr("type", "text")
169 close("div")
170 open("div")
171 add("label").attr("id", "lbbranchGit").text("Branch")
172 add("input").attr("id", "branchGit").attr("name", "branch").attr("type", "text")
173 close("div")
174 open("div")
175 add("a").attr("id", "signIn").text("Sign In")
176 close("div")
177 close("div")
178 close("li")
179 close("ul")
180 close("nav")
181 close("header")
182 end
183
184 redef fun body do
185 super
186 open("div").add_class("page")
187 open("div").add_class("content fullpage")
188 add("h1").text("Nit Standard Library")
189 open("article").add_class("overview")
190 add_html("<p>Documentation for the standard library of Nit<br />Version jenkins-component=stdlib-19<br />Date: TODAY</p>")
191 close("article")
192 open("article").add_class("overview")
193 add("h2").text("Modules")
194 open("ul")
195 add_modules
196 close("ul")
197 process_generate_dot
198 close("article")
199 close("div")
200 close("div")
201 add("footer").text("Nit standard library. Version jenkins-component=stdlib-19.")
202 end
203
204 fun add_modules do
205 var ls = new List[nullable MModule]
206 for amodule in amodules do
207 var mmodule = amodule.mmodule.public_owner
208 if mmodule != null and not ls.has(mmodule) then
209 open("li")
210 add("a").attr("href", "{mmodule.name}.html").text("{mmodule.to_s} ")
211 add_html(amodule.comment)
212 close("li")
213 ls.add(mmodule)
214 end
215 end
216 end
217
218 fun process_generate_dot do
219 var op = new Buffer
220 op.append("digraph dep \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
221 for amodule in amodules do
222 op.append("\"{amodule.mmodule.name}\"[URL=\"{amodule.mmodule.name}.html\"];\n")
223 for mmodule2 in amodule.mmodule.in_importation.direct_greaters do
224 op.append("\"{amodule.mmodule.name}\"->\"{mmodule2.name}\";\n")
225 end
226 end
227 op.append("\}\n")
228 generate_dot(op.to_s, "dep", "Modules hierarchy")
229 end
230
231 end
232
233 class NitdocFullindex
234 super NitdocPage
235
236 var mmodules: Array[MModule]
237
238 init with(mmodules: Array[MModule]) do
239 self.mmodules = mmodules
240 opt_nodot = false
241 destinationdir = ""
242 end
243
244 redef fun head do
245 super
246 add("title").text("Full Index | Nit Standard Library")
247 end
248
249 redef fun header do
250 open("header")
251 open("nav").add_class("main")
252 open("ul")
253 open("li")
254 add_html("<a href=\"index.html\">Overview</a>")
255 close("li")
256 add("li").add_class("current").text("Full Index")
257 open("li").attr("id", "liGitHub")
258 open("a").add_class("btn").attr("id", "logGitHub")
259 add("img").attr("id", "imgGitHub").attr("src", "resources/icons/github-icon.png")
260 close("a")
261 open("div").add_class("popover bottom")
262 add("div").add_class("arrow").text(" ")
263 open("div").add_class("githubTitle")
264 add("h3").text("Github Sign In")
265 close("div")
266 open("div")
267 add("label").attr("id", "lbloginGit").text("Username")
268 add("input").attr("id", "loginGit").attr("name", "login").attr("type", "text")
269 open("label").attr("id", "logginMessage").text("Hello ")
270 open("a").attr("id", "githubAccount")
271 add("strong").attr("id", "nickName").text(" ")
272 close("a")
273 close("label")
274 close("div")
275 open("div")
276 add("label").attr("id", "lbpasswordGit").text("Password")
277 add("input").attr("id", "passwordGit").attr("name", "password").attr("type", "password")
278 open("div").attr("id", "listBranches")
279 add("label").attr("id", "lbBranches").text("Branch")
280 add("select").add_class("dropdown").attr("id", "dropBranches").attr("name", "dropBranches").attr("tabindex", "1").text(" ")
281 close("div")
282 close("div")
283 open("div")
284 add("label").attr("id", "lbrepositoryGit").text("Repository")
285 add("input").attr("id", "repositoryGit").attr("name", "repository").attr("type", "text")
286 close("div")
287 open("div")
288 add("label").attr("id", "lbbranchGit").text("Branch")
289 add("input").attr("id", "branchGit").attr("name", "branch").attr("type", "text")
290 close("div")
291 open("div")
292 add("a").attr("id", "signIn").text("Sign In")
293 close("div")
294 close("div")
295 close("li")
296 close("ul")
297 close("nav")
298 close("header")
299 end
300
301 redef fun body do
302 super
303 open("div").add_class("page")
304 open("div").add_class("content fullpage")
305 add("h1").text("Full Index")
306 add_content
307 close("div")
308 close("div")
309 add("footer").text("Nit standard library. Version jenkins-component=stdlib-19.")
310 end
311
312 fun add_content do
313 end
314
315 end
316
317 class NitdocPage
318 super HTMLPage
319
320 var opt_nodot: Bool
321 var destinationdir : String
322
323 redef fun head do
324 add("meta").attr("charset", "utf-8")
325 add("script").attr("type", "text/javascript").attr("src", "scripts/jquery-1.7.1.min.js")
326 add("script").attr("type", "text/javascript").attr("src", "quicksearch-list.js")
327 add("script").attr("type", "text/javascript").attr("src", "scripts/js-facilities.js")
328 add("link").attr("rel", "stylesheet").attr("href", "styles/main.css").attr("type", "text/css").attr("media", "screen")
329 end
330
331 redef fun body do header
332 fun header do end
333
334 # Generate a clickable graphviz image using a dot content
335 fun generate_dot(dot: String, name: String, alt: String) do
336 if opt_nodot then return
337 var file = new OFStream.open("{self.destinationdir}/{name}.dot")
338 file.write(dot)
339 file.close
340 sys.system("\{ test -f {self.destinationdir}/{name}.png && test -f {self.destinationdir}/{name}.s.dot && diff {self.destinationdir}/{name}.dot {self.destinationdir}/{name}.s.dot >/dev/null 2>&1 ; \} || \{ cp {self.destinationdir}/{name}.dot {self.destinationdir}/{name}.s.dot && dot -Tpng -o{self.destinationdir}/{name}.png -Tcmapx -o{self.destinationdir}/{name}.map {self.destinationdir}/{name}.s.dot ; \}")
341 open("article").add_class("graph")
342 add("img").attr("src", "{name}.png").attr("usemap", "#{name}").attr("style", "margin:auto").attr("alt", "{alt}")
343 close("article")
344 var fmap = new IFStream.open("{self.destinationdir}/{name}.map")
345 add_html(fmap.read_all)
346 fmap.close
347 end
348
349 end
350
351 redef class AModule
352 private fun comment: String do
353 var ret = ""
354 if n_moduledecl is null or n_moduledecl.n_doc is null then ret
355 if n_moduledecl.n_doc is null then return ""
356 for t in n_moduledecl.n_doc.n_comment do
357 ret += "{t.text.replace("# ", "")}"
358 end
359 return ret
360 end
361
362 private fun short_comment: String do
363 var ret = ""
364 if n_moduledecl != null and n_moduledecl.n_doc != null then
365 var txt = n_moduledecl.n_doc.n_comment.first.text
366 txt = txt.replace("# ", "")
367 txt = txt.replace("\n", "")
368 ret += txt
369 end
370 return ret
371 end
372 end
373
374 # Create a tool context to handle options and paths
375 var toolcontext = new ToolContext
376 toolcontext.process_options
377
378 # Here we launch the nit index
379 var nitdoc = new Nitdoc(toolcontext)
380 nitdoc.start