nitdoc: display constructors list in MClass page
[nit.git] / src / doc / html_templates / html_model.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 # HTML templates for Nit model MEntities.
16 module html_model
17
18 import doc_base
19 import doc_down
20 import html_components
21 import html::bootstrap
22 import ordered_tree
23
24 redef class MEntity
25 # ID used as a HTML unique ID and in file names.
26 #
27 # **Must** match the following (POSIX ERE) regular expression:
28 #
29 # ~~~POSIX ERE
30 # ^[A-Za-z_][A-Za-z0-9._-]*$
31 # ~~~
32 #
33 # That way, the ID is always a valid URI component and a valid XML name.
34 fun nitdoc_id: String is abstract
35
36 # URL of this entity’s Nitdoc page.
37 fun nitdoc_url: String is abstract
38
39 # Returns the mentity name without short signature.
40 #
41 # * MProject: `foo`
42 # * MGroup: `foo`
43 # * MModule: `foo`
44 # * MClass: `Foo[E]`
45 # * MClassDef: `Foo[E]`
46 # * MProperty: `foo(e)`
47 # * MPropdef: `foo(e)`
48 var html_name: String is lazy do return name.html_escape
49
50 # Returns a Link to the mentity `html_url`.
51 #
52 # Example: `<a href="html_url" title="mdoc.short_comment">html_short_name</a>
53 var html_link: Link is lazy do
54 var tpl = new Link(nitdoc_url, html_name)
55 var mdoc = mdoc_or_fallback
56 if mdoc != null then
57 tpl.title = mdoc.short_comment
58 end
59 return tpl
60 end
61
62 # Returns a Link to the mentity `nitdoc_id`.
63 #
64 # Example: `<a href="#nitdoc_id" title="mdoc.short_comment">html_short_name</a>
65 fun html_link_to_anchor: Link do
66 var tpl = new Link("#{nitdoc_id}", html_name)
67 var mdoc = mdoc_or_fallback
68 if mdoc != null then
69 tpl.title = mdoc.short_comment
70 end
71 return tpl
72 end
73
74 # Returns the list of keyword used in `self` declaration.
75 fun html_modifiers: Array[String] is abstract
76
77 # Returns the complete MEntity declaration decorated with HTML.
78 #
79 # * MProject: `project foo`
80 # * MGroup: `group foo`
81 # * MModule: `module foo`
82 # * MClass: `private abstract class Foo[E: Object]`
83 # * MClassDef: `redef class Foo[E]`
84 # * MProperty: `private fun foo(e: Object): Int`
85 # * MPropdef: `redef fun foo(e)`
86 fun html_declaration: Template do
87 var tpl = new Template
88 tpl.add "<span>"
89 tpl.add html_modifiers.join(" ")
90 tpl.add " "
91 tpl.add html_link
92 tpl.add "</span>"
93 return tpl
94 end
95
96 # Returns `self` namespace decorated with HTML links.
97 #
98 # * MProject: `mproject`
99 # * MGroup: `mproject(::group)`
100 # * MModule: `mgroup::mmodule`
101 # * MClass: `mproject::mclass`
102 # * MClassDef: `mmodule::mclassdef`
103 # * MProperty: `mclass::mprop`
104 # * MPropdef: `mclassdef:mpropdef`
105 fun html_namespace: Template is abstract
106
107 # Returns the comment of this MEntity formatted as HTML.
108 var html_comment: nullable Writable is lazy do
109 var mdoc = mdoc_or_fallback
110 if mdoc == null then return null
111 return mdoc.tpl_comment
112 end
113
114 # Returns the comment of this MEntity formatted as HTML.
115 var html_short_comment: nullable Writable is lazy do
116 var mdoc = mdoc_or_fallback
117 if mdoc == null then return null
118 return mdoc.tpl_short_comment
119 end
120
121 # Icon that will be displayed before the title
122 fun html_icon: BSIcon do
123 var icon = new BSIcon("tag")
124 icon.css_classes.add_all(css_classes)
125 return icon
126 end
127
128 # CSS classes used to decorate `self`.
129 #
130 # Mainly used for icons.
131 var css_classes = new Array[String]
132
133 # A li element that can go in a `HTMLList`.
134 fun html_list_item: ListItem do
135 var tpl = new Template
136 tpl.add new DocHTMLLabel.with_classes(css_classes)
137 tpl.add html_link
138 var comment = html_short_comment
139 if comment != null then
140 tpl.add ": "
141 tpl.add comment
142 end
143 return new ListItem(tpl)
144 end
145 end
146
147 redef class MProject
148 redef var nitdoc_id = name.to_cmangle is lazy
149 redef fun nitdoc_url do return root.nitdoc_url
150 redef var html_modifiers = ["project"]
151 redef fun html_namespace do return html_link
152 redef var css_classes = ["public"]
153 end
154
155 redef class MGroup
156 redef var nitdoc_id is lazy do
157 if parent != null then
158 return "{parent.nitdoc_id}__{name.to_cmangle}"
159 end
160 return name.to_cmangle
161 end
162
163 redef fun nitdoc_url do return "group_{nitdoc_id}.html"
164 redef var html_modifiers = ["group"]
165
166 # Depends if `self` is root or not.
167 #
168 # * If root `mproject`.
169 # * Else `mproject::self`.
170 redef fun html_namespace do
171 var tpl = new Template
172 tpl.add mproject.html_namespace
173 if mproject.root != self then
174 tpl.add "::"
175 tpl.add html_link
176 end
177 return tpl
178 end
179
180 redef var css_classes = ["public"]
181 end
182
183 redef class MModule
184 redef var nitdoc_id is lazy do
185 if mgroup != null then
186 if mgroup.mmodules.length == 1 then
187 return "{mgroup.nitdoc_id}-"
188 else
189 return "{mgroup.nitdoc_id}__{name.to_cmangle}"
190 end
191 end
192 return name.to_cmangle
193 end
194
195 redef fun nitdoc_url do return "module_{nitdoc_id}.html"
196 redef var html_modifiers = ["module"]
197
198 # Depends if `self` belongs to a MGroup.
199 #
200 # * If mgroup `mgroup::self`.
201 # * Else `self`.
202 redef fun html_namespace do
203 var tpl = new Template
204 if mgroup != null then
205 tpl.add mgroup.html_namespace
206 tpl.add "::"
207 end
208 tpl.add html_link
209 return tpl
210 end
211
212 redef var css_classes = ["public"]
213 end
214
215 redef class MClass
216 redef var nitdoc_id = "{intro_mmodule.nitdoc_id}__{name.to_cmangle}" is lazy
217 redef fun nitdoc_url do return "class_{nitdoc_id}.html"
218 redef fun mdoc_or_fallback do return intro.mdoc
219
220 # Format: `Foo[E]`
221 redef var html_name is lazy do
222 var tpl = new Template
223 tpl.add name.html_escape
224 if arity > 0 then
225 tpl.add "["
226 var parameter_names = new Array[String]
227 for p in mparameters do
228 parameter_names.add(p.html_name)
229 end
230 tpl.add parameter_names.join(", ")
231 tpl.add "]"
232 end
233 return tpl.write_to_string
234 end
235
236 redef fun html_modifiers do return intro.html_modifiers
237 redef fun html_declaration do return intro.html_declaration
238
239 # Returns `mproject::self`.
240 redef fun html_namespace do
241 var tpl = new Template
242 tpl.add intro_mmodule.mgroup.mproject.html_namespace
243 tpl.add "::<span>"
244 tpl.add html_link
245 tpl.add "</span>"
246 return tpl
247 end
248
249 # Returns `intro.html_short_signature`.
250 fun html_short_signature: Template do return intro.html_short_signature
251
252 # Returns `intro.html_signature`.
253 fun html_signature: Template do return intro.html_signature
254
255 redef fun html_icon do return intro.html_icon
256 redef fun css_classes do return intro.css_classes
257 end
258
259 redef class MClassDef
260 redef var nitdoc_id = "{mmodule.nitdoc_id}__{name.to_cmangle}" is lazy
261 redef fun nitdoc_url do return "{mclass.nitdoc_url}#{nitdoc_id}"
262 redef fun mdoc_or_fallback do return mdoc or else mclass.mdoc_or_fallback
263
264 # Depends if `self` is an intro or not.
265 #
266 # * If intro contains the visibility and kind.
267 # * If redef contains the `redef` keyword and kind.
268 redef fun html_modifiers do
269 var res = new Array[String]
270 if not is_intro then
271 res.add "redef"
272 else
273 if mclass.visibility != public_visibility then
274 res.add mclass.visibility.to_s
275 end
276 end
277 res.add mclass.kind.to_s
278 return res
279 end
280
281 # Depends if `self` is an intro or not.
282 #
283 # For intro: `private abstract class Foo[E: Object]`
284 # For redef: `redef class Foo[E]`
285 redef fun html_declaration do
286 var tpl = new Template
287 tpl.add "<span>"
288 tpl.add html_modifiers.join(" ")
289 tpl.add " "
290 tpl.add html_link
291 if is_intro then
292 tpl.add html_signature
293 else
294 tpl.add html_short_signature
295 end
296 tpl.add "</span>"
297 return tpl
298 end
299
300 # Returns `mmodule::self`
301 redef fun html_namespace do
302 var tpl = new Template
303 tpl.add mmodule.html_namespace
304 tpl.add "::<span>"
305 tpl.add mclass.html_link
306 tpl.add "</span>"
307 return tpl
308 end
309
310 # Returns the MClassDef generic signature without static bounds.
311 fun html_short_signature: Template do
312 var tpl = new Template
313 var mparameters = mclass.mparameters
314 if not mparameters.is_empty then
315 tpl.add "["
316 for i in [0..mparameters.length[ do
317 tpl.add mparameters[i].html_name
318 if i < mparameters.length - 1 then tpl.add ", "
319 end
320 tpl.add "]"
321 end
322 return tpl
323 end
324
325 # Returns the MClassDef generic signature with static bounds.
326 fun html_signature: Template do
327 var tpl = new Template
328 var mparameters = mclass.mparameters
329 if not mparameters.is_empty then
330 tpl.add "["
331 for i in [0..mparameters.length[ do
332 tpl.add "{mparameters[i].html_name}: "
333 tpl.add bound_mtype.arguments[i].html_signature
334 if i < mparameters.length - 1 then tpl.add ", "
335 end
336 tpl.add "]"
337 end
338 return tpl
339 end
340
341 redef fun css_classes do
342 var set = new HashSet[String]
343 if is_intro then set.add "intro"
344 for m in mclass.intro.modifiers do set.add m.to_cmangle
345 for m in modifiers do set.add m.to_cmangle
346 return set.to_a
347 end
348 end
349
350 redef class MProperty
351 redef var nitdoc_id = "{intro_mclassdef.mclass.nitdoc_id}__{name.to_cmangle}" is lazy
352 redef fun nitdoc_url do return "property_{nitdoc_id}.html"
353 redef fun mdoc_or_fallback do return intro.mdoc
354 redef fun html_modifiers do return intro.html_modifiers
355 redef fun html_declaration do return intro.html_declaration
356
357 # Returns `mclass::self`.
358 redef fun html_namespace do
359 var tpl = new Template
360 tpl.add intro_mclassdef.mclass.html_namespace
361 tpl.add "::<span>"
362 tpl.add intro.html_link
363 tpl.add "</span>"
364 return tpl
365 end
366
367 # Returns `intro.html_short_signature`.
368 fun html_short_signature: Template do return intro.html_short_signature
369
370 # Returns `intro.html_signature`.
371 fun html_signature: Template do return intro.html_signature
372
373 redef fun css_classes do return intro.css_classes
374 end
375
376 redef class MPropDef
377 redef var nitdoc_id = "{mclassdef.nitdoc_id}__{name.to_cmangle}" is lazy
378 redef fun nitdoc_url do return "{mproperty.nitdoc_url}#{nitdoc_id}"
379 redef fun mdoc_or_fallback do return mdoc or else mproperty.mdoc_or_fallback
380
381 # Depends if `self` is an intro or not.
382 #
383 # * If intro contains the visibility and kind.
384 # * If redef contains the `redef` keyword and kind.
385 redef fun html_modifiers do
386 var res = new Array[String]
387 if not is_intro then
388 res.add "redef"
389 else
390 if mproperty.visibility != public_visibility then
391 res.add mproperty.visibility.to_s
392 end
393 end
394 return res
395 end
396
397 # Depends if `self` is an intro or not.
398 #
399 # For intro: `private fun foo(e: Object): Bar is abstract`
400 # For redef: `redef fun foo(e) is cached`
401 redef fun html_declaration do
402 var tpl = new Template
403 tpl.add "<span>"
404 tpl.add html_modifiers.join(" ")
405 tpl.add " "
406 if is_intro then
407 tpl.add html_link
408 tpl.add html_signature
409 else
410 tpl.add mproperty.intro.html_link
411 tpl.add html_short_signature
412 end
413 tpl.add "</span>"
414 return tpl
415 end
416
417 # Returns `mclassdef::self`
418 redef fun html_namespace do
419 var tpl = new Template
420 tpl.add mclassdef.html_namespace
421 tpl.add "::"
422 tpl.add html_link
423 return tpl
424 end
425
426 # Returns the MPropdDef signature without static types.
427 fun html_short_signature: Template is abstract
428
429 # Returns the MPropDef signature with static types.
430 fun html_signature: Template is abstract
431
432 redef fun css_classes do
433 var set = new HashSet[String]
434 if is_intro then set.add "intro"
435 for m in mproperty.intro.modifiers do set.add m.to_cmangle
436 for m in modifiers do set.add m.to_cmangle
437 return set.to_a
438 end
439 end
440
441 redef class MAttributeDef
442
443 redef fun html_modifiers do
444 var res = super
445 res.add "var"
446 return res
447 end
448
449 redef fun html_short_signature do return new Template
450
451 redef fun html_signature do
452 var tpl = new Template
453 if static_mtype != null then
454 tpl.add ": "
455 tpl.add static_mtype.html_signature
456 end
457 return tpl
458 end
459 end
460
461 redef class MMethodDef
462
463 # FIXME annotation should be handled in their own way
464 redef fun html_modifiers do
465 if mproperty.is_init then
466 var res = new Array[String]
467 if mproperty.visibility != public_visibility then
468 res.add mproperty.visibility.to_s
469 end
470 return res
471 end
472 var res = super
473 if is_abstract then
474 res.add "abstract"
475 else if is_intern then
476 res.add "intern"
477 end
478 res.add "fun"
479 return res
480 end
481
482 redef fun html_declaration do
483 if mproperty.is_init then
484 var tpl = new Template
485 tpl.add "<span>"
486 tpl.add html_modifiers.join(" ")
487 tpl.add " "
488 tpl.add html_link
489 tpl.add html_signature
490 tpl.add "</span>"
491 return tpl
492 end
493 return super
494 end
495
496 redef fun html_short_signature do
497 if mproperty.is_root_init and new_msignature != null then
498 return new_msignature.html_short_signature
499 end
500 return msignature.html_short_signature
501 end
502
503 redef fun html_signature do
504 if mproperty.is_root_init and new_msignature != null then
505 return new_msignature.html_signature
506 end
507 return msignature.html_signature
508 end
509 end
510
511 redef class MVirtualTypeProp
512 redef fun html_link do return mvirtualtype.html_link
513 end
514
515 redef class MVirtualTypeDef
516
517 redef fun html_modifiers do
518 var res = super
519 res.add "type"
520 return res
521 end
522
523 redef fun html_short_signature do return new Template
524
525 redef fun html_signature do
526 var tpl = new Template
527 if bound == null then return tpl
528 tpl.add ": "
529 tpl.add bound.html_signature
530 return tpl
531 end
532 end
533
534 redef class MType
535 # Returns the signature of this type whithout bounds.
536 fun html_short_signature: Template is abstract
537
538 # Returns the signature of this type.
539 fun html_signature: Template is abstract
540 end
541
542 redef class MClassType
543 redef fun html_link do return mclass.html_link
544 redef fun html_short_signature do return html_link
545 redef fun html_signature do return html_link
546 end
547
548 redef class MNullableType
549
550 redef fun html_short_signature do
551 var tpl = new Template
552 tpl.add "nullable "
553 tpl.add mtype.html_short_signature
554 return tpl
555 end
556
557 redef fun html_signature do
558 var tpl = new Template
559 tpl.add "nullable "
560 tpl.add mtype.html_signature
561 return tpl
562 end
563 end
564
565 redef class MGenericType
566 redef fun html_short_signature do
567 var lnk = html_link
568 var tpl = new Template
569 tpl.add new Link.with_title(lnk.href, mclass.name.html_escape, lnk.title)
570 tpl.add "["
571 for i in [0..arguments.length[ do
572 tpl.add arguments[i].html_short_signature
573 if i < arguments.length - 1 then tpl.add ", "
574 end
575 tpl.add "]"
576 return tpl
577 end
578
579 redef fun html_signature do
580 var lnk = html_link
581 var tpl = new Template
582 tpl.add new Link.with_title(lnk.href, mclass.name.html_escape, lnk.title)
583 tpl.add "["
584 for i in [0..arguments.length[ do
585 tpl.add arguments[i].html_signature
586 if i < arguments.length - 1 then tpl.add ", "
587 end
588 tpl.add "]"
589 return tpl
590 end
591 end
592
593 redef class MParameterType
594 redef fun html_link do
595 return new Link.with_title("{mclass.nitdoc_url}#FT_{name.to_cmangle}", name, "formal type")
596 end
597
598 redef fun html_short_signature do return html_link
599 redef fun html_signature do return html_link
600 end
601
602 redef class MVirtualType
603 redef fun html_link do return mproperty.intro.html_link
604 redef fun html_signature do return html_link
605 end
606
607 redef class MSignature
608
609 redef fun html_short_signature do
610 var tpl = new Template
611 if not mparameters.is_empty then
612 tpl.add "("
613 for i in [0..mparameters.length[ do
614 tpl.add mparameters[i].html_short_signature
615 if i < mparameters.length - 1 then tpl.add ", "
616 end
617 tpl.add ")"
618 end
619 return tpl
620 end
621
622 redef fun html_signature do
623 var tpl = new Template
624 if not mparameters.is_empty then
625 tpl.add "("
626 for i in [0..mparameters.length[ do
627 tpl.add mparameters[i].html_signature
628 if i < mparameters.length - 1 then tpl.add ", "
629 end
630 tpl.add ")"
631 end
632 if return_mtype != null then
633 tpl.add ": "
634 tpl.add return_mtype.html_signature
635 end
636 return tpl
637 end
638 end
639
640 redef class MParameter
641
642 # Returns `self` name and ellipsys if any.
643 fun html_short_signature: Template do
644 var tpl = new Template
645 tpl.add name
646 if is_vararg then tpl.add "..."
647 return tpl
648 end
649
650 # Returns `self` name with it's static type and ellipsys if any.
651 fun html_signature: Template do
652 var tpl = new Template
653 tpl.add "{name}: "
654 tpl.add mtype.html_signature
655 if is_vararg then tpl.add "..."
656 return tpl
657 end
658 end
659
660 redef class ConcernsTree
661 # Render `self` as a hierarchical UnorderedList.
662 fun html_list: UnorderedList do
663 var lst = new UnorderedList
664 lst.css_classes.add "list-unstyled list-definition"
665 for r in roots do
666 var li = r.html_concern_item
667 lst.add_li li
668 build_html_list(r, li)
669 end
670 return lst
671 end
672
673 # Build the html list recursively.
674 private fun build_html_list(e: MConcern, li: ListItem) do
675 if not sub.has_key(e) then return
676 var subs = sub[e]
677 var lst = new UnorderedList
678 lst.css_classes.add "list-unstyled list-definition"
679 for e2 in subs do
680 if e2 isa MGroup and e2.is_root then
681 build_html_list(e2, li)
682 else
683 var sli = e2.html_concern_item
684 lst.add_li sli
685 build_html_list(e2, sli)
686 end
687 end
688 var text = new Template
689 text.add li.text
690 if not lst.is_empty then text.add lst
691 li.text = text
692 end
693 end
694
695 redef class MConcern
696 # Return a li element for `self` that can be displayed in a concern list
697 private fun html_concern_item: ListItem do
698 var lnk = html_link
699 var tpl = new Template
700 tpl.add new Link.with_title("#concern:{nitdoc_id}", lnk.text, lnk.title)
701 var comment = html_short_comment
702 if comment != null then
703 tpl.add ": "
704 tpl.add comment
705 end
706 return new ListItem(tpl)
707 end
708 end
709
710 ################################################################################
711 # Additions to `model_ext`.
712
713 redef class MRawType
714 redef fun html_signature do
715 var tpl = new Template
716
717 for part in parts do
718 if part.target != null then
719 tpl.add part.target.as(not null).html_link
720 else
721 tpl.add part.text.html_escape
722 end
723 end
724 return tpl
725 end
726 end
727
728 redef class MInnerClass
729 redef fun nitdoc_url do return inner.nitdoc_url
730 redef fun html_signature do return inner.html_signature
731 end
732
733 redef class MInnerClassDef
734 redef fun nitdoc_url do return inner.nitdoc_url
735
736 redef fun html_link_to_anchor do return inner.html_link_to_anchor
737 redef fun html_link do return inner.html_link
738 redef fun html_signature do return inner.html_signature
739 end