1 # This file is part of NIT ( http://www.nitlanguage.org ).
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
15 # HTML templates used by Nitdoc to generate API documentation
16 # Pages are assembled using `Template`
21 # A documentation page
25 # Page title in HTML header
26 var title
: String is writable, noinit
29 var url
: String is writable, noinit
31 # Directory where css, js and other assets can be found
32 var shareurl
: String is writable, noinit
34 # Attributes of the body tag element
35 var body_attrs
= new Array[TagAttribute]
37 # Top menu template if any
38 var topmenu
: TplTopMenu is writable, noinit
40 # Sidebar template if any
41 var sidebar
: nullable TplSidebar = null is writable
43 # Content of the page in form a TplSection
44 var sections
= new Array[TplSection]
46 # Footer content if any
47 var footer
: nullable Streamable = null is writable
49 # JS scripts to append at the end of the body
50 var scripts
= new Array[TplScript]
54 # Add a section to this page
55 fun add_section
(section
: TplSection) do
59 # Render the html header
60 private fun render_head
do
63 add
" <meta charset='utf-8'/>"
64 add
" <!--link rel='stylesheet' href='{shareurl}/css/Nitdoc.UI.css' type='text/css'/-->"
65 add
" <link rel='stylesheet' href='{shareurl}/vendors/bootstrap/css/bootstrap.min.css'/>"
66 add
" <link rel='stylesheet' href='{shareurl}/css/nitdoc.bootstrap.css'/>"
67 add
" <link rel='stylesheet' href='{shareurl}/css/nitdoc.css'/>"
68 add
" <link rel='stylesheet' href='{shareurl}/css/Nitdoc.QuickSearch.css'/>"
69 add
" <link rel='stylesheet' href='{shareurl}/css/Nitdoc.ModalBox.css'/>"
70 add
" <link rel='stylesheet' href='{shareurl}/css/Nitdoc.GitHub.css'/>"
71 add
" <title>{title}</title>"
74 for attr
in body_attrs
do add attr
78 # Render the topmenu template
79 private fun render_topmenu
do
80 add
" <div class='row'>"
86 # Sidebar is automatically populated with a summary of all sections
88 if sidebar
== null then return
89 var summary
= new TplSummary.with_order
(0)
90 for section
in sections
do
91 section
.render_summary summary
93 sidebar
.boxes
.add summary
94 add sidebar
.as(not null)
96 # Render the footer and content
97 private fun render_content
do
98 for section
in sections
do add section
99 if footer
!= null then
100 add
"<div class='well footer'>"
101 add footer
.as(not null)
107 private fun render_footer
do
108 add
"<script src='{shareurl}/vendors/jquery/jquery-1.11.1.min.js'></script>"
109 add
"<script src='{shareurl}/vendors/jquery/jquery-ui-1.10.4.custom.min.js'></script>"
110 add
"<script src='{shareurl}/vendors/bootstrap/js/bootstrap.min.js'></script>"
111 add
"<script data-main='{shareurl}/js/nitdoc' src='{shareurl}/js/lib/require.js'></script>"
112 for script
in scripts
do add script
115 $("[data-toggle='tooltip']").tooltip();
116 $("[data-toggle='popover']").popover();
123 # Render the whole page
124 redef fun rendering
do
126 add
"<div class='container-fluid'>"
128 add
" <div class='row' id='content'>"
129 if sidebar
!= null then
130 add
"<div class='col col-xs-3 col-lg-2'>"
133 add
"<div class='col col-xs-9 col-lg-10' data-spy='scroll' data-target='.summary'>"
137 add
"<div class='col col-xs-12'>"
147 #########################
148 # general layout elements
149 #########################
151 # Top menu bar template
155 # Brand link to display in first position of the top menu
156 private var brand
: nullable Streamable = null is writable
157 # Elements of the topmenu
158 private var elts
= new Array[Streamable]
160 # The page url where the top menu is displayed.
162 # Used to select the active link.
163 private var current_url
: String
165 init(current_url
: String) do
166 self.current_url
= current_url
169 # Add a new link to the menu.
170 fun add_link
(content
: TplLink) do
171 var is_active
= content
.href
== current_url
172 add_item
(content
, is_active
)
175 # Add a content between `<li>` tags
176 fun add_item
(content
: Streamable, is_active
: Bool) do
177 var tpl
= new Template
180 tpl
.add
" class='active'"
188 # Add a raw content to the menu
189 fun add_raw
(content
: Streamable) do
193 redef fun rendering
do
194 if brand
== null and elts
.is_empty
then return
195 add
"<nav id='topmenu' class='navbar navbar-default navbar-fixed-top' role='navigation'>"
196 add
" <div class='container-fluid'>"
197 add
" <div class='navbar-header'>"
198 add
" <button type='button' class='navbar-toggle' "
199 add
" data-toggle='collapse' data-target='#topmenu-collapse'>"
200 add
" <span class='sr-only'>Toggle menu</span>"
201 add
" <span class='icon-bar'></span>"
202 add
" <span class='icon-bar'></span>"
203 add
" <span class='icon-bar'></span>"
205 if brand
!= null then add brand
.as(not null)
207 add
" <div class='collapse navbar-collapse' id='topmenu-collapse'>"
208 if not elts
.is_empty
then
209 add
"<ul class='nav navbar-nav'>"
210 for elt
in elts
do add elt
223 # Sidebar contains sidebar element templates called boxes
224 var boxes
= new Array[TplSidebarElt]
226 # Sort boxes by order priority
227 private fun order_boxes
do
228 var sorter
= new OrderComparator
232 redef fun rendering
do
233 if boxes
.is_empty
then return
235 add
"<div id='sidebar'>"
236 for box
in boxes
do add box
241 # Comparator used to sort boxes by order
242 private class OrderComparator
245 redef type COMPARED: TplSidebarElt
247 redef fun compare
(a
, b
) do
248 if a
.order
< b
.order
then return -1
249 if a
.order
> b
.order
then return 1
254 # Something that can be put in the sidebar
258 # Order of the box in the sidebar
261 init with_order
(order
: Int) do self.order
= order
264 # Agenericbox that can be added to sidebar
268 # Title of the box to display
269 # Title is also a placeholder for the collapse link
273 # equals to `title.to_cmangle` by default
274 # Used for collapsing
277 # Content to display in the box
278 # box will not be rendered if the content is null
279 var content
: nullable Streamable is writable
281 # Is the box opened by default
282 # otherwise, the user will have to clic on the title to display the content
283 var is_open
= false is writable
285 init(title
: String) do
287 self.id
= title
.to_cmangle
290 init with_content
(title
: String, content
: Streamable) do
292 self.content
= content
295 redef fun rendering
do
296 if content
== null then return
298 if is_open
then open
= "in"
299 add
"<div class='panel'>"
300 add
" <div class='panel-heading'>"
301 add
" <a data-toggle='collapse' data-parent='#sidebar' data-target='#box_{id}' href='#'>"
305 add
" <div id='box_{id}' class='panel-body collapse {open}'>"
306 add content
.as(not null)
312 # Something that can go on a summary template
316 # Add an element to the summary
317 fun add_child
(child
: TplSummaryElt) is abstract
320 # A summary that can go on the sidebar
321 # If the page contains a sidebar, the summary is automatically placed
322 # on top of the sidebarauto-generated
323 # summary contains anchors to all sections displayed in the page
328 # Summary elements to display
329 var children
= new Array[TplSummaryElt]
331 redef fun add_child
(child
) do children
.add child
333 redef fun rendering
do
334 if children
.is_empty
then return
335 add
"<div class='panel'>"
336 add
" <div class='panel-heading'>"
337 add
" <a data-toggle='collapse' data-parent='#sidebar' data-target='#box-sum' href='#'>"
341 add
" <div id='box-sum' class='summary collapse in'>"
342 add
" <ul class='nav'>"
343 for entry
in children
do add entry
351 class TplSummaryEntry
357 # Children of this entry
358 # Will be displayed as a tree
359 var children
= new Array[TplSummaryElt]
361 init(text
: Streamable) do self.text
= text
363 redef fun add_child
(child
) do children
.add child
365 redef fun rendering
do
368 if not children
.is_empty
then
369 add
"<ul class='nav'>"
370 for entry
in children
do add entry
377 # Something that can go in a section
378 # Sections are automatically collected to populate the menu
385 # Title to display if any
386 # if both `title` and `summary_title` are null then
387 # the section will not appear in the summary
388 var title
: nullable Streamable is writable
390 # Subtitle to display if any
391 var subtitle
: nullable Streamable is writable
393 # Title that appear in the summary
394 # if null use `title` instead
395 var summary_title
: nullable String is writable
397 # CSS classes to apply on the section element
398 var css_classes
= new Array[String]
400 # CSS classes to apply on the title heading element
401 var title_classes
= new Array[String]
403 # Parent article/section if any
404 var parent
: nullable TplSectionElt
406 init(id
: String) do self.id
= id
408 init with_title
(id
: String, title
: Streamable) do
413 # Level <hX> for HTML heading
414 protected fun hlvl
: Int do
415 if parent
== null then return 1
416 return parent
.hlvl
+ 1
419 # Elements contained by this section
420 var children
= new Array[TplSectionElt]
422 # Add an element in this section
423 fun add_child
(child
: TplSectionElt) do
428 # Is the section empty (no content at all)
429 fun is_empty
: Bool do return children
.is_empty
431 # Render this section in the summary
432 fun render_summary
(parent
: TplSummaryElt) do
433 if is_empty
then return
434 var title
= summary_title
435 if title
== null and self.title
!= null then title
= self.title
.write_to_string
436 if title
== null then return
437 var lnk
= new TplLink("#{id}", title
)
438 var entry
= new TplSummaryEntry(lnk
)
439 for child
in children
do
440 child
.render_summary
(entry
)
442 parent
.add_child entry
446 # A HTML <section> element
450 redef fun rendering
do
451 add
"<section id='{id}' class='{css_classes.join(" ")}'>"
452 if title
!= null then
454 if lvl
== 2 then title_classes
.add
"well well-sm"
455 add
"<h{lvl} class='{title_classes.join(" ")}'>"
456 add title
.as(not null)
459 if subtitle
!= null then
460 add
"<div class='info subtitle'>"
461 add subtitle
.as(not null)
464 for child
in children
do
471 # A page article that can go in a section
475 # Content for this article
476 var content
: nullable Streamable = null is writable
477 var source_link
: nullable Streamable = null is writable
479 init with_content
(id
: String, title
: Streamable, content
: Streamable) do
480 with_title
(id
, title
)
481 self.content
= content
484 redef fun render_summary
(parent
) do
485 if is_empty
then return
486 var title
= summary_title
487 if title
== null and self.title
!= null then title
= self.title
.write_to_string
488 if title
== null then return
489 var lnk
= new TplLink("#{id}", title
)
490 parent
.add_child
new TplSummaryEntry(lnk
)
493 redef fun rendering
do
494 if is_empty
then return
495 add
"<article id='{id}' class='{css_classes.join(" ")}'>"
496 if source_link
!= null then
497 add
"<div class='source-link'>"
498 add source_link
.as(not null)
501 if title
!= null then
503 if lvl
== 2 then title_classes
.add
"well well-sm"
504 add
"<h{lvl} class='{title_classes.join(" ")}'>"
505 add title
.as(not null)
508 if subtitle
!= null then
509 add
"<div class='info subtitle'>"
510 add subtitle
.as(not null)
513 if content
!= null then
514 add content
.as(not null)
516 for child
in children
do
522 redef fun is_empty
: Bool do
523 return title
== null and subtitle
== null and content
== null and children
.is_empty
527 # A module / class / prop definition
532 var comment
: nullable Streamable = null is writable
534 # Namespace for this definition
535 var namespace
: nullable Streamable = null is writable
537 # Location link to display
538 var location
: nullable Streamable = null is writable
540 private fun render_info
do
541 add
"<div class='info text-right'>"
542 if namespace
!= null then
543 if comment
== null then
544 add
"<span class=\"noComment\
">no comment for </span>"
546 add namespace
.as(not null)
548 if location
!= null then
550 add location
.as(not null)
555 private fun render_comment
do
556 if comment
!= null then add comment
.as(not null)
559 redef fun rendering
do
560 add
"<div class='definition'>"
568 class TplClassDefinition
571 var intros
= new Array[TplListElt]
572 var redefs
= new Array[TplListElt]
576 redef fun rendering
do
577 add
"<div class='definition'>"
580 render_list
("Introduces", intros
)
581 render_list
("Redefines", redefs
)
585 private fun render_list
(name
: String, elts
: Array[TplListElt]) do
586 if elts
.is_empty
then return
587 add
"<h5>{name}</h5>"
588 add
"<ul class='list-unstyled list-definition'>"
589 for elt
in elts
do add elt
594 # Layout for Search page
598 var modules
= new Array[Streamable]
599 var classes
= new Array[Streamable]
600 var props
= new Array[Streamable]
602 redef fun rendering
do
603 var title
= self.title
604 if title
!= null then add
"<h1>{title}</h1>"
605 add
"<div class='container-fluid'>"
606 add
" <div class='row'>"
607 if not modules
.is_empty
then
608 add
"<div class='col-xs-4'>"
609 add
"<h3>Modules</h3>"
619 if not classes
.is_empty
then
620 add
"<div class='col-xs-4'>"
621 add
"<h3>Classes</h3>"
631 if not props
.is_empty
then
632 add
"<div class='col-xs-4'>"
633 add
"<h3>Properties</h3>"
648 #####################
649 # Basiv HTML elements
650 #####################
657 var href
: String is writable
659 # Text to display in the link
660 var text
: Streamable is writable
663 var title
: nullable String is writable
665 init(href
, text
: String) do
670 init with_title
(href
, text
, title
: String) do
675 redef fun rendering
do
679 if title
!= null then
681 add title.as(not null)
694 # Elements contained in this list
695 # can be <li> or <ul> elements
696 var elts
= new Array[TplListElt]
698 # CSS classes of the <ul> element
699 var css_classes
= new Array[String]
701 # Add content wrapped in a <li> element
702 fun add_li
(item
: TplListItem) do elts
.add item
706 init with_classes
(classes
: Array[String]) do self.css_classes
= classes
708 fun is_empty
: Bool do return elts
.is_empty
710 redef fun rendering
do
711 if elts
.is_empty
then return
712 add
"<ul class='{css_classes.join(" ")}'>"
713 for elt
in elts
do add elt
718 # Something that can be added to a TplList
727 # Content of the list item
728 var content
= new Template
730 # CSS classes of the <li> element
731 var css_classes
= new Array[String]
735 init with_content
(content
: Streamable) do append
(content
)
737 init with_classes
(content
: Streamable, classes
: Array[String]) do
738 with_content
(content
)
739 css_classes
= classes
742 # Append `content` to the item
743 # similar to `self.content.add`
744 fun append
(content
: Streamable) do self.content
.add content
746 redef fun rendering
do
747 add
"<li class='{css_classes.join(" ")}'>"
753 # A Bootstrap tab component that contains `TplTabPanel`.
757 # Panels contained in the tab.
758 var panels
= new Array[TplTabPanel]
761 fun add_panel
(panel
: TplTabPanel) do panels
.add panel
763 # CSS classes of the tab component.
764 var css_classes
= new Array[String]
766 redef fun rendering
do
767 add
"<div class='tab-content'>"
768 for panel
in panels
do add panel
773 # A panel that goes in a `TplTab`.
777 # CSS classes of the pane element.
778 var css_classes
= new Array[String]
782 # Used to show/hide panel.
787 # Displayed in the tab header or in the pointing link.
790 # Is the panel visible by default?
791 var is_active
= false is writable
794 var content
: nullable Streamable = null is writable
796 # Get a link pointing to this panel.
797 fun tpl_link_to
: Streamable do
798 var lnk
= new Template
799 lnk
.add
"<a data-target='#{id}' data-toggle='pill'>"
805 redef fun rendering
do
806 add
"<div class='tab-pane {css_classes.join(" ")}"
807 if is_active
then add
"active"
809 if content
!= null then add content
.as(not null)
814 # A label with a text content
818 # Content of the label if any
819 var content
: nullable Streamable = null is writable
821 # CSS classes of the <span> element
822 var css_classes
= new Array[String]
824 init with_content
(content
: Streamable) do self.content
= content
825 init with_classes
(classes
: Array[String]) do self.css_classes
= classes
827 redef fun rendering
do
828 add
"<span class='label {css_classes.join(" ")}'>"
829 if content
!= null then add content
.as(not null)
834 # A label with an icon
839 # see: http://getbootstrap.com/components/#glyphicons
842 init with_icon
(icon
: String) do self.icon
= icon
844 redef fun rendering
do
845 add
"<span class='glyphicon glyphicon-{icon} {css_classes.join(" ")}'>"
846 if content
!= null then add content
.as(not null)
851 # A HTML tag attribute
852 # `<tag attr="value">`
857 var value
: nullable String
859 init(name
: String, value
: nullable String) do
864 redef fun rendering
do
865 var value
= self.value
866 if value
== null then
869 add
(" {name}=\"{value}\
"")
878 var attrs
= new Array[TagAttribute]
879 var content
: nullable Streamable = null is writable
882 attrs
.add
(new TagAttribute("type", "text/javascript"))
885 protected fun render_content
do
886 if content
!= null then add content
.as(not null)
889 redef fun rendering
do
891 for attr
in attrs
do add attr
898 # JS script for Piwik Tracker
902 var tracker_url
: String
905 init(tracker_url
, site_id
: String) do
907 self.tracker_url
= tracker_url
908 self.site_id
= site_id
911 redef fun render_content
do
913 add
"var _paq = _paq || [];"
914 add
" _paq.push([\"trackPageView\
"]);"
915 add
" _paq.push([\"enableLinkTracking\
"]);"
917 add
" var u=((\"https
:\
" == document.location.protocol) ? \"https\
" : \"http\
") + \"://{tracker_url}\
";"
918 add
" _paq.push([\"setTrackerUrl\
", u+\"piwik
.php\
"]);"
919 add
" _paq.push([\"setSiteId\
", \"{site_id}\
"]);"
920 add
" var d=document, g=d.createElement(\"script\
"), s=d.getElementsByTagName(\"script\
")[0]; g.type=\"text
/javascript\
";"
921 add
" g.defer=true; g.async=true; g.src=u+\"piwik
.js\
"; s.parentNode.insertBefore(g,s);"