X-Git-Url: http://nitlanguage.org diff --git a/src/doc/html_templates/html_templates.nit b/src/doc/html_templates/html_templates.nit index ab019c8..290f04b 100644 --- a/src/doc/html_templates/html_templates.nit +++ b/src/doc/html_templates/html_templates.nit @@ -16,3 +16,608 @@ 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 + super Template + + # Page url. + var html_url: String is writable, noinit + + # Directory where css, js and other assets can be found. + var shareurl: String is writable, noinit + + # Attributes of the body tag element. + var body_attrs = new Array[TagAttribute] + + # Top menu template if any. + var topmenu: DocTopMenu is writable, noinit + + # Sidebar template if any. + var sidebar: nullable DocSideBar = null is writable + + # Footer content if any. + var footer: nullable Writable = null is writable + + # JS scripts to append at the end of the body + var scripts = new Array[TplScript] + + # Renders the html ``. + private fun render_head do + var css = (self.shareurl / "css").html_escape + var vendors = (self.shareurl / "vendors").html_escape + + addn "" + addn "" + addn " " + addn " " + addn " " + addn " " + addn " " + addn " " + addn " " + addn " " + addn " {title.html_escape}" + addn "" + add "" + end + + # Renders the footer and content. + private fun render_content do + add root + if footer != null then + addn "" + end + end + + # Render JS scripts + private fun render_footer do + var vendors = (self.shareurl / "vendors").html_escape + var js = (self.shareurl / "js").html_escape + + addn "" + addn "" + addn "" + addn "" + addn "" + addn "" + addn "" + for script in scripts do add script + addn """""" + addn "" + addn "" + end + + # Render the whole page + redef fun rendering do + render_head + addn "
" + addn "
" + add topmenu + addn "
" + addn "
" + var sidebar = self.sidebar + if sidebar != null then + addn "
" + add sidebar + addn "
" + addn "
" + render_content + addn "
" + else + addn "
" + render_content + addn "
" + end + addn "
" + addn "
" + 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 "" + 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 "" + 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 "
" + addn "
" + add " " + add title + addn " " + addn "
" + addn "
" + add content + addn "
" + addn "
" + 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 "
" + addn html_subtitle.write_to_string + addn "
" + 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 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 "" + return + end + addn "" + render_title + render_body + addn "" + end +end + +redef class DocArticle + super BSComponent + + redef fun rendering do + if is_hidden then return + addn "" + render_title + render_body + addn "" + 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 "
" + addn "
" + render_list("Modules", mmodules) + render_list("Classes", mclasses) + render_list("Properties", mprops) + addn "
" + addn "
" + 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 "
" + 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 "
" + 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 "
" + var svg = self.svg + if svg != null then add svg + addn "
" + 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} – {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