src/web: use full_name instead of html_raw_namespace
[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 # 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 var new_msignature = self.new_msignature
476 if mproperty.is_root_init and new_msignature != null then
477 return new_msignature.html_short_signature
478 end
479 return msignature.as(not null).html_short_signature
480 end
481
482 redef fun html_signature do
483 var new_msignature = self.new_msignature
484 if mproperty.is_root_init and new_msignature != null then
485 return new_msignature.html_signature
486 end
487 return msignature.as(not null).html_signature
488 end
489 end
490
491 redef class MVirtualTypeProp
492 redef fun html_link do return mvirtualtype.html_link
493 end
494
495 redef class MVirtualTypeDef
496
497 redef fun html_modifiers do
498 var res = super
499 res.add "type"
500 return res
501 end
502
503 redef fun html_short_signature do return new Template
504
505 redef fun html_signature do
506 var bound = self.bound
507 var tpl = new Template
508 if bound == null then return tpl
509 tpl.add ": "
510 tpl.add bound.html_signature
511 return tpl
512 end
513 end
514
515 redef class MType
516 # Returns the signature of this type whithout bounds.
517 fun html_short_signature: Template is abstract
518
519 # Returns the signature of this type.
520 fun html_signature: Template is abstract
521 end
522
523 redef class MClassType
524 redef fun html_link do return mclass.html_link
525 redef fun html_short_signature do return html_link
526 redef fun html_signature do return html_link
527 end
528
529 redef class MNullableType
530 redef fun html_short_signature do
531 var tpl = new Template
532 tpl.add "nullable "
533 tpl.add mtype.html_short_signature
534 return tpl
535 end
536
537 redef fun html_signature do
538 var tpl = new Template
539 tpl.add "nullable "
540 tpl.add mtype.html_signature
541 return tpl
542 end
543 end
544
545 redef class MGenericType
546 redef fun html_short_signature do
547 var lnk = html_link
548 var tpl = new Template
549 tpl.add new Link.with_title(lnk.href, mclass.name.html_escape, lnk.title)
550 tpl.add "["
551 for i in [0..arguments.length[ do
552 tpl.add arguments[i].html_short_signature
553 if i < arguments.length - 1 then tpl.add ", "
554 end
555 tpl.add "]"
556 return tpl
557 end
558
559 redef fun html_signature do
560 var lnk = html_link
561 var tpl = new Template
562 tpl.add new Link.with_title(lnk.href, mclass.name.html_escape, lnk.title)
563 tpl.add "["
564 for i in [0..arguments.length[ do
565 tpl.add arguments[i].html_signature
566 if i < arguments.length - 1 then tpl.add ", "
567 end
568 tpl.add "]"
569 return tpl
570 end
571 end
572
573 redef class MParameterType
574 redef fun html_short_signature do return html_link
575 redef fun html_signature do return html_link
576 end
577
578 redef class MVirtualType
579 redef fun html_signature do return html_link
580 end
581
582 redef class MSignature
583 redef fun html_short_signature do
584 var tpl = new Template
585 if not mparameters.is_empty then
586 tpl.add "("
587 for i in [0..mparameters.length[ do
588 tpl.add mparameters[i].html_short_signature
589 if i < mparameters.length - 1 then tpl.add ", "
590 end
591 tpl.add ")"
592 end
593 return tpl
594 end
595
596 redef fun html_signature do
597 var tpl = new Template
598 if not mparameters.is_empty then
599 tpl.add "("
600 for i in [0..mparameters.length[ do
601 tpl.add mparameters[i].html_signature
602 if i < mparameters.length - 1 then tpl.add ", "
603 end
604 tpl.add ")"
605 end
606 var return_mtype = self.return_mtype
607 if return_mtype != null then
608 tpl.add ": "
609 tpl.add return_mtype.html_signature
610 end
611 return tpl
612 end
613 end
614
615 redef class MParameter
616
617 # Returns `self` name and ellipsys if any.
618 fun html_short_signature: Template do
619 var tpl = new Template
620 tpl.add name
621 if is_vararg then tpl.add "..."
622 return tpl
623 end
624
625 # Returns `self` name with it's static type and ellipsys if any.
626 fun html_signature: Template do
627 var tpl = new Template
628 tpl.add "{name}: "
629 tpl.add mtype.html_signature
630 if is_vararg then tpl.add "..."
631 return tpl
632 end
633 end
634
635 redef class MEntityTree
636 # Render `self` as a hierarchical UnorderedList.
637 fun html_list: UnorderedList do
638 var lst = new_unordered_list
639 for r in roots do
640 var li = new_mentity_item(r)
641 lst.add_li li
642 build_html_list(r, li)
643 end
644 return lst
645 end
646
647 # Build the html list recursively.
648 private fun build_html_list(e: MEntity, li: ListItem) do
649 if not sub.has_key(e) then return
650 var subs = sub[e]
651 var lst = new_unordered_list
652 for e2 in subs do
653 if e2 isa MGroup and e2.is_root then
654 build_html_list(e2, li)
655 else
656 var sli = new_mentity_item(e2)
657 lst.add_li sli
658 build_html_list(e2, sli)
659 end
660 end
661 var text = new Template
662 text.add li.text
663 if not lst.is_empty then text.add lst
664 li.text = text
665 end
666
667 # HTML unordered List used to compose the tree.
668 #
669 # Redefine this method to add custom CSS classes or other html attributes.
670 protected fun new_unordered_list: UnorderedList do return new UnorderedList
671
672 # Return a li element for `mconcern` that can be displayed in a concern list
673 protected fun new_mentity_item(mentity: MEntity): ListItem do
674 var tpl = new Template
675 tpl.add mentity.html_link
676 var comment = mentity.html_synopsis
677 if comment != null then
678 tpl.add ": "
679 tpl.add comment
680 end
681 return new ListItem(tpl)
682 end
683 end