src: mass rename project->package
[nit.git] / src / doc / html_templates / html_templates.nit
index 83c1842..290f04b 100644 (file)
 module html_templates
 
 import html_model
+import html::bootstrap
+import doc_phases::doc_structure
+import doc_phases::doc_hierarchies
+import doc_phases::doc_graphs
+import doc_phases::doc_intros_redefs
+import doc_phases::doc_lin
+import doc_phases::doc_readme
+intrude import doc_down
 
 # Renders the page as HTML.
 redef class DocPage
@@ -31,14 +39,10 @@ redef class DocPage
        var body_attrs = new Array[TagAttribute]
 
        # Top menu template if any.
-       var topmenu: TplTopMenu is writable, noinit
+       var topmenu: DocTopMenu is writable, noinit
 
        # Sidebar template if any.
-       var sidebar: nullable TplSidebar = null is writable
-
-       # Content of the page in form a TplSection.
-       # TODO remove when other templates are migrated.
-       var sections = new Array[TplSection]
+       var sidebar: nullable DocSideBar = null is writable
 
        # Footer content if any.
        var footer: nullable Writable = null is writable
@@ -46,12 +50,6 @@ redef class DocPage
        # JS scripts to append at the end of the body
        var scripts = new Array[TplScript]
 
-       # Adds a section to this page.
-       # TODO remove when other templates are migrated.
-       fun add_section(section: TplSection) do
-               sections.add section
-       end
-
        # Renders the html `<head>`.
        private fun render_head do
                var css = (self.shareurl / "css").html_escape
@@ -74,30 +72,9 @@ redef class DocPage
                addn ">"
        end
 
-       # Renders the topmenu template.
-       private fun render_topmenu do
-               addn " <div class='row'>"
-               add topmenu
-               addn " </div>"
-       end
-
-       # Renders the sidebar template.
-       #
-       # Sidebar is automatically populated with a summary of all sections
-       # TODO remove summary generation when other templates are migrated.
-       private fun render_sidebar do
-               if sidebar == null then return
-               var summary = new TplSummary.with_order(0)
-               for section in sections do
-                       section.render_summary summary
-               end
-               sidebar.boxes.add summary
-               add sidebar.as(not null)
-       end
-
        # Renders the footer and content.
        private fun render_content do
-               for section in sections do add section
+               add root
                if footer != null then
                        addn "<div class='well footer'>"
                        add footer.as(not null)
@@ -113,7 +90,10 @@ redef class DocPage
                addn "<script src='{vendors}/jquery/jquery-1.11.1.min.js'></script>"
                addn "<script src='{vendors}/jquery/jquery-ui-1.10.4.custom.min.js'></script>"
                addn "<script src='{vendors}/bootstrap/js/bootstrap.min.js'></script>"
-               addn "<script data-main='{js}/nitdoc' src='{js}/lib/require.js'></script>"
+               addn "<script src='{js}/lib/utils.js'></script>"
+               addn "<script src='{js}/plugins/filtering.js'></script>"
+               addn "<script src='quicksearch-list.js'></script>"
+               addn "<script src='{js}/plugins/quicksearch.js'></script>"
                for script in scripts do add script
                addn """<script>
                        $(function () {
@@ -129,11 +109,14 @@ redef class DocPage
        redef fun rendering do
                render_head
                addn "<div class='container-fluid'>"
-               render_topmenu
+               addn " <div class='row'>"
+               add topmenu
+               addn " </div>"
                addn " <div class='row' id='content'>"
+               var sidebar = self.sidebar
                if sidebar != null then
                        addn "<div class='col col-xs-3 col-lg-2'>"
-                       render_sidebar
+                       add sidebar
                        addn "</div>"
                        addn "<div class='col col-xs-9 col-lg-10' data-spy='scroll' data-target='.summary'>"
                        render_content
@@ -147,4 +130,494 @@ redef class DocPage
                addn "</div>"
                render_footer
        end
+
+       # Render table of content for this page.
+       fun html_toc: UnorderedList do
+               var lst = new UnorderedList
+               lst.css_classes.add "nav"
+               for child in root.children do
+                       child.render_toc_item(lst)
+               end
+               return lst
+       end
+end
+
+# Top menu bar template.
+#
+# FIXME should be a Bootstrap component template
+# At this moment, the topmenu structure stills to specific to Nitdoc to use the
+# generic component.
+class DocTopMenu
+       super UnorderedList
+
+       # Brand link to display in first position of the top menu.
+       #
+       # This is where you want to put your logo.
+       var brand: nullable Writable is noinit, writable
+
+       # Active menu item.
+       #
+       # Depends on the current page, this allows to hilighted the current item.
+       #
+       # FIXME should be using Boostrap breadcrumbs component.
+       # This will still like this to avoid diff and be changed in further fixes
+       # when we will modify the output.
+       var active_item: nullable ListItem is noinit, writable
+
+       redef fun rendering do
+               addn "<nav id='topmenu' class='navbar navbar-default navbar-fixed-top' role='navigation'>"
+               addn " <div class='container-fluid'>"
+               addn "  <div class='navbar-header'>"
+               add "   <button type='button' class='navbar-toggle' "
+               addn "       data-toggle='collapse' data-target='#topmenu-collapse'>"
+               addn "    <span class='sr-only'>Toggle menu</span>"
+               addn "    <span class='icon-bar'></span>"
+               addn "    <span class='icon-bar'></span>"
+               addn "    <span class='icon-bar'></span>"
+               addn "   </button>"
+               if brand != null then
+                       add "<span class='navbar-brand'>"
+                       add brand.write_to_string
+                       add "</span>"
+               end
+               addn "  </div>"
+               addn "  <div class='collapse navbar-collapse' id='topmenu-collapse'>"
+               addn "   <ul class='nav navbar-nav'>"
+               for item in items do
+                       if item == active_item then item.css_classes.add "active"
+                       add item.write_to_string
+               end
+               addn "   </ul>"
+               addn "  </div>"
+               addn " </div>"
+               addn "</nav>"
+       end
+end
+
+# Nitdoc sidebar template.
+class DocSideBar
+       super Template
+
+       # Sidebar contains `DocSideBox`.
+       var boxes = new Array[DocSideBox]
+
+       redef fun rendering do
+               if boxes.is_empty then return
+               addn "<div id='sidebar'>"
+               for box in boxes do add box
+               addn "</div>"
+       end
+end
+
+# Something that can be put in a DocSideBar.
+class DocSideBox
+       super Template
+
+       # Box HTML id, used for Bootstrap collapsing feature.
+       #
+       # Use `html_title.to_cmangle` by default.
+       var id: String is lazy do return title.write_to_string.to_cmangle
+
+       # Title of the box to display.
+       var title: Writable
+
+       # Content to display in the box.
+       var content: Writable
+
+       # Is the box opened by default?
+       #
+       # Otherwise, the user will have to clic on the title to display the content.
+       #
+       # Default is `true`.
+       var is_open = true is writable
+
+       redef fun rendering do
+               var open = ""
+               if is_open then open = "in"
+               addn "<div class='panel'>"
+               addn " <div class='panel-heading'>"
+               add "  <a data-toggle='collapse' data-parent='#sidebar'"
+               add "   data-target='#box_{id}' href='#'>"
+               add title
+               addn "  </a>"
+               addn " </div>"
+               addn " <div id='box_{id}' class='summary panel-body collapse {open}'>"
+               add content
+               addn " </div>"
+               addn "</div>"
+       end
+end
+
+redef class DocComposite
+       super Template
+
+       # HTML anchor id
+       var html_id: String is writable, lazy do return id
+
+       # Title to display if any.
+       #
+       # This title can be decorated with HTML.
+       var html_title: nullable Writable is writable, lazy do return title
+
+       # Subtitle to display if any.
+       var html_subtitle: nullable Writable is noinit, writable
+
+       # Render the element title and subtitle.
+       private fun render_title do
+               if html_title != null then
+               var header = new Header(hlvl, html_title.write_to_string)
+               header.css_classes.add "signature"
+               addn header
+               end
+               if html_subtitle != null then
+                       addn "<div class='info subtitle'>"
+                       addn html_subtitle.write_to_string
+                       addn "</div>"
+               end
+       end
+
+       # Render the element body.
+       private fun render_body do
+               for child in children do addn child.write_to_string
+       end
+
+       redef fun rendering do
+               if is_hidden then return
+               render_title
+               render_body
+       end
+
+       # Level <hX> for HTML heading.
+       private fun hlvl: Int do return depth
+
+       # A short, undecorated title that goes in the table of contents.
+       #
+       # By default, returns `html_title.to_s`, subclasses should redefine it.
+       var html_toc_title: nullable String is lazy, writable do
+               if html_title == null then return toc_title
+               return html_title.write_to_string
+       end
+
+       # Render this element in a table of contents.
+       private fun render_toc_item(lst: UnorderedList) do
+               if is_toc_hidden or html_toc_title == null then return
+
+               var content = new Template
+               content.add new Link("#{html_id}", html_toc_title.to_s)
+               if not children.is_empty then
+                       var sublst = new UnorderedList
+                       sublst.css_classes.add "nav"
+                       for child in children do
+                               child.render_toc_item(sublst)
+                       end
+                       content.add sublst
+               end
+               lst.add_li new ListItem(content)
+       end
+
+       # ID used in HTML tab labels.
+       #
+       # We sanitize it for Boostrap JS panels that do not like ":" and "." in ids.
+       var html_tab_id: String is lazy do
+               var id = html_id.replace(":", "")
+               id = id.replace(".", "")
+               return "{id}-tab"
+       end
+end
+
+redef class DocRoot
+       redef fun rendering do
+               for child in children do addn child.write_to_string
+       end
+end
+
+redef class DocSection
+       super BSComponent
+
+       redef fun rendering do
+               if is_hidden then
+                       addn "<a id=\"{html_id}\"></a>"
+                       return
+               end
+               addn "<section{render_css_classes} id=\"{html_id}\">"
+               render_title
+               render_body
+               addn "</section>"
+       end
+end
+
+redef class DocArticle
+       super BSComponent
+
+       redef fun rendering do
+               if is_hidden then return
+               addn "<article{render_css_classes} id=\"{html_id}\">"
+               render_title
+               render_body
+               addn "</article>"
+       end
+end
+
+redef class TabbedGroup
+       redef fun render_body do
+               var tabs = new DocTabs("{html_id}.tabs", "")
+               for child in children do
+                       if child.is_hidden then continue
+                       var title = child.html_toc_title or else child.toc_title or else ""
+                       tabs.add_panel new DocTabPanel(child.html_tab_id, title, child)
+               end
+               addn tabs
+       end
+end
+
+redef class PanelGroup
+       redef var html_title = null
+       redef var toc_title is lazy do return title or else ""
+       redef var is_toc_hidden = true
+end
+
+redef class HomeArticle
+       redef var html_title = "Overview"
+
+       # HTML content to display on the home page.
+       #
+       # This attribute is set by the `doc_render` phase who knows the context.
+       var content: nullable String is noinit, writable
+
+       redef fun render_body do
+               var content = self.content
+               if content != null then add content
+               super
+       end
+end
+
+redef class IndexArticle
+       redef var html_title = "Index"
+
+       redef fun render_body do
+               addn "<div class='container-fluid'>"
+               addn " <div class='row'>"
+               render_list("Modules", mmodules)
+               render_list("Classes", mclasses)
+               render_list("Properties", mprops)
+               addn "</div>"
+               addn "</div>"
+       end
+
+       # Displays a list from the content of `mentities`.
+       private fun render_list(title: String, mentities: Array[MEntity]) do
+               if mentities.is_empty then return
+               addn "<div class='col-xs-4'>"
+               addn new Header(3, title)
+               var lst = new UnorderedList
+               for mentity in mentities do
+                       if mentity isa MProperty then
+                               var tpl = new Template
+                               tpl.add mentity.intro.html_link
+                               tpl.add " ("
+                               tpl.add mentity.intro.mclassdef.mclass.html_link
+                               tpl.add ")"
+                               lst.add_li new ListItem(tpl)
+                       else
+                               lst.add_li new ListItem(mentity.html_link)
+                       end
+               end
+               addn lst
+               addn "</div>"
+       end
+end
+
+redef class MEntityComposite
+       redef var html_title is lazy do return mentity.nitdoc_name
+end
+
+redef class MEntitySection
+       redef var html_title is lazy do return mentity.html_name
+       redef var html_subtitle is lazy do return mentity.html_declaration
+end
+
+redef class ConcernSection
+       redef var html_title is lazy do return "in {mentity.nitdoc_name}"
+end
+
+redef class IntroArticle
+       redef var html_title = null
+
+       # Link to source to display if any.
+       var html_source_link: nullable Writable is noinit, writable
+
+       redef fun render_body do
+               var tabs = new DocTabs("{html_id}.tabs", "")
+               var comment = mentity.html_documentation
+               if mentity isa MPackage then
+                       comment = mentity.html_synopsis
+               end
+               if comment != null then
+                       tabs.add_panel new DocTabPanel("{html_tab_id}-comment", "Comment", comment)
+               end
+               for child in children do
+                       if child.is_hidden then continue
+                       var title = child.html_toc_title or else child.toc_title or else ""
+                       tabs.add_panel new DocTabPanel(child.html_tab_id, title, child)
+               end
+               var lnk = html_source_link
+               if lnk != null then
+                       tabs.drop_list.items.add new ListItem(lnk)
+               end
+               addn tabs
+       end
+end
+
+redef class ConcernsArticle
+       redef var html_title = "Concerns"
+       redef fun render_body do add concerns.html_list
+end
+
+redef class DefinitionListArticle
+       redef var html_title is lazy do
+               var title = new Template
+               title.add mentity.html_icon
+               title.add mentity.html_link
+               return title
+       end
+
+       redef var html_subtitle is lazy do return mentity.html_namespace
+       redef var html_toc_title is lazy do return mentity.html_name
+end
+
+redef class DefinitionArticle
+       redef var html_title is lazy do return mentity.html_name
+       redef var html_subtitle is lazy do return mentity.html_declaration
+
+       # Does `self` display only it's title and no body?
+       #
+       # FIXME diff hack
+       var is_no_body: Bool = false is writable
+
+       # Does `self` display only the short content as definition?
+       #
+       # FIXME diff hack
+       var is_short_comment: Bool = false is writable
+
+       # Link to source to display if any.
+       var html_source_link: nullable Writable is noinit, writable
+
+       redef fun render_body do
+               var tabs = new DocTabs("{html_id}.tabs", "")
+               if not is_no_body then
+                       var comment
+                       if is_short_comment or mentity isa MPackage then
+                               comment = mentity.html_synopsis
+                       else
+                               comment = mentity.html_documentation
+                       end
+                       if comment != null then
+                               tabs.add_panel new DocTabPanel("{html_tab_id}-comment", "Comment", comment)
+                       end
+               end
+               for child in children do
+                       if child.is_hidden then continue
+                       var title = child.html_toc_title or else child.toc_title or else ""
+                       tabs.add_panel new DocTabPanel(child.html_tab_id, title, child)
+               end
+               var lnk = html_source_link
+               if lnk != null then
+                       tabs.drop_list.items.add new ListItem(lnk)
+               end
+               addn tabs
+       end
+end
+
+redef class MEntitiesListArticle
+       redef fun render_body do
+               var lst = new UnorderedList
+               lst.css_classes.add "list-unstyled list-definition"
+               for mentity in mentities do
+                       lst.add_li mentity.html_list_item
+               end
+               add lst
+       end
+end
+
+redef class DefinitionLinArticle
+       redef fun render_body do
+               var lst = new UnorderedList
+               lst.css_classes.add "list-unstyled list-labeled"
+               for mentity in mentities do
+                       if not mentity isa MPropDef then continue # TODO handle all mentities
+                       var tpl = new Template
+                       tpl.add mentity.mclassdef.html_namespace
+                       var comment = mentity.mclassdef.html_synopsis
+                       if comment != null then
+                               tpl.add ": "
+                               tpl.add comment
+                       end
+                       var li = new ListItem(tpl)
+                       li.css_classes.add "signature"
+                       lst.add_li li
+               end
+               add lst
+       end
+end
+
+redef class GraphArticle
+       redef var html_title = null
+
+       # Graph in SVG with clickable map.
+       #
+       # This attribute is set by the `doc_render` phase who knows the context.
+       var svg: nullable String = null is writable
+
+       redef fun render_body do
+               addn "<div class=\"text-center\">"
+               var svg = self.svg
+               if svg != null then add svg
+               addn "</div>"
+       end
+end
+
+redef class ReadmeSection
+       redef var html_id is lazy do
+               return markdown_processor.emitter.decorator.strip_id(html_title.as(not null).to_s)
+       end
+
+       redef var html_title is lazy do
+               return markdown_processor.process(title.as(not null))
+       end
+end
+
+redef class ReadmeArticle
+       redef var html_id = ""
+       redef var html_title = null
+       redef var is_toc_hidden = true
+
+       redef fun render_body do
+               add markdown_processor.process(md.trim.write_to_string)
+       end
+end
+
+redef class DocumentationArticle
+       redef var html_title is lazy do
+               var synopsis = mentity.html_synopsis
+               if synopsis == null then return mentity.html_link
+               return "{mentity.html_link.write_to_string} &ndash; {synopsis.write_to_string}"
+       end
+
+       redef var html_subtitle is lazy do return null
+       redef var html_toc_title is lazy do return mentity.html_name
+       redef var is_toc_hidden is lazy do return depth > 3
+
+       redef fun render_body do
+               var tabs = new DocTabs("{html_id}.tabs", "")
+               var comment = mentity.html_comment
+               if comment != null then
+                       tabs.add_panel new DocTabPanel("{html_tab_id}-comment", "Comment", comment)
+               end
+               for child in children do
+                       if child.is_hidden then continue
+                       var title = child.html_toc_title or else child.toc_title or else ""
+                       tabs.add_panel new DocTabPanel(child.html_tab_id, title, child)
+               end
+               addn tabs
+       end
 end