src/doc: move rendering from old templates to new phases
[nit.git] / src / doc / html_templates / html_components.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 used by Nitdoc to generate API documentation
16 # Pages are assembled using `Template`
17 module html_components
18
19 import doc_base
20 import html::bootstrap
21 import json::static
22
23 # A label with a text content.
24 class DocHTMLLabel
25 super BSLabel
26
27 redef init do
28 css_classes.clear
29 css_classes.add "label"
30 end
31
32 # Init this label from css classes.
33 init with_classes(classes: Array[String]) do
34 init("label", "")
35 css_classes.add_all classes
36 end
37 end
38
39 #########################
40 # general layout elements
41 #########################
42
43 # Something that can go in a section
44 # Sections are automatically collected to populate the menu
45 class TplSectionElt
46 super Template
47
48 # HTML anchor id
49 var id: String
50
51 # Title to display if any
52 # if both `title` and `summary_title` are null then
53 # the section will not appear in the summary
54 var title: nullable Writable = null is writable
55
56 # Subtitle to display if any
57 var subtitle: nullable Writable = null is writable
58
59 # Title that appear in the summary
60 # if null use `title` instead
61 var summary_title: nullable String = null is writable
62
63 # CSS classes to apply on the section element
64 var css_classes = new Array[String]
65
66 # CSS classes to apply on the title heading element
67 var title_classes = new Array[String]
68
69 # Parent article/section if any
70 var parent: nullable TplSectionElt = null
71
72 init with_title(id: String, title: Writable) do
73 init(id)
74 self.title = title
75 end
76
77 # Level <hX> for HTML heading
78 protected fun hlvl: Int do
79 if parent == null then return 1
80 return parent.hlvl + 1
81 end
82
83 # Elements contained by this section
84 var children = new Array[TplSectionElt]
85
86 # Add an element in this section
87 fun add_child(child: TplSectionElt) do
88 child.parent = self
89 children.add child
90 end
91
92 # Is the section empty (no content at all)
93 fun is_empty: Bool do return children.is_empty
94 end
95
96 # A HTML <section> element
97 class TplSection
98 super TplSectionElt
99
100 redef fun rendering do
101 addn "<section id='{id}' class='{css_classes.join(" ")}'>"
102 if title != null then
103 var lvl = hlvl
104 if lvl == 2 then title_classes.add "well well-sm"
105 addn "<h{lvl} class='{title_classes.join(" ")}'>"
106 addn title.as(not null)
107 addn "</h{lvl}>"
108 end
109 if subtitle != null then
110 addn "<div class='info subtitle'>"
111 addn subtitle.as(not null)
112 addn "</div>"
113 end
114 for child in children do
115 add child
116 end
117 addn "</section>"
118 end
119 end
120
121 # A page article that can go in a section
122 class TplArticle
123 super TplSectionElt
124
125 # Content for this article
126 var content: nullable Writable = null is writable
127 var source_link: nullable Writable = null is writable
128
129 init with_content(id: String, title: Writable, content: Writable) do
130 with_title(id, title)
131 self.content = content
132 end
133
134 redef fun rendering do
135 if is_empty then return
136 addn "<article id='{id}' class='{css_classes.join(" ")}'>"
137 if source_link != null then
138 add "<div class='source-link'>"
139 add source_link.as(not null)
140 addn "</div>"
141 end
142 if title != null then
143 var lvl = hlvl
144 if lvl == 2 then title_classes.add "well well-sm"
145 add "<h{lvl} class='{title_classes.join(" ")}'>"
146 add title.as(not null)
147 addn "</h{lvl}>"
148 end
149 if subtitle != null then
150 add "<div class='info subtitle'>"
151 add subtitle.as(not null)
152 addn "</div>"
153 end
154 if content != null then
155 add content.as(not null)
156 end
157 for child in children do
158 add child
159 end
160 addn """</article>"""
161 end
162
163 redef fun is_empty: Bool do
164 return title == null and subtitle == null and content == null and children.is_empty
165 end
166 end
167
168 # A module / class / prop definition
169 class TplDefinition
170 super Template
171
172 # Comment to display
173 var comment: nullable Writable = null is writable
174
175 # Namespace for this definition
176 var namespace: nullable Writable = null is writable
177
178 # Location link to display
179 var location: nullable Writable = null is writable
180
181 private fun render_info do
182 addn "<div class='info text-right'>"
183 if namespace != null then
184 if comment == null then
185 add "<span class=\"noComment\">no comment for </span>"
186 end
187 add namespace.as(not null)
188 end
189 if location != null then
190 add " "
191 add location.as(not null)
192 end
193 addn "</div>"
194 end
195
196 private fun render_comment do
197 if comment != null then add comment.as(not null)
198 end
199
200 redef fun rendering do
201 addn "<div class='definition'>"
202 render_comment
203 render_info
204 addn "</div>"
205 end
206 end
207
208 # Class definition
209 class TplClassDefinition
210 super TplDefinition
211
212 var intros = new Array[TplListElt]
213 var redefs = new Array[TplListElt]
214
215 redef fun rendering do
216 addn "<div class='definition'>"
217 render_comment
218 render_info
219 render_list("Introduces", intros)
220 render_list("Redefines", redefs)
221 addn "</div>"
222 end
223
224 private fun render_list(name: String, elts: Array[TplListElt]) do
225 if elts.is_empty then return
226 addn "<h5>{name.html_escape}</h5>"
227 addn "<ul class='list-unstyled list-definition'>"
228 for elt in elts do add elt
229 addn "</ul>"
230 end
231 end
232
233 # Layout for Search page
234 class TplSearchPage
235 super TplSectionElt
236
237 var modules = new Array[Writable]
238 var classes = new Array[Writable]
239 var props = new Array[Writable]
240
241 redef fun rendering do
242 var title = self.title
243 if title != null then addn "<h1>{title.to_s.html_escape}</h1>"
244 addn "<div class='container-fluid'>"
245 addn " <div class='row'>"
246 if not modules.is_empty then
247 addn "<div class='col-xs-4'>"
248 addn "<h3>Modules</h3>"
249 addn "<ul>"
250 for m in modules do
251 add "<li>"
252 add m
253 addn "</li>"
254 end
255 addn "</ul>"
256 addn "</div>"
257 end
258 if not classes.is_empty then
259 addn "<div class='col-xs-4'>"
260 addn "<h3>Classes</h3>"
261 addn "<ul>"
262 for c in classes do
263 add "<li>"
264 add c
265 addn "</li>"
266 end
267 addn "</ul>"
268 addn "</div>"
269 end
270 if not props.is_empty then
271 addn "<div class='col-xs-4'>"
272 addn "<h3>Properties</h3>"
273 addn "<ul>"
274 for p in props do
275 add "<li>"
276 add p
277 addn "</li>"
278 end
279 addn "</ul>"
280 addn "</div>"
281 end
282 addn " </div>"
283 addn "</div>"
284 end
285 end
286
287 #####################
288 # Basiv HTML elements
289 #####################
290
291 # A html link <a>
292 class TplLink
293 super Template
294
295 # Link href
296 var href: String is writable
297
298 # The raw HTML content to display in the link
299 var text: Writable is writable
300
301 # The unescaped optional title.
302 var title: nullable String = null is writable
303
304 init with_title(href, text, title: String) do
305 init(href, text)
306 self.title = title
307 end
308
309 redef fun rendering do
310 add "<a href=\""
311 add href.html_escape
312 add "\""
313 if title != null then
314 add " title=\""
315 add title.as(not null).html_escape
316 add "\""
317 end
318 add ">"
319 add text
320 add "</a>"
321 end
322 end
323
324 # A <ul> list
325 class TplList
326 super TplListElt
327
328 # Elements contained in this list
329 # can be <li> or <ul> elements
330 var elts = new Array[TplListElt]
331
332 # CSS classes of the <ul> element
333 var css_classes = new Array[String]
334
335 # Add content wrapped in a <li> element
336 fun add_li(item: TplListItem) do elts.add item
337
338 init with_classes(classes: Array[String]) do self.css_classes = classes
339
340 fun is_empty: Bool do return elts.is_empty
341
342 redef fun rendering do
343 if elts.is_empty then return
344 addn "<ul class='{css_classes.join(" ")}'>"
345 for elt in elts do add elt
346 addn "</ul>"
347 end
348 end
349
350 # Something that can be added to a TplList
351 class TplListElt
352 super Template
353 end
354
355 # A list item <li>
356 class TplListItem
357 super TplListElt
358
359 # Content of the list item
360 var content = new Template
361
362 # CSS classes of the <li> element
363 var css_classes = new Array[String]
364
365 init with_content(content: Writable) do append(content)
366
367 init with_classes(content: Writable, classes: Array[String]) do
368 with_content(content)
369 css_classes = classes
370 end
371
372 # Append `content` to the item
373 # similar to `self.content.add`
374 fun append(content: Writable) do self.content.add content
375
376 redef fun rendering do
377 add "<li class='{css_classes.join(" ")}'>"
378 add content
379 addn "</li>"
380 end
381 end
382
383 # A Bootstrap tab component that contains `TplTabPanel`.
384 class TplTab
385 super Template
386
387 # Panels contained in the tab.
388 var panels = new Array[TplTabPanel]
389
390 # Add a new panel.
391 fun add_panel(panel: TplTabPanel) do panels.add panel
392
393 # CSS classes of the tab component.
394 var css_classes = new Array[String]
395
396 redef fun rendering do
397 addn "<div class='tab-content'>"
398 for panel in panels do add panel
399 addn "</div>"
400 end
401 end
402
403 # A panel that goes in a `TplTab`.
404 class TplTabPanel
405 super Template
406
407 # CSS classes of the pane element.
408 var css_classes = new Array[String]
409
410 # The panel id.
411 #
412 # Used to show/hide panel.
413 var id: String is noinit
414
415 # The panel name.
416 #
417 # Displayed in the tab header or in the pointing link.
418 var name: Writable
419
420 # Is the panel visible by default?
421 var is_active = false is writable
422
423 # Body of the panel
424 var content: nullable Writable = null is writable
425
426 # Get a link pointing to this panel.
427 fun tpl_link_to: Writable do
428 var lnk = new Template
429 lnk.add "<a data-target='#{id}' data-toggle='pill'>"
430 lnk.add name
431 lnk.add "</a>"
432 return lnk
433 end
434
435 redef fun rendering do
436 add "<div class='tab-pane {css_classes.join(" ")}"
437 if is_active then add "active"
438 addn "' id='{id}'>"
439 if content != null then add content.as(not null)
440 addn "</div>"
441 end
442 end
443
444 # A label with a text content
445 class TplLabel
446 super Template
447
448 # Content of the label if any
449 var content: nullable Writable = null is writable
450
451 # CSS classes of the <span> element
452 var css_classes = new Array[String]
453
454 init with_content(content: Writable) do self.content = content
455 init with_classes(classes: Array[String]) do self.css_classes = classes
456
457 redef fun rendering do
458 add "<span class='label {css_classes.join(" ")}'>"
459 if content != null then add content.as(not null)
460 add "</span>"
461 end
462 end
463
464 # A label with an icon
465 class TplIcon
466 super TplLabel
467
468 # Bootsrap icon name
469 # see: http://getbootstrap.com/components/#glyphicons
470 var icon: String
471
472 init with_icon(icon: String) do self.icon = icon
473
474 redef fun rendering do
475 add "<span class='glyphicon glyphicon-{icon} {css_classes.join(" ")}'>"
476 if content != null then add content.as(not null)
477 add "</span>"
478 end
479 end
480
481 # A HTML tag attribute
482 # `<tag attr="value">`
483 #
484 # ~~~nit
485 # var attr: TagAttribute
486 #
487 # attr = new TagAttribute("foo", null)
488 # assert attr.write_to_string == " foo=\"\""
489 #
490 # attr = new TagAttribute("foo", "bar<>")
491 # assert attr.write_to_string == " foo=\"bar&lt;&gt;\""
492 # ~~~
493 class TagAttribute
494 super Template
495
496 var name: String
497 var value: nullable String
498
499 redef fun rendering do
500 var value = self.value
501 if value == null then
502 # SEE: http://www.w3.org/TR/html5/infrastructure.html#boolean-attributes
503 add " {name.html_escape}=\"\""
504 else
505 add " {name.html_escape}=\"{value.html_escape}\""
506 end
507 end
508 end
509
510 # Javacript template
511 class TplScript
512 super Template
513
514 var attrs = new Array[TagAttribute]
515 var content: nullable Writable = null is writable
516
517 init do
518 attrs.add(new TagAttribute("type", "text/javascript"))
519 end
520
521 protected fun render_content do
522 if content != null then add content.as(not null)
523 end
524
525 redef fun rendering do
526 add "<script"
527 for attr in attrs do add attr
528 addn ">"
529 render_content
530 addn "</script>"
531 end
532 end
533
534 # JS script for Piwik Tracker
535 class TplPiwikScript
536 super TplScript
537
538 var tracker_url: String
539 var site_id: String
540
541 redef fun render_content do
542 var site_id = self.site_id.to_json
543 var tracker_url = self.tracker_url.trim
544 if tracker_url.chars.last != '/' then tracker_url += "/"
545 tracker_url = "://{tracker_url}".to_json
546
547 addn "<!-- Piwik -->"
548 addn "var _paq = _paq || [];"
549 addn " _paq.push([\"trackPageView\"]);"
550 addn " _paq.push([\"enableLinkTracking\"]);"
551 addn "(function() \{"
552 addn " var u=((\"https:\" == document.location.protocol) ? \"https\" : \"http\") + {tracker_url};"
553 addn " _paq.push([\"setTrackerUrl\", u+\"piwik.php\"]);"
554 addn " _paq.push([\"setSiteId\", {site_id}]);"
555 addn " var d=document, g=d.createElement(\"script\"), s=d.getElementsByTagName(\"script\")[0]; g.type=\"text/javascript\";"
556 addn " g.defer=true; g.async=true; g.src=u+\"piwik.js\"; s.parentNode.insertBefore(g,s);"
557 addn "\})();"
558 end
559 end