Merge: Contract implementation
[nit.git] / src / doc / static / static_structure.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Composes the pages of the static documentation
16 module static_structure
17
18 import static::static_base
19
20 redef class DocPage
21
22 # Create the structure of this page
23 fun apply_structure(doc: DocModel) do end
24 end
25
26 redef class PageHome
27 redef fun apply_structure(doc) do
28 var title = doc.custom_title or else "Welcome to Nitdoc!"
29 var intro = doc.custom_intro
30
31 if intro != null then
32 main_tab.content.add new CardPageHeader(title)
33 main_tab.content.add new CardText(intro)
34 else
35 main_tab.content.add new CardPageHeader(title, "The Nit API documentation.")
36 end
37
38 main_tab.content.add new CardCatalogStats(doc.catalog)
39 main_tab.content.add new CardCatalogTags(doc.catalog)
40
41 main_tab.content.add new CardSection(2, "Packages")
42 var mpackages_sorter = new CatalogScoreSorter(doc.catalog)
43
44 var mpackages = doc.catalog.mpackages.values.to_a
45 mpackages_sorter.sort mpackages
46 var list = new CardList("packages", "Packages")
47 for mpackage in mpackages do
48 list.cards.add new CardCatalogPackage(doc.catalog, mpackage)
49 end
50 # TODO pagination?
51 main_tab.content.add list
52 end
53 end
54
55 redef class PageMEntity
56 # Concerns to display in this page.
57 var concerns: nullable ConcernsTree = null
58
59 redef fun apply_structure(doc) do
60 build_main(doc)
61 build_api(doc)
62 build_dependencies(doc)
63 end
64
65 # Build the main tab (the one that contains the MDoc)
66 fun build_main(doc: DocModel) do
67 var mentity = self.mentity
68
69 var sq = new CmdSummary(doc.model, doc.filter, mentity,
70 markdown_processor = doc.inline_processor)
71 sq.init_command
72
73 main_tab.content.add new CardMDoc(mentity, mentity.mdoc_or_fallback)
74
75 var summary = sq.summary
76 if summary != null then
77 main_tab.sidebar.cards.add new CardMdSummary(headlines = summary, md_processor = doc.inline_processor)
78 end
79 end
80
81 # Build the API tab
82 fun build_api(doc: DocModel) do
83 var summary = new CardSummary
84
85 var title = "All definitions"
86 if mentity isa MPackage then title = "All groups and modules"
87 if mentity isa MGroup then title = "All subgroups and modules"
88 if mentity isa MModule then title = "All class definitions"
89 if mentity isa MClass or mentity isa MClassDef then title = "All properties"
90
91 var section = new CardSection(2, title)
92 api_tab.content.add section
93 summary.cards.add section
94
95 var dq = new CmdFeatures(doc.model, doc.filter, mentity)
96 dq.init_command
97 var mentities = dq.results
98 if mentities == null then return
99
100 var list = new CardList("api", "API")
101 for m in mentities do
102 var card = new CardMEntity(m)
103 card.id = "api_{card.id}" # avoid id conflicts with main tab
104 list.cards.add card
105 summary.cards.add card
106 end
107 api_tab.content.add list
108
109 if summary.cards.not_empty then
110 api_tab.sidebar.cards.add summary
111 end
112 end
113
114 # Build the dependencies tab
115 fun build_dependencies(doc: DocModel) do
116 var summary = new CardSummary
117
118 var model = doc.model
119 var mainmodule = doc.mainmodule
120 var filter = doc.filter
121
122 if not doc.no_dot then
123 var gq = new CmdInheritanceGraph(model, mainmodule, filter, mentity)
124 gq.init_command
125 var graph = gq.graph
126 if graph != null then
127 graph.draw(2, 2)
128 dep_tab.content.add new CardGraph(mentity, graph)
129 end
130 end
131
132 # No inheritance lists for `Object`
133 if mentity isa MClass and mentity.name == "Object" then return
134
135 var inh = new HashMap[String, CmdEntityList]
136 inh["Ancestors"] = new CmdAncestors(model, mainmodule, filter, mentity, parents = false)
137 inh["Parents"] = new CmdParents(model, mainmodule, filter, mentity)
138 inh["Children"] = new CmdChildren(model, mainmodule, filter, mentity)
139 inh["Descendants"] = new CmdDescendants(model, mainmodule, filter, mentity, children = false)
140
141 for title, cmd in inh do
142 cmd.init_command
143 var results = cmd.results
144 if results == null or results.is_empty then continue
145 var section = new CardSection(3, title)
146 dep_tab.content.add section
147 summary.cards.add section
148
149 var list = new CardList("inh", "Inheritance")
150 for mentity in results do
151 var card = new CardMEntity(mentity)
152 list.cards.add card
153 summary.cards.add card
154 end
155 dep_tab.content.add list
156 end
157
158 if summary.cards.not_empty then
159 dep_tab.sidebar.cards.add summary
160 end
161 end
162
163 # Build the code panel
164 fun build_code(doc: DocModel) do
165 var code_url = doc.code_url
166
167 if not doc.no_code then
168 var cq = new CmdEntityCode(doc.model, doc.modelbuilder, doc.filter, mentity)
169 cq.init_command
170
171 var code = cq.node
172 if code == null then return
173 code_tab.content.add new CardCode(mentity, code)
174 else if doc.code_url != null then
175 code_tab = new DocTabLink("code", "Code", "console", mentity.source_url(code_url))
176 end
177 end
178
179 # Build the linearization panel
180 fun build_linearization(doc: DocModel) do
181 var summary = new CardSummary
182
183 var lq = new CmdLinearization(doc.model, doc.mainmodule, doc.filter, mentity)
184 lq.init_command
185
186 var mentities = lq.results
187 if mentities == null then return
188
189 if mentity isa MClass or mentity isa MClassDef then
190 if mentity.name == "Object" then return # No linearization for `Object`
191 if mentity.name == "Sys" then return # No linearization for `Sys`
192 var section = new CardSection(2, "Class definitions")
193 lin_tab.content.add section
194 summary.cards.add section
195 else if mentity isa MProperty or mentity isa MPropDef then
196 if mentity.name == "init" then return # No linearization for `init`
197 if mentity.name == "SELF" then return # No linearization for `SELF`
198 if mentity.name == "to_s" then return # No linearization for `to_s`
199 var section = new CardSection(2, "Property definitions")
200 lin_tab.content.add section
201 summary.cards.add section
202 end
203
204 var list = new CardLinearizationList(mentity)
205 for m in mentities do
206 var url = mentity.source_url(doc.code_url)
207 var node = doc.modelbuilder.mentity2node(m)
208 if node == null then continue
209 if doc.no_code then node = null
210 if m == mentity or
211 (m isa MClassDef and m.is_intro) or
212 (m isa MPropDef and m.is_intro) then
213 var card = new CardLinearizationDef(m, node, is_active = true, url)
214 list.cards.add card
215 summary.cards.add card
216 else
217 var card = new CardLinearizationDef(m, node, is_active = false, url)
218 list.cards.add card
219 summary.cards.add card
220 end
221 end
222 lin_tab.content.add list
223
224 if summary.cards.not_empty then
225 lin_tab.sidebar.cards.add summary
226 end
227 end
228 end
229
230 redef class PageMPackage
231 redef fun build_main(doc) do
232 super
233 main_tab.metadata.cards.add new CardMetadata(mentity, mentity.metadata,
234 doc.catalog.mpackages_stats[mentity],
235 doc.catalog.deps.successors(mentity).to_a,
236 doc.catalog.deps.predecessors(mentity).to_a)
237 end
238 end
239
240 redef class PageMModule
241 redef fun apply_structure(doc) do
242 super
243 build_code(doc)
244 end
245
246 redef fun build_main(doc) do
247 super
248
249 var summary = new CardSummary(no_title = true)
250
251 # Intros
252 var cmd: CmdEntities = new CmdIntros(doc.model, doc.mainmodule, doc.filter, mentity)
253 cmd.init_command
254 var intros = cmd.results
255 if intros != null and intros.not_empty then
256 var section = new CardSection(3, "Introduced classes")
257 main_tab.content.add section
258 summary.cards.add section
259 var cards = new CardList("intros", "Intros")
260 for intro in intros do
261 var card = new CardMEntity(intro)
262 summary.cards.add card
263 cards.cards.add card
264 end
265 main_tab.content.add cards
266 end
267
268 # Redefs
269 cmd = new CmdRedefs(doc.model, doc.mainmodule, doc.filter, mentity)
270 cmd.init_command
271 var redefs = cmd.results
272 if redefs != null and redefs.not_empty then
273 var section = new CardSection(3, "Redefined classes")
274 main_tab.content.add section
275 summary.cards.add section
276 var cards = new CardList("redefs", "Redefs")
277 for prop in redefs do
278 var card = new CardMEntity(prop)
279 summary.cards.add card
280 cards.cards.add card
281 end
282 main_tab.content.add cards
283 end
284
285 main_tab.sidebar.cards.add summary
286 end
287 end
288
289 redef class PageMClass
290 redef fun apply_structure(doc) do
291 super
292 build_code(doc)
293 build_linearization(doc)
294 end
295
296 redef fun build_main(doc) do
297 super
298
299 var summary = new CardSummary(no_title = true)
300
301 # Intros
302 var cmd: CmdEntities = new CmdIntros(doc.model, doc.mainmodule, doc.filter, mentity)
303 cmd.init_command
304 var intros = cmd.results
305 if intros != null and intros.not_empty then
306 var section = new CardSection(3, "Introduced properties")
307 main_tab.content.add section
308 summary.cards.add section
309 var cards = new CardList("intros", "Intros")
310 for intro in intros do
311 var card = new CardMEntity(intro)
312 summary.cards.add card
313 cards.cards.add card
314 end
315 main_tab.content.add cards
316 end
317
318 # Redefs
319 cmd = new CmdRedefs(doc.model, doc.mainmodule, doc.filter, mentity)
320 cmd.init_command
321 var redefs = cmd.results
322 if redefs != null and redefs.not_empty then
323 var section = new CardSection(3, "Redefined properties")
324 main_tab.content.add section
325 summary.cards.add section
326 var cards = new CardList("redefs", "Redefs")
327 for prop in redefs do
328 var card = new CardMEntity(prop)
329 summary.cards.add card
330 cards.cards.add card
331 end
332 main_tab.content.add cards
333 end
334
335 # Expand summary
336 main_tab.sidebar.cards.add summary
337 end
338
339 redef fun build_api(doc) do
340 var summary = new CardSummary
341
342 var section = new CardSection(2, "All properties")
343 api_tab.content.add section
344 summary.cards.add section
345
346 var dq = new CmdAllProps(doc.model, doc.mainmodule, doc.filter, mentity)
347 dq.init_command
348 var mentities = dq.results
349 if mentities == null then return
350
351 var list = new CardList("api", "API")
352 for m in mentities do
353 var card = new CardMEntity(m)
354 list.cards.add card
355 summary.cards.add card
356 end
357 api_tab.content.add list
358
359 if summary.cards.not_empty then
360 api_tab.sidebar.cards.add summary
361 end
362 end
363 end
364
365 redef class PageMProperty
366 redef fun apply_structure(doc) do
367 super
368 build_code(doc)
369 build_linearization(doc)
370 end
371 end
372
373 redef class PagePerson
374 redef fun apply_structure(doc) do
375 var mpackages_sorter = new CatalogScoreSorter(doc.catalog)
376 main_tab.content.add new CardPageHeader(person.name, person.email)
377
378 var maint = doc.catalog.maint2proj[person]
379 mpackages_sorter.sort maint
380 var mlist = new CardList("maintained", "Maintained")
381 for mpackage in maint do
382 mlist.cards.add new CardCatalogPackage(doc.catalog, mpackage)
383 end
384
385 # TODO pagination?
386 if maint.not_empty then
387 main_tab.content.add new CardSection(3, "{maint.length} maintained packages")
388 main_tab.content.add mlist
389 end
390
391 var contrib = doc.catalog.contrib2proj[person]
392 mpackages_sorter.sort contrib
393 var clist = new CardList("contribs", "Contributed")
394 for mpackage in contrib do
395 clist.cards.add new CardCatalogPackage(doc.catalog, mpackage)
396 end
397
398 # TODO pagination?
399 if contrib.not_empty then
400 main_tab.content.add new CardSection(3, "{contrib.length} contributed packages")
401 main_tab.content.add clist
402 end
403 end
404 end
405
406 redef class PageTag
407 redef fun apply_structure(doc) do
408 var mpackages_sorter = new CatalogScoreSorter(doc.catalog)
409 main_tab.content.add new CardPageHeader(tag)
410
411 var mpackages = doc.catalog.tag2proj[tag]
412 mpackages_sorter.sort mpackages
413 var list = new CardList("packages", "Packages")
414 for mpackage in mpackages do
415 list.cards.add new CardCatalogPackage(doc.catalog, mpackage)
416 end
417
418 # TODO pagination?
419 main_tab.content.add new CardSection(3, "{mpackages.length} packages")
420 main_tab.content.add list
421 end
422 end
423
424 redef class MEntity
425 # Render a HTML link for the MEntity location
426 private fun source_url(url_pattern: nullable String): String do
427 var location = self.location
428 var file = location.file
429
430 if file == null then return location.to_s
431 if url_pattern == null then return file.filename.simplify_path
432
433 var url = url_pattern
434 url = url.replace("%f", file.filename.simplify_path)
435 url = url.replace("%l", location.line_start.to_s)
436 url = url.replace("%L", location.line_end.to_s)
437 return url.simplify_path
438 end
439 end