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