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