src/doc/commands: clean importation for `commands_base`
[nit.git] / src / doc / static / static_cards.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 # Cards templates for the static documentation
16 module static_cards
17
18 import doc::commands::commands_graph
19 import doc::commands::commands_catalog
20 import doc::commands::commands_docdown
21 import templates_html
22
23 # A card that can be rendered to HTML
24 #
25 # Basically, these cards are templates with additionnal data and behavior.
26 abstract class StaticCard
27 super Template
28
29 # Card title
30 var title: String is writable
31
32 # Card id
33 var id: String is writable
34 end
35
36 # A list of cards
37 class CardList
38 super StaticCard
39
40 # Cards contained in this list
41 var cards = new Array[StaticCard] is writable
42
43 redef fun rendering do
44 addn "<div id='{id}' class='card-list'>"
45 for card in cards do
46 addn card
47 end
48 addn "</div>"
49 end
50 end
51
52 # Doc elements
53
54 # A card that display custom text data
55 class CardText
56 super StaticCard
57 autoinit(content)
58
59 # Custom content from options
60 var content: nullable String is writable
61
62 redef var id = "home"
63 redef var title = "Home"
64
65 redef fun rendering do
66 var content = self.content
67 if content == null then return
68 addn "<div>"
69 addn content
70 addn "</div>"
71 addn "<hr/>"
72 end
73 end
74
75 # A heading section
76 #
77 # It displays an heading at a specific level from 1 to 6.
78 class CardSection
79 super StaticCard
80 autoinit(level, title, subtitle)
81
82 # Section heading level
83 var level: Int is writable
84
85 # Section subtitle
86 var subtitle: nullable String is writable
87
88 redef var id = title.to_cmangle is lazy
89
90 redef fun rendering do
91 addn "<h{level} id='{id}'>{title}</h{level}>"
92 end
93 end
94
95 # A page header
96 class CardPageHeader
97 super CardSection
98 autoinit(title, subtitle)
99
100 redef var level = 2
101
102 redef fun rendering do
103 addn "<div class='page-header'>"
104 super
105 var subtitle = self.subtitle
106 if subtitle != null then
107 addn "<p class='text-muted'>"
108 addn subtitle
109 addn "</p>"
110 end
111 addn "</div>"
112 end
113 end
114
115 # A card that displays a summary of a list of cards
116 class CardSummary
117 super CardList
118 autoinit(no_title)
119
120 redef var id = "summary"
121 redef var title = "Summary"
122
123 # Show the summary title
124 var no_title: Bool = false is optional, writable
125
126 redef fun rendering do
127 if not no_title then
128 addn "<h4>Summary</h4>"
129 end
130 addn "<div class='summary'>"
131 addn " <ul class='list-unstyled'>"
132 var sections = new Array[CardSection]
133 for card in cards do
134 if card isa CardSection then
135 while sections.not_empty and sections.last.level >= card.level do
136 sections.pop
137 end
138 sections.add card
139 end
140 var level = if sections.is_empty then 1 else sections.last.level
141 if not card isa CardSection then level += 1
142 addn "<li><a href='#{card.id}'><h{level}>{card.title}</h{level}></a></li>"
143 end
144 addn " </ul>"
145 addn "</div>"
146 end
147 end
148
149 # A card that displays the summary of a Markdown document
150 class CardMdSummary
151 super CardMDoc
152 autoinit(md_processor, headlines)
153
154 # Markdown processor used to extract and render the content
155 var md_processor: MarkdownProcessor is writable
156
157 # Headlines found in the document
158 var headlines: ArrayMap[String, HeadLine] is writable
159
160 redef var id = "summary"
161 redef var title = "Summary"
162
163 redef fun rendering do
164 addn "<h4>Summary</h4>"
165 addn "<div class='summary'>"
166 addn " <ul class='list-unstyled'>"
167 for id, headline in headlines do
168 var level = headline.level
169 var title = md_processor.process(headline.title)
170 addn "<li><a href='#{id}'><h{level}>{title}</h{level}></a></li>"
171 end
172 addn " </ul>"
173 addn "</div>"
174 end
175 end
176
177 # MEntity related cards
178
179 # A card about a mentity
180 #
181 # It displays the documentation about the model entity.
182 class CardMEntity
183 super StaticCard
184 autoinit(mentity, full_doc)
185
186 # MEntity displayed in this card
187 var mentity: MEntity is writable
188
189 # Render the mentity full documentation?
190 var full_doc = false is optional, writable
191
192 redef var id = mentity.html_id is lazy
193 redef var title = mentity.html_name is lazy
194
195 redef fun rendering do
196 addn """
197 <div id='{{{id}}}' class='card'>
198 <div class='card-left text-center'>
199 {{{mentity.html_icon.write_to_string}}}
200 </div>
201 <div class='card-body'>
202 <h5 class='card-heading'>
203 {{{mentity.html_declaration.write_to_string}}}
204 </h5>
205 <p><small>{{{mentity.html_namespace.write_to_string}}}</small></p>"""
206 var mdoc = mentity.mdoc_or_fallback
207 if mdoc != null then
208 if full_doc then
209 addn mdoc.html_documentation
210 else
211 addn mdoc.html_synopsis
212 end
213 end
214 addn """
215 </div>
216 </div>"""
217 end
218 end
219
220 # A card that displays the content of a MDoc
221 class CardMDoc
222 super CardMEntity
223 autoinit(mentity, mdoc, full_doc)
224
225 # MDoc to display in this card
226 var mdoc: nullable MDoc is writable
227
228 redef fun rendering do
229 var mdoc = self.mdoc
230 if mdoc == null then return
231 addn "<div id='{id}' class='card'>"
232 addn " <div class='card-body nitdoc'>"
233 addn mdoc.html_documentation
234 addn " </div>"
235 addn "</div>"
236 end
237 end
238
239 # A card about the inheritance of a MEntity
240 class CardInheritance
241 super CardMEntity
242
243 # Ancestors list
244 var ancestors: nullable Array[MEntity] is writable
245
246 # Parents list
247 var parents: nullable Array[MEntity] is writable
248
249 # Children list
250 var children: nullable Array[MEntity] is writable
251
252 # Descendants list
253 var descendants: nullable Array[MEntity] is writable
254
255 redef var id = "inh_{super}" is lazy
256 redef var title = "Inheritance" is lazy
257
258 redef fun rendering do
259 var ancestors = self.ancestors
260 var descendants = self.descendants
261 if ancestors == null and parents == null and
262 children == null and descendants == null then return
263
264 addn "<div id='{id}' class='card'>"
265 addn " <div class='card-body'>"
266 if ancestors != null and ancestors.length <= 10 then
267 render_list("Ancestors", ancestors)
268 else
269 render_list("Parents", parents)
270 end
271 if descendants != null and descendants.length <= 10 then
272 render_list("Descendants", descendants)
273 else
274 render_list("Children", children)
275 end
276 addn " </div>"
277 addn "</div>"
278 end
279
280 private fun render_list(title: String, mentities: nullable Array[MEntity]) do
281 if mentities == null or mentities.is_empty then return
282 addn "<h4 id='{id}'>{title}</h4>"
283 addn "<ul class='list-unstyled'>"
284 for mentity in mentities do
285 addn mentity.html_list_item
286 end
287 addn "</ul>"
288 end
289 end
290
291 # A card about the linearization of a MEntity
292 class CardLinearizationList
293 super CardMEntity
294
295 # Linearization cards contained in this list
296 var cards = new Array[CardLinearizationDef] is writable
297
298 redef var id = "lin_{super}" is lazy
299 redef var title = "Linearization" is lazy
300
301 redef fun rendering do
302 if cards.is_empty then return
303
304 addn "<div id='{id}'>"
305 for card in cards do
306 addn card
307 if card == cards.last then break
308 addn "<h4 class='text-muted text-center'>"
309 addn " <span class='glyphicon glyphicon-chevron-up'></span>"
310 addn "</h4>"
311 end
312 addn "</div>"
313 end
314 end
315
316 # A card about a definition in a linearization list
317 class CardLinearizationDef
318 super CardCode
319
320 # Is this card displayed by default?
321 var is_active: Bool = false is optional, writable
322
323 # Link to external code repository
324 #
325 # Used if `node` is null
326 var url: nullable String = null is optional, writable
327
328 redef var id = "def_{super}" is lazy
329 redef var title = mentity.full_name is lazy
330
331 redef fun rendering do
332 var url = self.url
333
334 var cin = if is_active then "in" else ""
335 var active = if is_active then "active" else ""
336 addn """
337 <div class='card {{{active}}}' id='{{{id}}}'>
338 <div class='card-body'>
339 <h5>
340 {{{mentity.html_icon.write_to_string}}}
341 {{{mentity.html_namespace.write_to_string}}}"""
342 if node != null then
343 addn """
344 <div class='btn-bar'>
345 <button class='btn btn-link' data-toggle='collapse'
346 data-target='#{{{mentity.html_id}}}'>
347 <span class='glyphicon glyphicon-console' title='Show code' />
348 </button>
349 </div>"""
350 else if url != null then
351 addn """
352 <div class='btn-bar'>
353 <a class='btn btn-link' href='{{{url}}}'>
354 <span class='glyphicon glyphicon-console' title='Show code' />
355 </a>
356 </div>"""
357 var mdoc = mentity.mdoc
358 if mdoc != null then
359 addn "<br/><br/>"
360 addn mdoc.html_documentation
361 end
362 end
363 addn "</h5>"
364 if node != null then
365 addn """
366 <div id='{{{mentity.html_id}}}' class='collapse {{{cin}}}'>
367 <pre>"""
368 render_code
369 addn """</pre>
370 <span class='text-muted'>{{{mentity.location.to_s}}}</span>
371 </div>"""
372 end
373 addn """
374 </div>
375 </div>"""
376 end
377 end
378
379 # A card that displays the code of a MEntity
380 class CardCode
381 super CardMEntity
382 autoinit(mentity, node)
383
384 # AST node to display in this card
385 var node: nullable ANode is writable
386
387 redef var id = "code_{super}" is lazy
388 redef var title = "Code"
389
390 redef fun rendering do
391 addn "<div id='{id}' class='card'>"
392 addn " <div class='card-body'>"
393
394 if node != null then
395 addn "<pre>"
396 render_code
397 addn "</pre>"
398 end
399 addn "<span class='text-muted'>{mentity.location}</span>"
400
401 addn " </div>"
402 addn "</div>"
403 end
404
405 private fun render_code do
406 var node = self.node
407 if node == null then return
408 var hl = new HtmlightVisitor
409 hl.show_infobox = false
410 hl.highlight_node node
411 addn hl.html
412 end
413 end
414
415 # A card that displays a graph
416 class CardGraph
417 super CardMEntity
418 autoinit(mentity, graph)
419
420 # Graph to display in this card
421 var graph: InheritanceGraph is writable
422
423 redef var id = "graph_{super}" is lazy
424 redef var title = "Graph"
425
426 redef fun rendering do
427 addn "<div id='{id}' class='card'>"
428 addn " <div class='card-body'>"
429 addn " <div class='text-center'>"
430 addn graph.graph.to_svg
431 addn " </div>"
432 addn " </div>"
433 addn "</div>"
434 end
435 end
436
437 # Catalog related cards
438
439 # A card that displays Nit catalog related data
440 abstract class CardCatalog
441 super StaticCard
442 autoinit(catalog)
443
444 # Catalog used to extract the data
445 var catalog: Catalog is writable
446 end
447
448 # A card that displays statistics about a Nit catalog
449 class CardCatalogStats
450 super CardCatalog
451
452 redef var id = "catalog_stats"
453 redef var title = "Stats"
454
455 redef fun rendering do
456 addn "<div id='{id}' class='container-fluid'>"
457 for key, value in catalog.catalog_stats.to_map do
458 addn "<span class='text-muted small'>"
459 addn " <strong>{value}</strong>&nbsp;<span>{key}</span>&nbsp;"
460 addn "</span>"
461 end
462 addn "</div>"
463 addn "<hr/>"
464 end
465 end
466
467 # A card that displays a list of tags
468 class CardCatalogTags
469 super CardCatalog
470
471 redef var id = "catalog_tags"
472 redef var title = "Tags"
473
474 # Sorter to sort tags alphabetically
475 var tags_sorter = new CatalogTagsSorter is writable
476
477 redef fun rendering do
478 var tags = catalog.tag2proj.keys.to_a
479 if tags.is_empty then return
480 tags_sorter.sort(tags)
481
482 addn "<h2 id='{id}'>Tags</h2>"
483 addn "<div class='container-fluid'>"
484 for tag in tags do
485 addn "<div class='col-xs-6 col-sm-3 col-md-2'>"
486 addn " <span class='badge'>{catalog.tag2proj[tag].length}</span>"
487 addn " <a href='tag_{tag.to_cmangle}.html'>{tag}</a>"
488 addn "</div>"
489 end
490 addn "</div>"
491 addn "<hr/>"
492 end
493 end
494
495 # A card that displays a package from a Nit catalog
496 class CardCatalogPackage
497 super CardCatalog
498 super CardMEntity
499 autoinit(catalog, mentity)
500
501 redef var id = "package_{super}" is lazy
502
503 redef fun rendering do
504 var mpackage = self.mentity
505 if not mpackage isa MPackage then return
506
507 addn """
508 <div id='{{{id}}}' class='card'>
509 <div class='card-left text-center'>{{{mpackage.html_icon.write_to_string}}}</div>
510 <div class='card-body' style='width: 75%'>
511 <h5 class='card-heading'>
512 {{{mentity.html_declaration.write_to_string}}}
513 <small>&nbsp;"""
514 for tag in mpackage.metadata.tags do
515 add "<span>"
516 add "<a href='tag_{tag.to_cmangle}.html' class='text-muted'>{tag}</a>"
517 if tag != mpackage.metadata.tags.last then addn ", "
518 add "</span>"
519 end
520 addn """</small>
521 </h5>"""
522 var mdoc = mentity.mdoc_or_fallback
523 if mdoc != null then
524 if full_doc then
525 addn mdoc.html_documentation
526 else
527 addn mdoc.html_synopsis
528 end
529 end
530 addn " </div>"
531 addn " <div class='card-right' style='width: 25%'>"
532 for maintainer in mpackage.metadata.maintainers do
533 addn maintainer.to_html
534 end
535 addn " <br>"
536 var license = mpackage.metadata.license
537 if license != null then
538 addn """
539 <span class='text-muted'>
540 <a href='http://opensource.org/licenses/{{{license}}}' class='text-muted'>
541 {{{license}}}
542 </a>
543 </span>"""
544 end
545 addn " </div>"
546 addn "</div>"
547 end
548 end
549
550 # A card that displays the metadata about a package in the Nit catalog
551 class CardMetadata
552 super CardMEntity
553 autoinit(mentity, metadata, stats, deps, clients)
554
555 # Package metadata to display
556 var metadata: MPackageMetadata is writable
557
558 # Package stats
559 var stats: MPackageStats is writable
560
561 # Package dependencies
562 var deps: Array[MPackage] is writable
563
564 # Package clients
565 var clients: Array[MPackage] is writable
566
567 redef var id = "metadata_{super}" is lazy
568 redef var title = "Metadata"
569
570 redef fun rendering do
571 for maintainer in metadata.maintainers do
572 addn """
573 <p class='lead'>
574 {{{maintainer.to_html}}}
575 </p>"""
576 end
577 var license = metadata.license
578 if license != null then
579 addn """
580 <span class='text-muted'>
581 <a href='http://opensource.org/licenses/{{{license}}}'>{{{license}}}</a>
582 license
583 </span>"""
584 end
585
586 var homepage = metadata.homepage
587 var browse = metadata.browse
588 var issues = metadata.issues
589 if homepage != null or browse != null or issues != null then
590 addn """
591 <h4>Links</h4>
592 <ul class='list-unstyled'>"""
593 if homepage != null then addn "<li><a href='{homepage}'>Homepage</a></li>"
594 if browse != null then addn "<li><a href='{browse}'>Source Code</a></li>"
595 if issues != null then addn "<li><a href='{issues}'>Issues</a></li>"
596 addn "</ul>"
597 end
598
599 var git = metadata.git
600 var last_date = metadata.last_date
601 var first_date = metadata.first_date
602 if git != null then
603 addn """
604 <h4>Git</h4>
605 <ul class='list-unstyled'>
606 <li><a href='{{{git}}}'>{{{git}}}</a></li>
607 </ul>
608 <span class='text-muted'><b>{{{stats.commits}}}</b> commits</span>
609 <br>"""
610 if last_date != null then
611 addn """<b class=text-muted>Last:</b> {{{last_date}}}<br>"""
612 end
613 if first_date != null then
614 addn """<b class=text-muted>First:</b> {{{first_date}}}"""
615 end
616 end
617
618 addn """
619 <h4>Quality</h4>
620 <ul class='list-unstyled'>
621 <li>{{{stats.documentation_score}}}% documented</li>
622 </ul>"""
623
624 if metadata.tags.not_empty then
625 addn "<h4>Tags</h4>"
626 for tag in metadata.tags do
627 addn " <a href='tag_{tag.to_cmangle}.html'>{tag}</a>"
628 if tag != metadata.tags.last then add ", "
629 end
630 end
631
632 if deps.not_empty then
633 addn "<h4>Dependencies</h4>"
634 for dep in deps do
635 add dep.html_link
636 if dep != deps.last then add ", "
637 end
638 end
639
640 if clients.not_empty then
641 addn "<h4>Clients</h4>"
642 for client in clients do
643 add client.html_link
644 if client != clients.last then add ", "
645 end
646 end
647
648 if metadata.contributors.not_empty then
649 addn """
650 <h4>Contributors</h4>
651 <ul class='list-unstyled'>"""
652 for contrib in metadata.contributors do
653 addn """<li>{{{contrib.to_html}}}</li>"""
654 end
655 addn "</ul>"
656 end
657
658 addn """
659 <h4>Stats</h4>
660 <ul class='list-unstyled'>
661 <li>{{{stats.mmodules}}} modules</li>
662 <li>{{{stats.mclasses}}} classes</li>
663 <li>{{{stats.mmethods}}} methods</li>
664 <li>{{{stats.loc}}} loc</li>
665 </ul>"""
666 end
667 end