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