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 # Introduces templates that compose the documentation HTML rendering.
19 import html
::bootstrap
20 import doc_phases
::doc_structure
21 import doc_phases
::doc_hierarchies
22 import doc_phases
::doc_graphs
23 import doc_phases
::doc_intros_redefs
24 import doc_phases
::doc_lin
26 # Renders the page as HTML.
31 var html_url
: String is writable, noinit
33 # Directory where css, js and other assets can be found.
34 var shareurl
: String is writable, noinit
36 # Attributes of the body tag element.
37 var body_attrs
= new Array[TagAttribute]
39 # Top menu template if any.
40 var topmenu
: DocTopMenu is writable, noinit
42 # Sidebar template if any.
43 var sidebar
: nullable DocSideBar = null is writable
45 # Footer content if any.
46 var footer
: nullable Writable = null is writable
48 # JS scripts to append at the end of the body
49 var scripts
= new Array[TplScript]
51 # Renders the html `<head>`.
52 private fun render_head
do
53 var css
= (self.shareurl
/ "css").html_escape
54 var vendors
= (self.shareurl
/ "vendors").html_escape
56 addn
"<!DOCTYPE html>"
58 addn
" <meta charset='utf-8'/>"
59 addn
" <!--link rel='stylesheet' href='{css}/Nitdoc.UI.css' type='text/css'/-->"
60 addn
" <link rel='stylesheet' href='{vendors}/bootstrap/css/bootstrap.min.css'/>"
61 addn
" <link rel='stylesheet' href='{css}/nitdoc.bootstrap.css'/>"
62 addn
" <link rel='stylesheet' href='{css}/nitdoc.css'/>"
63 addn
" <link rel='stylesheet' href='{css}/Nitdoc.QuickSearch.css'/>"
64 addn
" <link rel='stylesheet' href='{css}/Nitdoc.ModalBox.css'/>"
65 addn
" <link rel='stylesheet' href='{css}/Nitdoc.GitHub.css'/>"
66 addn
" <title>{title.html_escape}</title>"
69 for attr
in body_attrs
do add attr
73 # Renders the footer and content.
74 private fun render_content
do
76 if footer
!= null then
77 addn
"<div class='well footer'>"
78 add footer
.as(not null)
84 private fun render_footer
do
85 var vendors
= (self.shareurl
/ "vendors").html_escape
86 var js
= (self.shareurl
/ "js").html_escape
88 addn
"<script src='{vendors}/jquery/jquery-1.11.1.min.js'></script>"
89 addn
"<script src='{vendors}/jquery/jquery-ui-1.10.4.custom.min.js'></script>"
90 addn
"<script src='{vendors}/bootstrap/js/bootstrap.min.js'></script>"
91 addn
"<script src='{js}/lib/utils.js'></script>"
92 addn
"<script src='{js}/plugins/filtering.js'></script>"
93 addn
"<script src='quicksearch-list.js'></script>"
94 addn
"<script src='{js}/plugins/quicksearch.js'></script>"
95 for script
in scripts
do add script
98 $("[data-toggle='tooltip']").tooltip();
99 $("[data-toggle='popover']").popover();
106 # Render the whole page
107 redef fun rendering
do
109 addn
"<div class='container-fluid'>"
110 addn
" <div class='row'>"
113 addn
" <div class='row' id='content'>"
114 var sidebar
= self.sidebar
115 if sidebar
!= null then
116 addn
"<div class='col col-xs-3 col-lg-2'>"
119 addn
"<div class='col col-xs-9 col-lg-10' data-spy='scroll' data-target='.summary'>"
123 addn
"<div class='col col-xs-12'>"
132 # Render table of content for this page.
133 fun html_toc
: UnorderedList do
134 var lst
= new UnorderedList
135 lst
.css_classes
.add
"nav"
136 for child
in root
.children
do
137 child
.render_toc_item
(lst
)
143 # Top menu bar template.
145 # FIXME should be a Bootstrap component template
146 # At this moment, the topmenu structure stills to specific to Nitdoc to use the
151 # Brand link to display in first position of the top menu.
153 # This is where you want to put your logo.
154 var brand
: nullable Writable is noinit
, writable
158 # Depends on the current page, this allows to hilighted the current item.
160 # FIXME should be using Boostrap breadcrumbs component.
161 # This will still like this to avoid diff and be changed in further fixes
162 # when we will modify the output.
163 var active_item
: nullable ListItem is noinit
, writable
165 redef fun rendering
do
166 addn
"<nav id='topmenu' class='navbar navbar-default navbar-fixed-top' role='navigation'>"
167 addn
" <div class='container-fluid'>"
168 addn
" <div class='navbar-header'>"
169 add
" <button type='button' class='navbar-toggle' "
170 addn
" data-toggle='collapse' data-target='#topmenu-collapse'>"
171 addn
" <span class='sr-only'>Toggle menu</span>"
172 addn
" <span class='icon-bar'></span>"
173 addn
" <span class='icon-bar'></span>"
174 addn
" <span class='icon-bar'></span>"
176 if brand
!= null then
177 add
"<span class='navbar-brand'>"
178 add brand
.write_to_string
182 addn
" <div class='collapse navbar-collapse' id='topmenu-collapse'>"
183 addn
" <ul class='nav navbar-nav'>"
185 if item
== active_item
then item
.css_classes
.add
"active"
186 add item
.write_to_string
195 # Nitdoc sidebar template.
199 # Sidebar contains `DocSideBox`.
200 var boxes
= new Array[DocSideBox]
202 redef fun rendering
do
203 if boxes
.is_empty
then return
204 addn
"<div id='sidebar'>"
205 for box
in boxes
do add box
210 # Something that can be put in a DocSideBar.
214 # Box HTML id, used for Bootstrap collapsing feature.
216 # Use `html_title.to_cmangle` by default.
217 var id
: String is lazy
do return title
.write_to_string
.to_cmangle
219 # Title of the box to display.
222 # Content to display in the box.
223 var content
: Writable
225 # Is the box opened by default?
227 # Otherwise, the user will have to clic on the title to display the content.
230 var is_open
= true is writable
232 redef fun rendering
do
234 if is_open
then open
= "in"
235 addn
"<div class='panel'>"
236 addn
" <div class='panel-heading'>"
237 add
" <a data-toggle='collapse' data-parent='#sidebar'"
238 add
" data-target='#box_{id}' href='#'>"
242 addn
" <div id='box_{id}' class='summary panel-body collapse {open}'>"
249 redef class DocComposite
253 var html_id
: String is writable, lazy
do return id
255 # Title to display if any.
257 # This title can be decorated with HTML.
258 var html_title
: nullable Writable is writable, lazy
do return title
260 # Subtitle to display if any.
261 var html_subtitle
: nullable Writable is noinit
, writable
263 # Render the element title and subtitle.
264 private fun render_title
do
265 if html_title
!= null then
266 var header
= new Header(hlvl
, html_title
.write_to_string
)
267 header
.css_classes
.add
"signature"
270 if html_subtitle
!= null then
271 addn
"<div class='info subtitle'>"
272 addn html_subtitle
.write_to_string
277 # Render the element body.
278 private fun render_body
do
279 for child
in children
do addn child
.write_to_string
282 redef fun rendering
do
283 if is_hidden
then return
288 # Level <hX> for HTML heading.
289 private fun hlvl
: Int do return depth
291 # A short, undecorated title that goes in the table of contents.
293 # By default, returns `html_title.to_s`, subclasses should redefine it.
294 var html_toc_title
: nullable String is lazy
, writable do
295 if html_title
== null then return toc_title
296 return html_title
.write_to_string
299 # Render this element in a table of contents.
300 private fun render_toc_item
(lst
: UnorderedList) do
301 if is_toc_hidden
or html_toc_title
== null then return
303 var content
= new Template
304 content
.add
new Link("#{html_id}", html_toc_title
.to_s
)
305 if not children
.is_empty
then
306 var sublst
= new UnorderedList
307 sublst
.css_classes
.add
"nav"
308 for child
in children
do
309 child
.render_toc_item
(sublst
)
313 lst
.add_li
new ListItem(content
)
316 # ID used in HTML tab labels.
318 # We sanitize it for Boostrap JS panels that do not like ":" and "." in ids.
319 var html_tab_id
: String is lazy
do
320 var id
= html_id
.replace
(":", "")
321 id
= id
.replace
(".", "")
327 redef fun rendering
do
328 for child
in children
do addn child
.write_to_string
332 redef class DocSection
335 redef fun rendering
do
337 addn
"<a id=\"{html_id}\
"></a>"
340 addn
"<section{render_css_classes} id=\"{html_id}\
">"
347 redef class DocArticle
350 redef fun rendering
do
351 if is_hidden
then return
352 addn
"<article{render_css_classes} id=\"{html_id}\
">"
359 redef class TabbedGroup
360 redef fun render_body
do
361 var tabs
= new DocTabs("{html_id}.tabs", "")
362 for child
in children
do
363 if child
.is_hidden
then continue
364 var title
= child
.html_toc_title
or else child
.toc_title
or else ""
365 tabs
.add_panel
new DocTabPanel(child
.html_tab_id
, title
, child
)
371 redef class PanelGroup
372 redef var html_title
= null
373 redef var toc_title
is lazy
do return title
or else ""
374 redef var is_toc_hidden
= true
377 redef class HomeArticle
378 redef var html_title
= "Overview"
380 # HTML content to display on the home page.
382 # This attribute is set by the `doc_render` phase who knows the context.
383 var content
: nullable String is noinit
, writable
385 redef fun render_body
do
386 var content
= self.content
387 if content
!= null then add content
392 redef class IndexArticle
393 redef var html_title
= "Index"
395 redef fun render_body
do
396 addn
"<div class='container-fluid'>"
397 addn
" <div class='row'>"
398 render_list
("Modules", mmodules
)
399 render_list
("Classes", mclasses
)
400 render_list
("Properties", mprops
)
405 # Displays a list from the content of `mentities`.
406 private fun render_list
(title
: String, mentities
: Array[MEntity]) do
407 if mentities
.is_empty
then return
408 addn
"<div class='col-xs-4'>"
409 addn
new Header(3, title
)
410 var lst
= new UnorderedList
411 for mentity
in mentities
do
412 if mentity
isa MProperty then
413 var tpl
= new Template
414 tpl
.add mentity
.intro
.html_link
416 tpl
.add mentity
.intro
.mclassdef
.mclass
.html_link
418 lst
.add_li
new ListItem(tpl
)
420 lst
.add_li
new ListItem(mentity
.html_link
)
428 redef class MEntityComposite
429 redef var html_title
is lazy
do return mentity
.nitdoc_name
432 redef class MEntitySection
433 redef var html_title
is lazy
do return mentity
.html_name
434 redef var html_subtitle
is lazy
do return mentity
.html_declaration
437 redef class ConcernSection
438 redef var html_title
is lazy
do return "in {mentity.nitdoc_name}"
441 redef class IntroArticle
442 redef var html_title
= null
444 # Link to source to display if any.
445 var html_source_link
: nullable Writable is noinit
, writable
447 redef fun render_body
do
448 var tabs
= new DocTabs("{html_id}.tabs", "")
449 var comment
= mentity
.html_comment
450 if comment
!= null then
451 tabs
.add_panel
new DocTabPanel("{html_tab_id}-comment", "Comment", comment
)
453 for child
in children
do
454 if child
.is_hidden
then continue
455 var title
= child
.html_toc_title
or else child
.toc_title
or else ""
456 tabs
.add_panel
new DocTabPanel(child
.html_tab_id
, title
, child
)
458 var lnk
= html_source_link
460 tabs
.drop_list
.items
.add
new ListItem(lnk
)
466 redef class ConcernsArticle
467 redef var html_title
= "Concerns"
468 redef fun render_body
do add concerns
.html_list
471 redef class DefinitionListArticle
472 redef var html_title
is lazy
do
473 var title
= new Template
474 title
.add mentity
.html_icon
475 title
.add mentity
.html_link
479 redef var html_subtitle
is lazy
do return mentity
.html_namespace
480 redef var html_toc_title
is lazy
do return mentity
.html_name
483 redef class DefinitionArticle
484 redef var html_title
is lazy
do return mentity
.html_name
485 redef var html_subtitle
is lazy
do return mentity
.html_declaration
487 # Does `self` display only it's title and no body?
490 var is_no_body
: Bool = false is writable
492 # Does `self` display only the short content as definition?
495 var is_short_comment
: Bool = false is writable
497 # Link to source to display if any.
498 var html_source_link
: nullable Writable is noinit
, writable
500 redef fun render_body
do
501 var tabs
= new DocTabs("{html_id}.tabs", "")
502 if not is_no_body
then
504 if is_short_comment
then
505 comment
= mentity
.html_short_comment
507 comment
= mentity
.html_comment
509 if comment
!= null then
510 tabs
.add_panel
new DocTabPanel("{html_tab_id}-comment", "Comment", comment
)
513 for child
in children
do
514 if child
.is_hidden
then continue
515 var title
= child
.html_toc_title
or else child
.toc_title
or else ""
516 tabs
.add_panel
new DocTabPanel(child
.html_tab_id
, title
, child
)
518 var lnk
= html_source_link
520 tabs
.drop_list
.items
.add
new ListItem(lnk
)
526 redef class MEntitiesListArticle
527 redef fun render_body
do
528 var lst
= new UnorderedList
529 lst
.css_classes
.add
"list-unstyled list-definition"
530 for mentity
in mentities
do
531 lst
.add_li mentity
.html_list_item
537 redef class DefinitionLinArticle
538 redef fun render_body
do
539 var lst
= new UnorderedList
540 lst
.css_classes
.add
"list-unstyled list-labeled"
541 for mentity
in mentities
do
542 if not mentity
isa MPropDef then continue # TODO handle all mentities
543 var tpl
= new Template
544 tpl
.add mentity
.mclassdef
.html_namespace
545 var comment
= mentity
.mclassdef
.html_short_comment
546 if comment
!= null then
550 var li
= new ListItem(tpl
)
551 li
.css_classes
.add
"signature"
558 redef class GraphArticle
559 redef var html_title
= null
561 # HTML map used to display link.
563 # This attribute is set by the `doc_render` phase who knows the context.
564 var map
: String is noinit
, writable
566 redef fun render_body
do
567 addn
"<div class=\"text-center\
">"
568 addn
" <img src='{graph_id}.png' usemap='#{graph_id}' style='margin:auto'"
569 addn
" alt='{title or else ""}'/>"