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_nodot = new OptionBool("do not generate graphes with graphviz", "--no-dot")
-
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")
super
var opts = option_context
- opts.add_option(opt_dir, opt_source, opt_sharedir, opt_shareurl,
- opt_nodot)
+ 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)
# Build page content template
fun tpl_content is abstract
- # Clickable graphviz image using dot format
- # return null if no graph for this page
- fun tpl_graph(dot: Buffer, name: String, title: nullable String): nullable TplArticle do
- if ctx.opt_nodot.value then return null
- var output_dir = ctx.output_dir
- var path = output_dir / name
- 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 = ""
- 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 = name.html_escape
- content.add "<img src='{name_html}.png' usemap='#{name_html}' style='margin:auto' {alt}/>"
- content.add map
- article.content = content
- return article
- end
-
# A (source) link template for a given location
fun tpl_showsource(location: nullable Location): nullable String
do
# Display lists
var section = new TplSection.with_title("dependencies", "Dependencies")
- # Graph
- var mmodules = new HashSet[MModule]
- mmodules.add_all mmodule.nested_mmodules
- mmodules.add_all imports
- if clients.length < 10 then mmodules.add_all clients
- mmodules.add mmodule
- var graph = tpl_dot(mmodules)
- if graph != null then section.add_child graph
-
# Imports
var lst = new Array[MModule]
if not lst.is_empty then
article.content = list
return article
end
-
- # Genrate dot hierarchy for class inheritance
- fun tpl_dot(mmodules: Collection[MModule]): nullable TplArticle do
- # build graph
- var op = new RopeBuffer
- var name = "dep_module_{mmodule.nitdoc_id}"
- op.append("digraph \"{name.escape_to_dot}\" \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
- for mmodule in poset do
- if mmodule == self.mmodule then
- op.append("\"{mmodule.name.escape_to_dot}\"[shape=box,margin=0.03];\n")
- else
- op.append("\"{mmodule.name.escape_to_dot}\"[URL=\"{mmodule.nitdoc_url.escape_to_dot}\"];\n")
- end
- for omodule in poset[mmodule].direct_greaters do
- op.append("\"{mmodule.name.escape_to_dot}\"->\"{omodule.name.escape_to_dot}\";\n")
- end
- end
- op.append("\}\n")
- return tpl_graph(op, name, null)
- end
end
# A class page
# Display lists
var section = new TplSection.with_title("inheritance", "Inheritance")
- # Graph
- var mclasses = new HashSet[MClass]
- mclasses.add_all hancestors
- mclasses.add_all hparents
- mclasses.add_all hchildren
- mclasses.add_all hdescendants
- mclasses.add mclass
- var graph = tpl_dot(mclasses)
- if graph != null then section.add_child graph
-
# parents
if not hparents.is_empty then
var lst = hparents.to_a
end
return article
end
-
- # Generate dot hierarchy for classes
- fun tpl_dot(mclasses: Collection[MClass]): nullable TplArticle do
- var op = new RopeBuffer
- var name = "dep_class_{mclass.nitdoc_id}"
- op.append("digraph \"{name.escape_to_dot}\" \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
- var classes = poset.to_a
- var todo = new Array[MClass]
- var done = new HashSet[MClass]
- mainmodule.linearize_mclasses(classes)
- if not classes.is_empty then todo.add classes.first
- while not todo.is_empty do
- var c = todo.shift
- if done.has(c) then continue
- done.add c
- if c == mclass then
- op.append("\"{c.name.escape_to_dot}\"[shape=box,margin=0.03];\n")
- else
- op.append("\"{c.name.escape_to_dot}\"[URL=\"{c.nitdoc_url.escape_to_dot}\"];\n")
- end
- var smallers = poset[c].direct_smallers
- if smallers.length < 10 then
- for c2 in smallers do
- op.append("\"{c2.name.escape_to_dot}\"->\"{c.name.escape_to_dot}\";\n")
- end
- todo.add_all smallers
- else
- op.append("\"...\"->\"{c.name.escape_to_dot}\";\n")
- end
- end
- op.append("\}\n")
- return tpl_graph(op, name, null)
- end
end
# A MProperty page
--- /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.
+
+# Adds importation and class hierarchy graphs.
+module doc_graphs
+
+import doc_poset
+
+redef class ToolContext
+
+ # Do not generate `graphviz` diagrams.
+ var opt_nodot = new OptionBool("do not generate graphes with graphviz", "--no-dot")
+
+ redef init do
+ super
+ option_context.add_option(opt_nodot)
+ end
+end
+
+# This phase insert importation and inheritance graphs into pages.
+class GraphPhase
+ super DocPhase
+
+ redef fun apply do
+ if ctx.opt_nodot.value then return
+ for page in doc.pages do
+ var article = page.build_graph(self, doc)
+ if article == null then continue
+ # FIXME avoid diff
+ # page.root.add article
+ page.root.children[1].children.insert(article, 0)
+ end
+ end
+end
+
+redef class DocPage
+ # Build dot graph articles from `mmodules` list.
+ #
+ # Since only `MEntity pages` contain a graph, this method returns null in all
+ # other cases.
+ private fun build_graph(v: GraphPhase, doc: DocModel): nullable GraphArticle do return null
+end
+
+# TODO graph generation can be factorized in POSet.
+
+redef class MModulePage
+ redef fun build_graph(v, doc) do
+ var op = new FlatBuffer
+ var name = "dep_module_{mentity.nitdoc_id}"
+ op.append("digraph \"{name.escape_to_dot}\" \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
+ for mmodule in poset do
+ if mmodule == self.mentity then
+ op.append("\"{mmodule.name.escape_to_dot}\"[shape=box,margin=0.03];\n")
+ else
+ op.append("\"{mmodule.name.escape_to_dot}\"[URL=\"{mmodule.nitdoc_url.escape_to_dot}\"];\n")
+ end
+ for omodule in poset[mmodule].direct_greaters do
+ op.append("\"{mmodule.name.escape_to_dot}\"->\"{omodule.name.escape_to_dot}\";\n")
+ end
+ end
+ op.append("\}\n")
+ return new GraphArticle(name, op)
+ end
+end
+
+redef class MClassPage
+ redef fun build_graph(v, doc) do
+ var op = new FlatBuffer
+ var name = "dep_class_{mentity.nitdoc_id}"
+ op.append("digraph \"{name.escape_to_dot}\" \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
+ var classes = poset.to_a
+ var todo = new Array[MClass]
+ var done = new HashSet[MClass]
+ doc.mainmodule.linearize_mclasses(classes)
+ if not classes.is_empty then todo.add classes.first
+ while not todo.is_empty do
+ var c = todo.shift
+ if done.has(c) then continue
+ done.add c
+ if c == self.mentity then
+ op.append("\"{c.name.escape_to_dot}\"[shape=box,margin=0.03];\n")
+ else
+ op.append("\"{c.name.escape_to_dot}\"[URL=\"{c.nitdoc_url.escape_to_dot}\"];\n")
+ end
+ var smallers = poset[c].direct_smallers
+ if smallers.length < 10 then
+ for c2 in smallers do
+ op.append("\"{c2.name.escape_to_dot}\"->\"{c.name.escape_to_dot}\";\n")
+ end
+ todo.add_all smallers
+ else
+ op.append("\"...\"->\"{c.name.escape_to_dot}\";\n")
+ end
+ end
+ op.append("\}\n")
+ return new GraphArticle(name, op)
+ end
+end
+
+# An article that display an importation or inheritance graph.
+#
+# The graph is stored in dot format.
+# The final output is delayed untill rendering.
+class GraphArticle
+ super DocComposite
+
+ # Graph ID (used for outputing file with names).
+ var id: String
+
+ # Dot script of the graph.
+ var dot: Text
+end