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