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