import doc_model
private import json::static
-redef class ToolContext
- private var opt_dir = new OptionString("output directory", "-d", "--dir")
- private var opt_source = new OptionString("link for source (%f for filename, %l for first line, %L for last line)", "--source")
- private var opt_sharedir = new OptionString("directory containing nitdoc assets", "--sharedir")
- private var opt_shareurl = new OptionString("use shareurl instead of copy shared files", "--shareurl")
- private var opt_custom_title = new OptionString("custom title for homepage", "--custom-title")
- private var opt_custom_brand = new OptionString("custom link to external site", "--custom-brand")
- private var opt_custom_intro = new OptionString("custom intro text for homepage", "--custom-overview-text")
- private var opt_custom_footer = new OptionString("custom footer text", "--custom-footer-text")
-
- private var opt_github_upstream = new OptionString("Git branch where edited commits will be pulled into (ex: user:repo:branch)", "--github-upstream")
- private var opt_github_base_sha1 = new OptionString("Git sha1 of base commit used to create pull request", "--github-base-sha1")
- private var opt_github_gitdir = new OptionString("Git working directory used to resolve path name (ex: /home/me/myproject/)", "--github-gitdir")
-
- private var opt_piwik_tracker = new OptionString("Piwik tracker URL (ex: nitlanguage.org/piwik/)", "--piwik-tracker")
- private var opt_piwik_site_id = new OptionString("Piwik site ID", "--piwik-site-id")
-
- private var output_dir: String
- private var min_visibility: MVisibility
-
- redef init do
- super
-
- var opts = option_context
- opts.add_option(opt_dir, opt_source, opt_sharedir, opt_shareurl)
- opts.add_option(opt_custom_title, opt_custom_footer, opt_custom_intro, opt_custom_brand)
- opts.add_option(opt_github_upstream, opt_github_base_sha1, opt_github_gitdir)
- opts.add_option(opt_piwik_tracker, opt_piwik_site_id)
- end
-
- redef fun process_options(args) do
- super
-
- # output dir
- var output_dir = opt_dir.value
- if output_dir == null then
- output_dir = "doc"
- end
- self.output_dir = output_dir
- # github urls
- var gh_upstream = opt_github_upstream.value
- var gh_base_sha = opt_github_base_sha1.value
- var gh_gitdir = opt_github_gitdir.value
- if not gh_upstream == null or not gh_base_sha == null or not gh_gitdir == null then
- if gh_upstream == null or gh_base_sha == null or gh_gitdir == null then
- print "Error: Options {opt_github_upstream.names.first}, {opt_github_base_sha1.names.first} and {opt_github_gitdir.names.first} are required to enable the GitHub plugin"
- abort
- end
- end
- end
-end
-
-# The Nitdoc class explores the model and generate pages for each mentities found
-class Nitdoc
- var ctx: ToolContext
- var model: Model
- var mainmodule: MModule
-
- private fun init_output_dir do
- # create destination dir if it's necessary
- var output_dir = ctx.output_dir
- if not output_dir.file_exists then output_dir.mkdir
- # locate share dir
- var sharedir = ctx.opt_sharedir.value
- if sharedir == null then
- var dir = ctx.nit_dir
- sharedir = dir/"share/nitdoc"
- if not sharedir.file_exists then
- print "Error: Cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
- abort
- end
- end
- # copy shared files
- if ctx.opt_shareurl.value == null then
- sys.system("cp -r -- {sharedir.to_s.escape_to_sh}/* {output_dir.to_s.escape_to_sh}/")
- else
- sys.system("cp -r -- {sharedir.to_s.escape_to_sh}/resources/ {output_dir.to_s.escape_to_sh}/resources/")
- end
-
- end
-end
-
# Nitdoc QuickSearch list generator
#
# Create a JSON object containing links to:
return "\{\"txt\":{txt.to_json},\"url\":{url.to_json}\}"
end
end
-
-# Nitdoc base page
-# Define page structure and properties
-abstract class NitdocPage
-
- private var ctx: ToolContext
- private var model: Model
- private var mainmodule: MModule
- private var name_sorter = new MEntityNameSorter
-
- # Render the page as a html template
- fun render: Template do
- var shareurl = "."
- if ctx.opt_shareurl.value != null then
- shareurl = ctx.opt_shareurl.value.as(not null)
- end
-
- # build page
- var tpl = tpl_page
- tpl.title = tpl_title
- tpl.url = page_url
- tpl.shareurl = shareurl
- tpl.topmenu = tpl_topmenu
- tpl_content
- tpl.footer = ctx.opt_custom_footer.value
- tpl.body_attrs.add(new TagAttribute("data-bootstrap-share", shareurl))
- tpl.sidebar = tpl_sidebar
-
- # piwik tracking
- var tracker_url = ctx.opt_piwik_tracker.value
- var site_id = ctx.opt_piwik_site_id.value
- if tracker_url != null and site_id != null then
- tpl.scripts.add new TplPiwikScript(tracker_url, site_id)
- end
- return tpl
- end
-
- # URL to this page.
- fun page_url: String is abstract
-
- # Build page template
- fun tpl_page: TplPage is abstract
-
- # Build page sidebar if any
- fun tpl_sidebar: nullable TplSidebar do return null
-
- # Build page title string
- fun tpl_title: String do
- if ctx.opt_custom_title.value != null then
- return ctx.opt_custom_title.value.to_s
- end
- return "Nitdoc"
- end
-
- # Build top menu template
- fun tpl_topmenu: TplTopMenu do
- var topmenu = new TplTopMenu(page_url)
- var brand = ctx.opt_custom_brand.value
- if brand != null then
- var tpl = new Template
- tpl.add "<span class='navbar-brand'>"
- tpl.add brand
- tpl.add "</span>"
- topmenu.brand = tpl
- end
- topmenu.add_link new TplLink("index.html", "Overview")
- topmenu.add_link new TplLink("search.html", "Index")
- return topmenu
- end
-
- # Build page content template
- fun tpl_content is abstract
-
- # A (source) link template for a given location
- fun tpl_showsource(location: nullable Location): nullable String
- do
- if location == null then return null
- var source = ctx.opt_source.value
- if source == null then
- var url = location.file.filename.simplify_path
- return "<a target='_blank' title='Show source' href=\"{url.html_escape}\">View Source</a>"
- end
- # THIS IS JUST UGLY ! (but there is no replace yet)
- var x = source.split_with("%f")
- source = x.join(location.file.filename.simplify_path)
- x = source.split_with("%l")
- source = x.join(location.line_start.to_s)
- x = source.split_with("%L")
- source = x.join(location.line_end.to_s)
- source = source.simplify_path
- return "<a target='_blank' title='Show source' href=\"{source.to_s.html_escape}\">View Source</a>"
- end
-
- # MProject description template
- fun tpl_mproject_article(mproject: MProject): TplArticle do
- var article = mproject.tpl_article
- article.subtitle = mproject.tpl_declaration
- article.content = mproject.tpl_definition
- var mdoc = mproject.mdoc_or_fallback
- if mdoc != null then
- article.content = mdoc.tpl_short_comment
- end
- return article
- end
-
- # MGroup description template
- fun tpl_mgroup_article(mgroup: MGroup): TplArticle do
- var article = mgroup.tpl_article
- article.subtitle = mgroup.tpl_declaration
- article.content = mgroup.tpl_definition
- return article
- end
-
- # MModule description template
- fun tpl_mmodule_article(mmodule: MModule): TplArticle do
- var article = mmodule.tpl_article
- article.subtitle = mmodule.tpl_declaration
- article.content = mmodule.tpl_definition
- return article
- end
-
- # MClassDef description template
- fun tpl_mclass_article(mclass: MClass, mclassdefs: Array[MClassDef]): TplArticle do
- var article = mclass.tpl_article
- return article
- end
-
- # MClassDef description template
- fun tpl_mclassdef_article(mclassdef: MClassDef): TplArticle do
- var article = mclassdef.tpl_article
- if mclassdef.is_intro then article.content = null
- article.source_link = tpl_showsource(mclassdef.location)
- return article
- end
-
- # MProp description template
- #
- # `main_mpropdef`: The most important mpropdef to display
- # `local_mpropdefs`: List of other locally defined mpropdefs to display
- # `lin`: full linearization from local_mpropdefs to intro (displayed in redef tree)
- fun tpl_mprop_article(main_mpropdef: MPropDef, local_mpropdefs: Array[MPropDef],
- lin: Array[MPropDef]): TplArticle do
- var mprop = main_mpropdef.mproperty
- var article = new TplArticle(mprop.nitdoc_id)
- var title = new Template
- title.add mprop.tpl_icon
- title.add "<span id='{main_mpropdef.nitdoc_id}'></span>"
- if main_mpropdef.is_intro then
- title.add mprop.tpl_link
- title.add mprop.intro.tpl_signature
- else
- var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url
- var def_url = "{cls_url}#{mprop.nitdoc_id}"
- var lnk = new TplLink.with_title(def_url, mprop.nitdoc_name,
- "Go to introduction")
- title.add "redef "
- title.add lnk
- end
- article.title = title
- article.title_classes.add "signature"
- article.summary_title = "{mprop.nitdoc_name}"
- article.subtitle = main_mpropdef.tpl_namespace
- if main_mpropdef.mdoc_or_fallback != null then
- article.content = main_mpropdef.mdoc_or_fallback.tpl_comment
- end
- var subarticle = new TplArticle("{main_mpropdef.nitdoc_id}.redefs")
- # Add linearization
- if lin.length > 1 then
- var lin_article = new TplArticle("{main_mpropdef.nitdoc_id}.lin")
- lin_article.title = "Inheritance"
- var lst = new TplList.with_classes(["list-unstyled", "list-labeled"])
- for mpropdef in lin do
- lst.add_li mpropdef.tpl_inheritance_item
- end
- lin_article.content = lst
- subarticle.add_child lin_article
- end
- article.add_child subarticle
- return article
- end
-end
-
-# The overview page
-# Display a list of modules contained in program
-class NitdocOverview
- super NitdocPage
-
- private var page = new TplPage
- redef fun tpl_page do return page
-
- private var sidebar = new TplSidebar
- redef fun tpl_sidebar do return sidebar
-
- redef fun tpl_title do
- if ctx.opt_custom_title.value != null then
- return ctx.opt_custom_title.value.to_s
- else
- return "Overview"
- end
- end
-
- redef fun page_url do return "index.html"
-end
-
-# The search page
-# Display a list of modules, classes and properties
-class NitdocSearch
- super NitdocPage
-
- private var page = new TplPage
- redef fun tpl_page do return page
-
- redef fun tpl_title do return "Index"
-
- redef fun page_url do return "search.html"
-end
-
-# A group page
-# Display a flattened view of the group
-class NitdocGroup
- super NitdocPage
-
- private var mgroup: MGroup
-
- private var page = new TplPage
- redef fun tpl_page do return page
-
- private var sidebar = new TplSidebar
- redef fun tpl_sidebar do return sidebar
-
- redef fun tpl_title do return mgroup.nitdoc_name
-
- redef fun page_url do return mgroup.nitdoc_url
-
- redef fun tpl_topmenu do
- var topmenu = super
- var mproject = mgroup.mproject
- if not mgroup.is_root then
- topmenu.add_link new TplLink(mproject.nitdoc_url, mproject.nitdoc_name)
- end
- topmenu.add_link new TplLink(page_url, mproject.nitdoc_name)
- return topmenu
- end
-
- # Class list to display in sidebar
- fun tpl_sidebar_mclasses do
- var mclasses = new HashSet[MClass]
- mclasses.add_all intros
- mclasses.add_all redefs
- if mclasses.is_empty then return
- var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
-
- var sorted = mclasses.to_a
- name_sorter.sort(sorted)
- for mclass in sorted do
- list.add_li tpl_sidebar_item(mclass)
- end
- tpl_sidebar.boxes.add new TplSideBox.with_content("All classes", list)
- end
-
- private fun tpl_sidebar_item(def: MClass): TplListItem do
- var classes = def.intro.tpl_css_classes.to_a
- if intros.has(def) then
- classes.add "intro"
- else
- classes.add "redef"
- end
- var lnk = new Template
- lnk.add new TplLabel.with_classes(classes)
- lnk.add def.tpl_link
- return new TplListItem.with_content(lnk)
- end
-end
-
-# A module page
-# Display the list of introduced and redefined classes in module
-class NitdocModule
- super NitdocPage
-
- private var mmodule: MModule
-
- private var page = new TplPage
- redef fun tpl_page do return page
-
- private var sidebar = new TplSidebar
- redef fun tpl_sidebar do return sidebar
-
- redef fun tpl_title do return mmodule.nitdoc_name
- redef fun page_url do return mmodule.nitdoc_url
-
- redef fun tpl_topmenu do
- var topmenu = super
- var mproject = mmodule.mgroup.mproject
- topmenu.add_link new TplLink(mproject.nitdoc_url, mproject.nitdoc_name)
- topmenu.add_link new TplLink(page_url, mmodule.nitdoc_name)
- return topmenu
- end
-
- # Class list to display in sidebar
- fun tpl_sidebar_mclasses do
- var mclasses = new HashSet[MClass]
- mclasses.add_all mmodule.filter_intro_mclasses(ctx.min_visibility)
- mclasses.add_all mmodule.filter_redef_mclasses(ctx.min_visibility)
- if mclasses.is_empty then return
- var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
-
- var sorted = mclasses.to_a
- name_sorter.sort(sorted)
- for mclass in sorted do
- list.add_li tpl_sidebar_item(mclass)
- end
- tpl_sidebar.boxes.add new TplSideBox.with_content("All classes", list)
- end
-
- private fun tpl_sidebar_item(def: MClass): TplListItem do
- var classes = def.intro.tpl_css_classes.to_a
- if def.intro_mmodule == mmodule then
- classes.add "intro"
- else
- classes.add "redef"
- end
- var lnk = new Template
- lnk.add new TplLabel.with_classes(classes)
- lnk.add def.tpl_link
- return new TplListItem.with_content(lnk)
- end
-end
-
-# A class page
-# Display a list properties defined or redefined for this class
-class NitdocClass
- super NitdocPage
-
- private var mclass: MClass
-
- private var page = new TplPage
- redef fun tpl_page do return page
-
- private var sidebar = new TplSidebar
- redef fun tpl_sidebar do return sidebar
-
- redef fun tpl_title do return "{mclass.nitdoc_name}{mclass.tpl_signature.write_to_string}"
- redef fun page_url do return mclass.nitdoc_url
-
- redef fun tpl_topmenu do
- var topmenu = super
- var mproject = mclass.intro_mmodule.mgroup.mproject
- topmenu.add_link new TplLink("{mproject.nitdoc_url}", "{mproject.nitdoc_name}")
- topmenu.add_link new TplLink(page_url, mclass.nitdoc_name)
- return topmenu
- end
-
- # Property list to display in sidebar
- fun tpl_sidebar_properties do
- var by_kind = new PropertiesByKind.with_elements(mclass_inherited_mprops)
- var summary = new TplList.with_classes(["list-unstyled"])
-
- by_kind.sort_groups(name_sorter)
- for g in by_kind.groups do tpl_sidebar_list(g, summary)
- tpl_sidebar.boxes.add new TplSideBox.with_content("All properties", summary)
- end
-
- private fun tpl_sidebar_list(mprops: PropertyGroup[MProperty], summary: TplList) do
- if mprops.is_empty then return
- var entry = new TplListItem.with_content(mprops.title)
- var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
- for mprop in mprops do
- list.add_li tpl_sidebar_item(mprop)
- end
- entry.append list
- summary.elts.add entry
- end
-
- private fun tpl_sidebar_item(mprop: MProperty): TplListItem do
- var classes = mprop.intro.tpl_css_classes.to_a
- if not mprops2mdefs.has_key(mprop) then
- classes.add "inherit"
- var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url
- var def_url = "{cls_url}#{mprop.nitdoc_id}"
- var lnk = new TplLink(def_url, mprop.nitdoc_name)
- var mdoc = mprop.intro.mdoc_or_fallback
- if mdoc != null then lnk.title = mdoc.short_comment
- var item = new Template
- item.add new TplLabel.with_classes(classes)
- item.add lnk
- return new TplListItem.with_content(item)
- end
- var defs = mprops2mdefs[mprop]
- if defs.has(mprop.intro) then
- classes.add "intro"
- else
- classes.add "redef"
- end
- var lnk = new Template
- lnk.add new TplLabel.with_classes(classes)
- lnk.add mprop.tpl_anchor
- return new TplListItem.with_content(lnk)
- end
-end
-
-# A MProperty page
-class NitdocProperty
- super NitdocPage
-
- private var mproperty: MProperty
-
- private var page = new TplPage
- redef fun tpl_page do return page
-
- private var sidebar = new TplSidebar
- redef fun tpl_sidebar do return sidebar
-
- redef fun tpl_title do
- return "{mproperty.nitdoc_name}{mproperty.tpl_signature.write_to_string}"
- end
-
- redef fun page_url do return mproperty.nitdoc_url
-
- redef fun tpl_topmenu do
- var topmenu = super
- var mmodule = mproperty.intro_mclassdef.mmodule
- var mproject = mmodule.mgroup.mproject
- var mclass = mproperty.intro_mclassdef.mclass
- topmenu.add_link new TplLink("{mproject.nitdoc_url}", "{mproject.nitdoc_name}")
- topmenu.add_link new TplLink("{mclass.nitdoc_url}", "{mclass.nitdoc_name}")
- topmenu.add_link new TplLink(page_url, mproperty.nitdoc_name)
- return topmenu
- end
-end
-
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Render the DocModel pages as HTML pages.
+#
+# FIXME this module is all f*cked up to maintain compatibility with
+# the original `doc_templates` and `doc_model` modules.
+# This will change in further refactorings.
+module doc_html
+
+import doc_structure
+import doc_hierarchies
+import doc_intros_redefs
+import doc_graphs
+
+redef class ToolContext
+
+ # File pattern used to link documentation to source code.
+ var opt_source = new OptionString("link for source (%f for filename, " +
+ "%l for first line, %L for last line)", "--source")
+
+ # Directory where the CSS and JS is stored.
+ var opt_sharedir = new OptionString("directory containing nitdoc assets", "--sharedir")
+
+ # Use a shareurl instead of copy shared files.
+ #
+ # This is usefull if you don't want to store the Nitdoc templates with your
+ # documentation.
+ var opt_shareurl = new OptionString("use shareurl instead of copy shared files", "--shareurl")
+
+ # Use a custom title for the homepage.
+ var opt_custom_title = new OptionString("custom title for homepage", "--custom-title")
+
+ # Display a custom brand or logo in the documentation top menu.
+ var opt_custom_brand = new OptionString("custom link to external site", "--custom-brand")
+
+ # Display a custom introduction text before the projects overview.
+ var opt_custom_intro = new OptionString("custom intro text for homepage", "--custom-overview-text")
+ # Display a custom footer on each documentation page.
+ #
+ # Generally used to display the documentation or product version.
+ var opt_custom_footer = new OptionString("custom footer text", "--custom-footer-text")
+
+ # Piwik tracker URL.
+ #
+ # If you want to monitor your visitors.
+ var opt_piwik_tracker = new OptionString("Piwik tracker URL (ex: nitlanguage.org/piwik/)", "--piwik-tracker")
+
+ # Piwik tracker site id.
+ var opt_piwik_site_id = new OptionString("Piwik site ID", "--piwik-site-id")
+
+ # These options are not currently used in Nitdoc.
+
+ # FIXME redo the plugin
+ var opt_github_upstream = new OptionString("Git branch where edited commits will be pulled into (ex: user:repo:branch)", "--github-upstream")
+ # FIXME redo the plugin
+ var opt_github_base_sha1 = new OptionString("Git sha1 of base commit used to create pull request", "--github-base-sha1")
+ # FIXME redo the plugin
+ var opt_github_gitdir = new OptionString("Git working directory used to resolve path name (ex: /home/me/myproject/)", "--github-gitdir")
+
+ redef init do
+ super
+
+ option_context.add_option(
+ opt_source, opt_sharedir, opt_shareurl, opt_custom_title,
+ opt_custom_footer, opt_custom_intro, opt_custom_brand,
+ opt_github_upstream, opt_github_base_sha1, opt_github_gitdir,
+ opt_piwik_tracker, opt_piwik_site_id)
+ end
+
+ redef fun process_options(args) do
+ super
+ var upstream = opt_github_upstream
+ var base_sha = opt_github_base_sha1
+ var git_dir = opt_github_gitdir
+ var opts = [upstream.value, base_sha.value, git_dir.value]
+ if not opts.has_only(null) and opts.has(null) then
+ print "Error: Options {upstream.names.first}, " +
+ "{base_sha.names.first} and {git_dir.names.first} " +
+ "are required to enable the GitHub plugin"
+ exit 1
+ end
+ end
+end
+
+# Render the Nitdoc as a HTML website.
+class RenderHTMLPhase
+ super DocPhase
+
+ # Used to sort sidebar elements by name.
+ var name_sorter = new MEntityNameSorter
+
+ redef fun apply do
+ init_output_dir
+ for page in doc.pages do
+ page.render(self, doc).write_to_file("{ctx.output_dir.to_s}/{page.page_url}")
+ end
+ end
+
+ # Creates the output directory and imports assets files form `resources/`.
+ fun init_output_dir do
+ # create destination dir if it's necessary
+ var output_dir = ctx.output_dir
+ if not output_dir.file_exists then output_dir.mkdir
+ # locate share dir
+ var sharedir = ctx.opt_sharedir.value
+ if sharedir == null then
+ var dir = ctx.nit_dir
+ sharedir = dir/"share/nitdoc"
+ if not sharedir.file_exists then
+ print "Error: Cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
+ abort
+ end
+ end
+ # copy shared files
+ if ctx.opt_shareurl.value == null then
+ sys.system("cp -r -- {sharedir.to_s.escape_to_sh}/* {output_dir.to_s.escape_to_sh}/")
+ else
+ sys.system("cp -r -- {sharedir.to_s.escape_to_sh}/resources/ {output_dir.to_s.escape_to_sh}/resources/")
+ end
+
+ end
+
+ # A source link template for a given location
+ fun tpl_showsource(location: nullable Location): nullable String
+ do
+ if location == null then return null
+ var source = ctx.opt_source.value
+ if source == null then
+ var url = location.file.filename.simplify_path
+ return "<a target='_blank' title='Show source' href=\"{url.html_escape}\">View Source</a>"
+ end
+ # THIS IS JUST UGLY ! (but there is no replace yet)
+ var x = source.split_with("%f")
+ source = x.join(location.file.filename.simplify_path)
+ x = source.split_with("%l")
+ source = x.join(location.line_start.to_s)
+ x = source.split_with("%L")
+ source = x.join(location.line_end.to_s)
+ source = source.simplify_path
+ return "<a target='_blank' title='Show source' href=\"{source.to_s.html_escape}\">View Source</a>"
+ end
+end
+
+redef class DocPage
+
+ # Render the page as a html template.
+ private fun render(v: RenderHTMLPhase, doc: DocModel): TplPage do
+ var shareurl = "."
+ if v.ctx.opt_shareurl.value != null then
+ shareurl = v.ctx.opt_shareurl.value.as(not null)
+ end
+
+ # build page
+ var tpl = new TplPage
+ tpl.title = tpl_title(v, doc)
+ tpl.url = page_url
+ tpl.shareurl = shareurl
+ tpl.topmenu = tpl_topmenu(v, doc)
+ tpl.add_section tpl_content(v, doc)
+ tpl.footer = v.ctx.opt_custom_footer.value
+ tpl.body_attrs.add(new TagAttribute("data-bootstrap-share", shareurl))
+ tpl.sidebar = tpl_sidebar(v, doc)
+
+ # piwik tracking
+ var tracker_url = v.ctx.opt_piwik_tracker.value
+ var site_id = v.ctx.opt_piwik_site_id.value
+ if tracker_url != null and site_id != null then
+ tpl.scripts.add new TplPiwikScript(tracker_url, site_id)
+ end
+ return tpl
+ end
+
+ # FIXME diff hack
+ # all properties below are roughly copied from `doc_pages`
+
+ # URL to this page.
+ fun page_url: String is abstract
+
+ # Build page sidebar if any
+ fun tpl_sidebar(v: RenderHTMLPhase, doc: DocModel): nullable TplSidebar do return null
+
+ # Build page title string
+ fun tpl_title(v: RenderHTMLPhase, doc: DocModel): String do
+ if v.ctx.opt_custom_title.value != null then
+ return v.ctx.opt_custom_title.value.to_s
+ end
+ return "Nitdoc"
+ end
+
+ # Build top menu template
+ fun tpl_topmenu(v: RenderHTMLPhase, doc: DocModel): TplTopMenu do
+ var topmenu = new TplTopMenu(page_url)
+ var brand = v.ctx.opt_custom_brand.value
+ if brand != null then
+ var tpl = new Template
+ tpl.add "<span class='navbar-brand'>"
+ tpl.add brand
+ tpl.add "</span>"
+ topmenu.brand = tpl
+ end
+ topmenu.add_link new TplLink("index.html", "Overview")
+ topmenu.add_link new TplLink("search.html", "Index")
+ return topmenu
+ end
+
+ # Build page content template
+ fun tpl_content(v: RenderHTMLPhase, doc: DocModel): TplSection is abstract
+end
+
+redef class OverviewPage
+ redef fun page_url do return "index.html"
+
+ redef fun tpl_title(v, doc) do
+ if v.ctx.opt_custom_title.value != null then
+ return v.ctx.opt_custom_title.value.to_s
+ else
+ return "Overview"
+ end
+ end
+
+ # TODO this should be done in StructurePhase.
+ redef fun tpl_content(v, doc) do
+ # intro text
+ var section = new TplSection.with_title("overview", tpl_title(v, doc))
+ var article = new TplArticle("intro")
+ if v.ctx.opt_custom_intro.value != null then
+ article.content = v.ctx.opt_custom_intro.value.to_s
+ end
+ section.add_child article
+ # Projects list
+ var mprojects = doc.model.mprojects.to_a
+ var sorter = new MConcernRankSorter
+ sorter.sort mprojects
+ var ssection = new TplSection.with_title("projects", "Projects")
+ for mproject in mprojects do
+ var sarticle = mproject.tpl_article
+ sarticle.subtitle = mproject.tpl_declaration
+ sarticle.content = mproject.tpl_definition
+ var mdoc = mproject.mdoc_or_fallback
+ if mdoc != null then
+ sarticle.content = mdoc.tpl_short_comment
+ end
+ ssection.add_child sarticle
+ end
+ section.add_child ssection
+ return section
+ end
+
+ redef fun tpl_sidebar(v, doc) do return new TplSidebar
+end
+
+redef class SearchPage
+ redef fun page_url do return "search.html"
+ redef fun tpl_title(v, doc) do return "Index"
+
+ # TODO this should be done in StructurePhase.
+ redef fun tpl_content(v, doc) do
+ var tpl = new TplSearchPage("search_all")
+ var section = new TplSection("search")
+ # title
+ tpl.title = "Index"
+ # modules list
+ for mmodule in modules_list(v, doc) do
+ tpl.modules.add mmodule.tpl_link
+ end
+ # classes list
+ for mclass in classes_list(v, doc) do
+ tpl.classes.add mclass.tpl_link
+ end
+ # properties list
+ for mproperty in mprops_list(v, doc) do
+ var m = new Template
+ m.add mproperty.intro.tpl_link
+ m.add " ("
+ m.add mproperty.intro.mclassdef.mclass.tpl_link
+ m.add ")"
+ tpl.props.add m
+ end
+ section.add_child tpl
+ return section
+ end
+
+ # Extract mmodule list to display (sorted by name)
+ private fun modules_list(v: RenderHTMLPhase, doc: DocModel): Array[MModule] do
+ var sorted = new Array[MModule]
+ for mmodule in doc.model.mmodule_importation_hierarchy do
+ if mmodule.is_fictive or mmodule.is_test_suite then continue
+ sorted.add mmodule
+ end
+ v.name_sorter.sort(sorted)
+ return sorted
+ end
+
+ # Extract mclass list to display (sorted by name)
+ private fun classes_list(v: RenderHTMLPhase, doc: DocModel): Array[MClass] do
+ var sorted = doc.mclasses.to_a
+ v.name_sorter.sort(sorted)
+ return sorted
+ end
+
+ # Extract mproperty list to display (sorted by name)
+ private fun mprops_list(v: RenderHTMLPhase, doc: DocModel): Array[MProperty] do
+ var sorted = doc.mproperties.to_a
+ v.name_sorter.sort(sorted)
+ return sorted
+ end
+end
+
+redef class MEntityPage
+ redef fun page_url do return mentity.nitdoc_url
+ redef fun tpl_title(v, doc) do return mentity.nitdoc_name
+ redef fun tpl_content(v, doc) do return root.start_rendering(v, doc, self)
+end
+
+# FIXME all clases below are roughly copied from `doc_pages` and adapted to new
+# doc phases. This is to preserve the compatibility with the current
+# `doc_templates` module.
+
+redef class MGroupPage
+ redef fun tpl_topmenu(v, doc) do
+ var topmenu = super
+ var mproject = mentity.mproject
+ if not mentity.is_root then
+ topmenu.add_link new TplLink(mproject.nitdoc_url, mproject.nitdoc_name)
+ end
+ topmenu.add_link new TplLink(page_url, mproject.nitdoc_name)
+ return topmenu
+ end
+
+ redef fun tpl_sidebar(v, doc) do
+ var sidebar = new TplSidebar
+ var mclasses = new HashSet[MClass]
+ mclasses.add_all intros
+ mclasses.add_all redefs
+ if mclasses.is_empty then return sidebar
+ var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
+
+ var sorted = mclasses.to_a
+ v.name_sorter.sort(sorted)
+ for mclass in sorted do
+ list.add_li tpl_sidebar_item(mclass)
+ end
+ sidebar.boxes.add new TplSideBox.with_content("All classes", list)
+ return sidebar
+ end
+
+ private fun tpl_sidebar_item(def: MClass): TplListItem do
+ var classes = def.intro.tpl_css_classes.to_a
+ if intros.has(def) then
+ classes.add "intro"
+ else
+ classes.add "redef"
+ end
+ var lnk = new Template
+ lnk.add new TplLabel.with_classes(classes)
+ lnk.add def.tpl_link
+ return new TplListItem.with_content(lnk)
+ end
+end
+
+redef class MModulePage
+ redef fun tpl_topmenu(v, doc) do
+ var topmenu = super
+ var mproject = mentity.mproject
+ topmenu.add_link new TplLink(mproject.nitdoc_url, mproject.nitdoc_name)
+ topmenu.add_link new TplLink(mentity.nitdoc_url, mentity.nitdoc_name)
+ return topmenu
+ end
+
+ # Class list to display in sidebar
+ redef fun tpl_sidebar(v, doc) do
+ # TODO filter here?
+ var sidebar = new TplSidebar
+ var mclasses = new HashSet[MClass]
+ mclasses.add_all mentity.filter_intro_mclasses(v.ctx.min_visibility)
+ mclasses.add_all mentity.filter_redef_mclasses(v.ctx.min_visibility)
+ if mclasses.is_empty then return sidebar
+ var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
+
+ var sorted = mclasses.to_a
+ v.name_sorter.sort(sorted)
+ for mclass in sorted do
+ list.add_li tpl_sidebar_item(mclass)
+ end
+ sidebar.boxes.add new TplSideBox.with_content("All classes", list)
+ return sidebar
+ end
+
+ private fun tpl_sidebar_item(def: MClass): TplListItem do
+ var classes = def.intro.tpl_css_classes.to_a
+ if def.intro_mmodule == self.mentity then
+ classes.add "intro"
+ else
+ classes.add "redef"
+ end
+ var lnk = new Template
+ lnk.add new TplLabel.with_classes(classes)
+ lnk.add def.tpl_link
+ return new TplListItem.with_content(lnk)
+ end
+end
+
+redef class MClassPage
+
+ redef fun tpl_title(v, doc) do
+ return "{mentity.nitdoc_name}{mentity.tpl_signature.write_to_string}"
+ end
+
+ redef fun tpl_topmenu(v, doc) do
+ var topmenu = super
+ var mproject = mentity.intro_mmodule.mgroup.mproject
+ topmenu.add_link new TplLink("{mproject.nitdoc_url}", "{mproject.nitdoc_name}")
+ topmenu.add_link new TplLink(page_url, mentity.nitdoc_name)
+ return topmenu
+ end
+
+ redef fun tpl_sidebar(v, doc) do
+ var sidebar = new TplSidebar
+ var by_kind = new PropertiesByKind.with_elements(mclass_inherited_mprops(v, doc))
+ var summary = new TplList.with_classes(["list-unstyled"])
+
+ by_kind.sort_groups(v.name_sorter)
+ for g in by_kind.groups do tpl_sidebar_list(g, summary)
+ sidebar.boxes.add new TplSideBox.with_content("All properties", summary)
+ return sidebar
+ end
+
+ private fun tpl_sidebar_list(mprops: PropertyGroup[MProperty], summary: TplList) do
+ if mprops.is_empty then return
+ var entry = new TplListItem.with_content(mprops.title)
+ var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
+ for mprop in mprops do
+ list.add_li tpl_sidebar_item(mprop)
+ end
+ entry.append list
+ summary.elts.add entry
+ end
+
+ private fun tpl_sidebar_item(mprop: MProperty): TplListItem do
+ var classes = mprop.intro.tpl_css_classes.to_a
+ if not mprop_is_local(mprop) then
+ classes.add "inherit"
+ var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url
+ var def_url = "{cls_url}#{mprop.nitdoc_id}"
+ var lnk = new TplLink(def_url, mprop.nitdoc_name)
+ var mdoc = mprop.intro.mdoc_or_fallback
+ if mdoc != null then lnk.title = mdoc.short_comment
+ var item = new Template
+ item.add new TplLabel.with_classes(classes)
+ item.add lnk
+ return new TplListItem.with_content(item)
+ end
+ if mpropdefs.has(mprop.intro) then
+ classes.add "intro"
+ else
+ classes.add "redef"
+ end
+ var lnk = new Template
+ lnk.add new TplLabel.with_classes(classes)
+ lnk.add mprop.tpl_anchor
+ return new TplListItem.with_content(lnk)
+ end
+
+ private fun mclass_inherited_mprops(v: RenderHTMLPhase, doc: DocModel): Set[MProperty] do
+ var res = new HashSet[MProperty]
+ var local = mentity.local_mproperties(v.ctx.min_visibility)
+ for mprop in mentity.inherited_mproperties(doc.mainmodule, v.ctx.min_visibility) do
+ if local.has(mprop) then continue
+ #if mprop isa MMethod and mprop.is_init then continue
+ if mprop.intro.mclassdef.mclass.name == "Object" and
+ (mprop.visibility == protected_visibility or
+ mprop.intro.mclassdef.mmodule.name != "kernel") then continue
+ res.add mprop
+ end
+ res.add_all local
+ return res
+ end
+
+ private fun mprop_is_local(mprop: MProperty): Bool do
+ for mpropdef in mprop.mpropdefs do
+ if self.mpropdefs.has(mpropdef) then return true
+ end
+ return false
+ end
+end
+
+redef class MPropertyPage
+ redef fun tpl_topmenu(v, doc) do
+ var topmenu = super
+ var mmodule = mentity.intro_mclassdef.mmodule
+ var mproject = mmodule.mgroup.mproject
+ var mclass = mentity.intro_mclassdef.mclass
+ topmenu.add_link new TplLink("{mproject.nitdoc_url}", "{mproject.nitdoc_name}")
+ topmenu.add_link new TplLink("{mclass.nitdoc_url}", "{mclass.nitdoc_name}")
+ topmenu.add_link new TplLink(page_url, mentity.nitdoc_name)
+ return topmenu
+ end
+
+ redef fun tpl_title(v, doc) do
+ return "{mentity.nitdoc_name}{mentity.tpl_signature.write_to_string}"
+ end
+
+ redef fun tpl_sidebar(v, doc) do return new TplSidebar
+end
+
+redef class DocComposite
+ # Render this DocComposite as HTML.
+ #
+ # FIXME needed to maintain TplSection compatibility.
+ fun render(v: RenderHTMLPhase, doc: DocModel, page: MEntityPage, parent: TplSectionElt) is abstract
+end
+
+redef class DocRoot
+
+ # Start the rendering from root.
+ #
+ # FIXME needed to maintain TplSection compatibility.
+ fun start_rendering(v: RenderHTMLPhase, doc: DocModel, page: MEntityPage): TplSection do
+ var section = new TplSection("top")
+ var mentity = page.mentity
+ section.title = mentity.nitdoc_name
+ section.subtitle = mentity.tpl_declaration
+ # FIXME ugly hack to avoid diff
+ if mentity isa MGroup and mentity.is_root then
+ section.title = mentity.mproject.nitdoc_name
+ section.subtitle = mentity.mproject.tpl_declaration
+ else if mentity isa MClass then
+ section.title = "{mentity.nitdoc_name}{mentity.tpl_signature.write_to_string}"
+ else if mentity isa MProperty then
+ section.title = "{mentity.nitdoc_name}{mentity.intro.tpl_signature.write_to_string}"
+ section.subtitle = mentity.tpl_namespace
+ section.summary_title = mentity.nitdoc_name
+ end
+ render(v, doc, page, section)
+ return section
+ end
+
+ redef fun render(v, doc, page, parent) do
+ for child in children do
+ child.render(v, doc, page, parent)
+ end
+ end
+end
+
+redef class ConcernSection
+ redef fun render(v, doc, page, parent) do
+ var section = new TplSection(mentity.nitdoc_id)
+ var mentity = self.mentity
+ # FIXME hideous hacks to avoid diff
+ if page.mentity isa MModule and mentity isa MModule then
+ render_concern_mmodule(page, section, mentity)
+ else if page.mentity isa MClass and mentity isa MModule then
+ render_concern_other(page, section, mentity)
+ else if page.mentity isa MProperty and mentity isa MModule then
+ render_concern_other(page, section, mentity)
+ end
+ for child in children do
+ child.render(v, doc, page, section)
+ end
+ parent.add_child section
+ end
+
+ private fun render_concern_mmodule(page: MEntityPage, section: TplSection, mmodule: MModule) do
+ var title = new Template
+ if mmodule == page.mentity then
+ title.add "in "
+ section.summary_title = "in {mmodule.nitdoc_name}"
+ else
+ title.add "from "
+ section.summary_title = "from {mmodule.nitdoc_name}"
+ end
+ title.add mmodule.tpl_namespace
+ section.title = title
+ end
+
+ private fun render_concern_other(page: MEntityPage, section: TplSection, mmodule: MModule) do
+ var title = new Template
+ title.add "in "
+ title.add mmodule.tpl_namespace
+ section.title = title
+ section.summary_title = "in {mmodule.nitdoc_name}"
+ end
+end
+
+redef class IntroArticle
+ redef fun render(v, doc, page, parent) do
+ var article = new TplArticle("intro")
+ var mentity = self.mentity
+ if mentity isa MModule then
+ article.source_link = v.tpl_showsource(mentity.location)
+ else if mentity isa MClassDef then
+ article.source_link = v.tpl_showsource(mentity.location)
+ else if mentity isa MPropDef then
+ article.source_link = v.tpl_showsource(mentity.location)
+ end
+ # article.subtitle = mentity.tpl_declaration
+ # FIXME diff hack
+ if mentity isa MProperty then
+ # intro title
+ var ns = mentity.intro.mclassdef.mmodule.tpl_namespace
+ var section = new TplSection("intro")
+ var title = new Template
+ title.add "Introduction in "
+ title.add ns
+ section.title = title
+ section.summary_title = "Introduction"
+ var intro = mentity.intro.tpl_article
+ intro.source_link = v.tpl_showsource(mentity.intro.location)
+ section.add_child intro
+ parent.add_child section
+ else
+ article.content = mentity.tpl_definition
+ parent.add_child article
+ end
+ end
+end
+
+redef class ConcernsArticle
+ redef fun render(v, doc, page, parent) do
+ # FIXME diff hack
+ var title = "concerns"
+ if page.mentity isa MProperty then title = "Concerns"
+ parent.add_child new TplArticle.
+ with_content(title, "Concerns", concerns.to_tpl)
+ end
+end
+
+redef class DefinitionArticle
+ redef fun render(v, doc, page, parent) do
+ var article: TplArticle
+ var mentity = self.mentity
+ # FIXME hideous hacks...
+ if mentity isa MModule then
+ article = mentity.tpl_article
+ article.subtitle = mentity.tpl_declaration
+ article.content = mentity.tpl_definition
+ else if mentity isa MClass then
+ article = make_mclass_article(v, page)
+ else if mentity isa MClassDef then
+ article = make_mclassdef_article(v, page)
+ article.source_link = v.tpl_showsource(mentity.location)
+ else if mentity isa MPropDef and page.mentity isa MClass then
+ article = make_mpropdef_article(v, doc, page)
+ else
+ article = mentity.tpl_article
+ article.subtitle = mentity.tpl_declaration
+ if mentity isa MPropDef then
+ article.source_link = v.tpl_showsource(mentity.location)
+ end
+ if not mentity isa MVirtualTypeProp then
+ # article.content = mentity.tpl_comment
+ end
+ end
+ for child in children do
+ child.render(v, doc, page, article)
+ end
+ parent.add_child article
+ end
+
+ # FIXME avoid diff while preserving TplArticle compatibility.
+
+ private fun make_mclass_article(v: RenderHTMLPhase, page: MEntityPage): TplArticle do
+ var article = mentity.tpl_article
+ article.subtitle = mentity.tpl_namespace
+ article.content = null
+ return article
+ end
+
+ private fun make_mclassdef_article(v: RenderHTMLPhase, page: MEntityPage): TplArticle do
+ var mclassdef = mentity.as(MClassDef)
+ var article = mentity.tpl_article
+ if mclassdef.is_intro and mclassdef.mmodule != page.mentity then
+ article = mentity.tpl_short_article
+ end
+ var title = new Template
+ title.add "in "
+ title.add mclassdef.mmodule.tpl_namespace
+ article.subtitle = title
+ return article
+ end
+
+ private fun make_mpropdef_article(v: RenderHTMLPhase, doc: DocModel, page: MEntityPage): TplArticle
+ do
+ var mpropdef = mentity.as(MPropDef)
+ var mprop = mpropdef.mproperty
+ var article = new TplArticle(mprop.nitdoc_id)
+ var title = new Template
+ title.add mprop.tpl_icon
+ title.add "<span id='{mpropdef.nitdoc_id}'></span>"
+ if mpropdef.is_intro then
+ title.add mprop.tpl_link
+ title.add mprop.intro.tpl_signature
+ else
+ var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url
+ var def_url = "{cls_url}#{mprop.nitdoc_id}"
+ var lnk = new TplLink.with_title(def_url, mprop.nitdoc_name,
+ "Go to introduction")
+ title.add "redef "
+ title.add lnk
+ end
+ article.title = title
+ article.title_classes.add "signature"
+ article.summary_title = "{mprop.nitdoc_name}"
+ article.subtitle = mpropdef.tpl_namespace
+ if mpropdef.mdoc_or_fallback != null then
+ article.content = mpropdef.mdoc_or_fallback.tpl_comment
+ end
+ # TODO move in its own phase? let's see after doc_template refactoring.
+ # Add linearization
+ var all_defs = new HashSet[MPropDef]
+ for local_def in local_defs(page.as(MClassPage), mprop) do
+ all_defs.add local_def
+ var smpropdef = local_def
+ while not smpropdef.is_intro do
+ smpropdef = smpropdef.lookup_next_definition(
+ doc.mainmodule, smpropdef.mclassdef.bound_mtype)
+ all_defs.add smpropdef
+ end
+ end
+ var lin = all_defs.to_a
+ doc.mainmodule.linearize_mpropdefs(lin)
+ if lin.length > 1 then
+ var lin_article = new TplArticle("{mpropdef.nitdoc_id}.lin")
+ lin_article.title = "Inheritance"
+ var lst = new TplList.with_classes(["list-unstyled", "list-labeled"])
+ for smpropdef in lin do
+ lst.add_li smpropdef.tpl_inheritance_item
+ end
+ lin_article.content = lst
+ article.add_child lin_article
+ end
+ return article
+ end
+
+ # Filter `page.mpropdefs` for this `mpropertie`.
+ #
+ # FIXME compatability with current templates.
+ private fun local_defs(page: MClassPage, mproperty: MProperty): HashSet[MPropDef] do
+ var mpropdefs = new HashSet[MPropDef]
+ for mpropdef in page.mpropdefs do
+ if mpropdef.mproperty == mproperty then
+ mpropdefs.add mpropdef
+ end
+ end
+ return mpropdefs
+ end
+end
+
+redef class IntrosRedefsListArticle
+ redef fun render(v, doc, page, parent) do
+ if mentities.is_empty then return
+ var title = list_title
+ # FIXME diff hack
+ var id = "intros"
+ if title == "Redefines" then id = "redefs"
+ var article = new TplArticle.with_title("{mentity.nitdoc_id}.{id}", title)
+ var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
+ for mentity in mentities do
+ list.add_li mentity.tpl_list_item
+ end
+ article.content = list
+ parent.add_child article
+ end
+end
+
+# FIXME compatibility with doc_templates.
+redef class ImportationListSection
+ redef fun render(v, doc, page, parent) do
+ var section = new TplSection.with_title("dependencies", "Dependencies")
+ for child in children do
+ child.render(v, doc, page, section)
+ end
+ parent.add_child section
+ end
+end
+
+# FIXME compatibility with doc_templates.
+redef class InheritanceListSection
+ redef fun render(v, doc, page, parent) do
+ var section = new TplSection.with_title("inheritance", "Inheritance")
+ for child in children do
+ child.render(v, doc, page, section)
+ end
+ parent.add_child section
+ end
+end
+
+# FIXME compatibility with doc_templates.
+redef class HierarchyListArticle
+ redef fun render(v, doc, page, parent) do
+ if mentities.is_empty then return
+ var title = list_title
+ var id = list_title.to_lower
+ var article = new TplArticle.with_title(id, title)
+ var list = new TplList.with_classes(["list-unstyled", "list-definition"])
+ for mentity in mentities do
+ list.elts.add mentity.tpl_list_item
+ end
+ article.content = list
+ parent.add_child article
+ end
+end
+
+redef class GraphArticle
+ redef fun render(v, doc, page, parent) do
+ var output_dir = v.ctx.output_dir
+ var path = output_dir / id
+ var path_sh = path.escape_to_sh
+ var file = new OFStream.open("{path}.dot")
+ file.write(dot)
+ file.close
+ sys.system("\{ test -f {path_sh}.png && test -f {path_sh}.s.dot && diff -- {path_sh}.dot {path_sh}.s.dot >/dev/null 2>&1 ; \} || \{ cp -- {path_sh}.dot {path_sh}.s.dot && dot -Tpng -o{path_sh}.png -Tcmapx -o{path_sh}.map {path_sh}.s.dot ; \}")
+ var fmap = new IFStream.open("{path}.map")
+ var map = fmap.read_all
+ fmap.close
+
+ var article = new TplArticle("graph")
+ var alt = ""
+ # FIXME diff hack
+ # if title != null then
+ # article.title = title
+ # alt = "alt='{title.html_escape}'"
+ # end
+ article.css_classes.add "text-center"
+ var content = new Template
+ var name_html = id.html_escape
+ content.add "<img src='{name_html}.png' usemap='#{name_html}' style='margin:auto' {alt}/>"
+ content.add map
+ article.content = content
+ parent.add_child article
+ end
+end