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