src/doc: rename `tpl_namespace` in `html_namespace` also clean comments
[nit.git] / src / doc / doc_phases / doc_html.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
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
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 # Render the DocModel pages as HTML pages.
16 #
17 # FIXME this module is all f*cked up to maintain compatibility with
18 # the original `doc_templates` and `doc_model` modules.
19 # This will change in further refactorings.
20 module doc_html
21
22 import doc_structure
23 import doc_hierarchies
24 import doc_intros_redefs
25 import doc_graphs
26 import html_templates
27
28 redef class ToolContext
29
30 # File pattern used to link documentation to source code.
31 var opt_source = new OptionString("link for source (%f for filename, " +
32 "%l for first line, %L for last line)", "--source")
33
34 # Directory where the CSS and JS is stored.
35 var opt_sharedir = new OptionString("directory containing nitdoc assets", "--sharedir")
36
37 # Use a shareurl instead of copy shared files.
38 #
39 # This is usefull if you don't want to store the Nitdoc templates with your
40 # documentation.
41 var opt_shareurl = new OptionString("use shareurl instead of copy shared files", "--shareurl")
42
43 # Use a custom title for the homepage.
44 var opt_custom_title = new OptionString("custom title for homepage", "--custom-title")
45
46 # Display a custom brand or logo in the documentation top menu.
47 var opt_custom_brand = new OptionString("custom link to external site", "--custom-brand")
48
49 # Display a custom introduction text before the projects overview.
50 var opt_custom_intro = new OptionString("custom intro text for homepage", "--custom-overview-text")
51 # Display a custom footer on each documentation page.
52 #
53 # Generally used to display the documentation or product version.
54 var opt_custom_footer = new OptionString("custom footer text", "--custom-footer-text")
55
56 # Piwik tracker URL.
57 #
58 # If you want to monitor your visitors.
59 var opt_piwik_tracker = new OptionString("Piwik tracker URL (ex: nitlanguage.org/piwik/)", "--piwik-tracker")
60
61 # Piwik tracker site id.
62 var opt_piwik_site_id = new OptionString("Piwik site ID", "--piwik-site-id")
63
64 # These options are not currently used in Nitdoc.
65
66 # FIXME redo the plugin
67 var opt_github_upstream = new OptionString("Git branch where edited commits will be pulled into (ex: user:repo:branch)", "--github-upstream")
68 # FIXME redo the plugin
69 var opt_github_base_sha1 = new OptionString("Git sha1 of base commit used to create pull request", "--github-base-sha1")
70 # FIXME redo the plugin
71 var opt_github_gitdir = new OptionString("Git working directory used to resolve path name (ex: /home/me/myproject/)", "--github-gitdir")
72
73 redef init do
74 super
75
76 option_context.add_option(
77 opt_source, opt_sharedir, opt_shareurl, opt_custom_title,
78 opt_custom_footer, opt_custom_intro, opt_custom_brand,
79 opt_github_upstream, opt_github_base_sha1, opt_github_gitdir,
80 opt_piwik_tracker, opt_piwik_site_id)
81 end
82
83 redef fun process_options(args) do
84 super
85 var upstream = opt_github_upstream
86 var base_sha = opt_github_base_sha1
87 var git_dir = opt_github_gitdir
88 var opts = [upstream.value, base_sha.value, git_dir.value]
89 if not opts.has_only(null) and opts.has(null) then
90 print "Option Error: options {upstream.names.first}, " +
91 "{base_sha.names.first} and {git_dir.names.first} " +
92 "are required to enable the GitHub plugin"
93 exit 1
94 end
95 end
96 end
97
98 # Render the Nitdoc as a HTML website.
99 class RenderHTMLPhase
100 super DocPhase
101
102 # Used to sort sidebar elements by name.
103 var name_sorter = new MEntityNameSorter
104
105 redef fun apply do
106 init_output_dir
107 for page in doc.pages do
108 page.render(self, doc).write_to_file("{ctx.output_dir.to_s}/{page.html_url}")
109 end
110 end
111
112 # Creates the output directory and imports assets files form `resources/`.
113 fun init_output_dir do
114 # create destination dir if it's necessary
115 var output_dir = ctx.output_dir
116 if not output_dir.file_exists then output_dir.mkdir
117 # locate share dir
118 var sharedir = ctx.opt_sharedir.value
119 if sharedir == null then
120 var dir = ctx.nit_dir
121 sharedir = dir/"share/nitdoc"
122 if not sharedir.file_exists then
123 print "Error: cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
124 abort
125 end
126 end
127 # copy shared files
128 if ctx.opt_shareurl.value == null then
129 sys.system("cp -r -- {sharedir.to_s.escape_to_sh}/* {output_dir.to_s.escape_to_sh}/")
130 else
131 sys.system("cp -r -- {sharedir.to_s.escape_to_sh}/resources/ {output_dir.to_s.escape_to_sh}/resources/")
132 end
133
134 end
135
136 # A source link template for a given location
137 fun tpl_showsource(location: nullable Location): nullable String
138 do
139 if location == null then return null
140 var source = ctx.opt_source.value
141 if source == null then
142 var url = location.file.filename.simplify_path
143 return "<a target='_blank' title='Show source' href=\"{url.html_escape}\">View Source</a>"
144 end
145 # THIS IS JUST UGLY ! (but there is no replace yet)
146 var x = source.split_with("%f")
147 source = x.join(location.file.filename.simplify_path)
148 x = source.split_with("%l")
149 source = x.join(location.line_start.to_s)
150 x = source.split_with("%L")
151 source = x.join(location.line_end.to_s)
152 source = source.simplify_path
153 return "<a target='_blank' title='Show source' href=\"{source.to_s.html_escape}\">View Source</a>"
154 end
155 end
156
157 redef class DocPage
158
159 # Render the page as a html template.
160 private fun render(v: RenderHTMLPhase, doc: DocModel): Writable do
161 var shareurl = "."
162 if v.ctx.opt_shareurl.value != null then
163 shareurl = v.ctx.opt_shareurl.value.as(not null)
164 end
165
166 # init page options
167 self.shareurl = shareurl
168 self.footer = v.ctx.opt_custom_footer.value
169 self.body_attrs.add(new TagAttribute("data-bootstrap-share", shareurl))
170
171 # build page
172 init_title(v, doc)
173 init_sidebar(v, doc)
174 init_topmenu(v, doc)
175 init_content(v, doc)
176
177 # piwik tracking
178 var tracker_url = v.ctx.opt_piwik_tracker.value
179 var site_id = v.ctx.opt_piwik_site_id.value
180 if tracker_url != null and site_id != null then
181 self.scripts.add new TplPiwikScript(tracker_url, site_id)
182 end
183 return self
184 end
185
186 # FIXME diff hack
187 # all properties below are roughly copied from `doc_pages`
188
189 # Build page title string
190 fun init_title(v: RenderHTMLPhase, doc: DocModel) is abstract
191
192 # Build top menu template if any.
193 fun init_topmenu(v: RenderHTMLPhase, doc: DocModel) do
194 topmenu = new DocTopMenu
195 var brand = v.ctx.opt_custom_brand.value
196 if brand != null then
197 var tpl = new Template
198 tpl.add "<span class='navbar-brand'>"
199 tpl.add brand
200 tpl.add "</span>"
201 topmenu.brand = tpl
202 end
203 var title = "Overview"
204 if v.ctx.opt_custom_title.value != null then
205 title = v.ctx.opt_custom_title.value.to_s
206 end
207 topmenu.add_li new ListItem(new Link("index.html", title))
208 topmenu.add_li new ListItem(new Link("search.html", "Index"))
209 topmenu.active_item = topmenu.items.first
210 end
211
212 # Build page sidebar if any.
213 fun init_sidebar(v: RenderHTMLPhase, doc: DocModel) do
214 sidebar = new TplSidebar
215 end
216
217 # Build page content template.
218 fun init_content(v: RenderHTMLPhase, doc: DocModel) do end
219 end
220
221 redef class OverviewPage
222 redef var html_url = "index.html"
223
224 redef fun init_title(v, doc) do
225 title = "Overview"
226 if v.ctx.opt_custom_title.value != null then
227 title = v.ctx.opt_custom_title.value.to_s
228 end
229 end
230
231 # TODO this should be done in StructurePhase.
232 redef fun init_content(v, doc) do
233 # intro text
234 var section = new TplSection.with_title("overview", title)
235 var article = new TplArticle("intro")
236 if v.ctx.opt_custom_intro.value != null then
237 article.content = v.ctx.opt_custom_intro.value.to_s
238 end
239 section.add_child article
240 # Projects list
241 var mprojects = doc.model.mprojects.to_a
242 var sorter = new MConcernRankSorter
243 sorter.sort mprojects
244 var ssection = new TplSection.with_title("projects", "Projects")
245 for mproject in mprojects do
246 var sarticle = mproject.tpl_article
247 sarticle.subtitle = mproject.html_declaration
248 sarticle.content = mproject.tpl_definition
249 var mdoc = mproject.mdoc_or_fallback
250 if mdoc != null then
251 sarticle.content = mdoc.tpl_short_comment
252 end
253 ssection.add_child sarticle
254 end
255 section.add_child ssection
256 self.add_section section
257 end
258
259 redef fun init_sidebar(v, doc) do sidebar = new TplSidebar
260 end
261
262 redef class SearchPage
263 redef var html_url = "search.html"
264 redef fun init_title(v, doc) do title = "Index"
265
266 redef fun init_topmenu(v, doc) do
267 super
268 topmenu.active_item = topmenu.items.last
269 end
270
271 redef fun init_sidebar(v, doc) do end
272
273 # TODO this should be done in StructurePhase.
274 redef fun init_content(v, doc) do
275 var tpl = new TplSearchPage("search_all")
276 var section = new TplSection("search")
277 # title
278 tpl.title = "Index"
279 # modules list
280 for mmodule in modules_list(v, doc) do
281 tpl.modules.add mmodule.html_link
282 end
283 # classes list
284 for mclass in classes_list(v, doc) do
285 tpl.classes.add mclass.html_link
286 end
287 # properties list
288 for mproperty in mprops_list(v, doc) do
289 var m = new Template
290 m.add mproperty.intro.html_link
291 m.add " ("
292 m.add mproperty.intro.mclassdef.mclass.html_link
293 m.add ")"
294 tpl.props.add m
295 end
296 section.add_child tpl
297 self.add_section section
298 end
299
300 # Extract mmodule list to display (sorted by name)
301 private fun modules_list(v: RenderHTMLPhase, doc: DocModel): Array[MModule] do
302 var sorted = new Array[MModule]
303 for mmodule in doc.model.mmodule_importation_hierarchy do
304 if mmodule.is_fictive or mmodule.is_test_suite then continue
305 sorted.add mmodule
306 end
307 v.name_sorter.sort(sorted)
308 return sorted
309 end
310
311 # Extract mclass list to display (sorted by name)
312 private fun classes_list(v: RenderHTMLPhase, doc: DocModel): Array[MClass] do
313 var sorted = doc.mclasses.to_a
314 v.name_sorter.sort(sorted)
315 return sorted
316 end
317
318 # Extract mproperty list to display (sorted by name)
319 private fun mprops_list(v: RenderHTMLPhase, doc: DocModel): Array[MProperty] do
320 var sorted = doc.mproperties.to_a
321 v.name_sorter.sort(sorted)
322 return sorted
323 end
324 end
325
326 redef class MEntityPage
327 redef var html_url is lazy do return mentity.nitdoc_url
328 redef fun init_title(v, doc) do title = mentity.html_name
329 redef fun init_content(v, doc) do add_section root.start_rendering(v, doc, self)
330 end
331
332 # FIXME all clases below are roughly copied from `doc_pages` and adapted to new
333 # doc phases. This is to preserve the compatibility with the current
334 # `doc_templates` module.
335
336 redef class MGroupPage
337 redef fun init_topmenu(v, doc) do
338 super
339 var mproject = mentity.mproject
340 if not mentity.is_root then
341 topmenu.add_li new ListItem(new Link(mproject.nitdoc_url, mproject.html_name))
342 end
343 topmenu.add_li new ListItem(new Link(html_url, mproject.html_name))
344 topmenu.active_item = topmenu.items.last
345 end
346
347 redef fun init_sidebar(v, doc) do
348 super
349 var mclasses = new HashSet[MClass]
350 mclasses.add_all intros
351 mclasses.add_all redefs
352 if mclasses.is_empty then return
353 var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
354
355 var sorted = mclasses.to_a
356 v.name_sorter.sort(sorted)
357 for mclass in sorted do
358 list.add_li tpl_sidebar_item(mclass)
359 end
360 sidebar.boxes.add new TplSideBox.with_content("All classes", list)
361 end
362
363 private fun tpl_sidebar_item(def: MClass): TplListItem do
364 var classes = def.intro.tpl_css_classes.to_a
365 if intros.has(def) then
366 classes.add "intro"
367 else
368 classes.add "redef"
369 end
370 var lnk = new Template
371 lnk.add new TplLabel.with_classes(classes)
372 lnk.add def.html_link
373 return new TplListItem.with_content(lnk)
374 end
375 end
376
377 redef class MModulePage
378 redef fun init_topmenu(v, doc) do
379 super
380 var mproject = mentity.mproject
381 topmenu.add_li new ListItem(new Link(mproject.nitdoc_url, mproject.html_name))
382 topmenu.add_li new ListItem(new Link(mentity.nitdoc_url, mentity.html_name))
383 topmenu.active_item = topmenu.items.last
384 end
385
386 # Class list to display in sidebar
387 redef fun init_sidebar(v, doc) do
388 # TODO filter here?
389 super
390 var mclasses = new HashSet[MClass]
391 mclasses.add_all mentity.filter_intro_mclasses(v.ctx.min_visibility)
392 mclasses.add_all mentity.filter_redef_mclasses(v.ctx.min_visibility)
393 if mclasses.is_empty then return
394 var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
395
396 var sorted = mclasses.to_a
397 v.name_sorter.sort(sorted)
398 for mclass in sorted do
399 list.add_li tpl_sidebar_item(mclass)
400 end
401 sidebar.boxes.add new TplSideBox.with_content("All classes", list)
402 end
403
404 private fun tpl_sidebar_item(def: MClass): TplListItem do
405 var classes = def.intro.tpl_css_classes.to_a
406 if def.intro_mmodule == self.mentity then
407 classes.add "intro"
408 else
409 classes.add "redef"
410 end
411 var lnk = new Template
412 lnk.add new TplLabel.with_classes(classes)
413 lnk.add def.html_link
414 return new TplListItem.with_content(lnk)
415 end
416 end
417
418 redef class MClassPage
419
420 redef fun init_topmenu(v, doc) do
421 super
422 var mproject = mentity.intro_mmodule.mgroup.mproject
423 topmenu.add_li new ListItem(new Link(mproject.nitdoc_url, mproject.html_name))
424 topmenu.add_li new ListItem(new Link(html_url, mentity.html_name))
425 topmenu.active_item = topmenu.items.last
426 end
427
428 redef fun init_sidebar(v, doc) do
429 super
430 var by_kind = new PropertiesByKind.with_elements(mclass_inherited_mprops(v, doc))
431 var summary = new TplList.with_classes(["list-unstyled"])
432
433 by_kind.sort_groups(v.name_sorter)
434 for g in by_kind.groups do tpl_sidebar_list(g, summary)
435 sidebar.boxes.add new TplSideBox.with_content("All properties", summary)
436 end
437
438 private fun tpl_sidebar_list(mprops: PropertyGroup[MProperty], summary: TplList) do
439 if mprops.is_empty then return
440 var entry = new TplListItem.with_content(mprops.title)
441 var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
442 for mprop in mprops do
443 list.add_li tpl_sidebar_item(mprop)
444 end
445 entry.append list
446 summary.elts.add entry
447 end
448
449 private fun tpl_sidebar_item(mprop: MProperty): TplListItem do
450 var classes = mprop.intro.tpl_css_classes.to_a
451 if not mprop_is_local(mprop) then
452 classes.add "inherit"
453 var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url
454 var def_url = "{cls_url}#{mprop.nitdoc_id}"
455 var lnk = new TplLink(def_url, mprop.html_name)
456 var mdoc = mprop.intro.mdoc_or_fallback
457 if mdoc != null then lnk.title = mdoc.short_comment
458 var item = new Template
459 item.add new TplLabel.with_classes(classes)
460 item.add lnk
461 return new TplListItem.with_content(item)
462 end
463 if mpropdefs.has(mprop.intro) then
464 classes.add "intro"
465 else
466 classes.add "redef"
467 end
468 var lnk = new Template
469 lnk.add new TplLabel.with_classes(classes)
470 lnk.add mprop.html_link_to_anchor
471 return new TplListItem.with_content(lnk)
472 end
473
474 private fun mclass_inherited_mprops(v: RenderHTMLPhase, doc: DocModel): Set[MProperty] do
475 var res = new HashSet[MProperty]
476 var local = mentity.local_mproperties(v.ctx.min_visibility)
477 for mprop in mentity.inherited_mproperties(doc.mainmodule, v.ctx.min_visibility) do
478 if local.has(mprop) then continue
479 #if mprop isa MMethod and mprop.is_init then continue
480 if mprop.intro.mclassdef.mclass.name == "Object" and
481 (mprop.visibility == protected_visibility or
482 mprop.intro.mclassdef.mmodule.name != "kernel") then continue
483 res.add mprop
484 end
485 res.add_all local
486 return res
487 end
488
489 private fun mprop_is_local(mprop: MProperty): Bool do
490 for mpropdef in mprop.mpropdefs do
491 if self.mpropdefs.has(mpropdef) then return true
492 end
493 return false
494 end
495 end
496
497 redef class MPropertyPage
498 redef fun init_title(v, doc) do
499 title = "{mentity.html_name}{mentity.tpl_signature.write_to_string}"
500 end
501
502 redef fun init_topmenu(v, doc) do
503 super
504 var mmodule = mentity.intro_mclassdef.mmodule
505 var mproject = mmodule.mgroup.mproject
506 var mclass = mentity.intro_mclassdef.mclass
507 topmenu.add_li new ListItem(new Link(mproject.nitdoc_url, mproject.html_name))
508 topmenu.add_li new ListItem(new Link(mclass.nitdoc_url, mclass.html_name))
509 topmenu.add_li new ListItem(new Link(html_url, mentity.html_name))
510 topmenu.active_item = topmenu.items.last
511 end
512 end
513
514 redef class DocComposite
515 # Render this DocComposite as HTML.
516 #
517 # FIXME needed to maintain TplSection compatibility.
518 fun render(v: RenderHTMLPhase, doc: DocModel, page: MEntityPage, parent: TplSectionElt) is abstract
519 end
520
521 redef class DocRoot
522
523 # Start the rendering from root.
524 #
525 # FIXME needed to maintain TplSection compatibility.
526 fun start_rendering(v: RenderHTMLPhase, doc: DocModel, page: MEntityPage): TplSection do
527 var section = new TplSection("top")
528 var mentity = page.mentity
529 section.title = mentity.html_name
530 section.subtitle = mentity.html_declaration
531 # FIXME ugly hack to avoid diff
532 if mentity isa MGroup and mentity.is_root then
533 section.title = mentity.mproject.html_name
534 section.subtitle = mentity.mproject.html_declaration
535 else if mentity isa MProperty then
536 section.title = "{mentity.html_name}{mentity.intro.tpl_signature.write_to_string}"
537 section.subtitle = mentity.html_namespace
538 section.summary_title = mentity.html_name
539 end
540 render(v, doc, page, section)
541 return section
542 end
543
544 redef fun render(v, doc, page, parent) do
545 for child in children do
546 child.render(v, doc, page, parent)
547 end
548 end
549 end
550
551 redef class ConcernSection
552 redef fun render(v, doc, page, parent) do
553 var section = new TplSection(mentity.nitdoc_id)
554 var mentity = self.mentity
555 # FIXME hideous hacks to avoid diff
556 if page.mentity isa MModule and mentity isa MModule then
557 render_concern_mmodule(page, section, mentity)
558 else if page.mentity isa MClass and mentity isa MModule then
559 render_concern_other(page, section, mentity)
560 else if page.mentity isa MProperty and mentity isa MModule then
561 render_concern_other(page, section, mentity)
562 end
563 for child in children do
564 child.render(v, doc, page, section)
565 end
566 parent.add_child section
567 end
568
569 private fun render_concern_mmodule(page: MEntityPage, section: TplSection, mmodule: MModule) do
570 var title = new Template
571 if mmodule == page.mentity then
572 title.add "in "
573 section.summary_title = "in {mmodule.html_name}"
574 else
575 title.add "from "
576 section.summary_title = "from {mmodule.html_name}"
577 end
578 title.add mmodule.html_namespace
579 section.title = title
580 end
581
582 private fun render_concern_other(page: MEntityPage, section: TplSection, mmodule: MModule) do
583 var title = new Template
584 title.add "in "
585 title.add mmodule.html_namespace
586 section.title = title
587 section.summary_title = "in {mmodule.html_name}"
588 end
589 end
590
591 redef class MEntitySection
592 redef fun render(v, doc, page, parent) do
593 for child in children do child.render(v, doc, page, parent)
594 end
595 end
596
597 redef class IntroArticle
598 redef fun render(v, doc, page, parent) do
599 var article = new TplArticle("intro")
600 var mentity = self.mentity
601 if mentity isa MModule then
602 article.source_link = v.tpl_showsource(mentity.location)
603 else if mentity isa MClassDef then
604 article.source_link = v.tpl_showsource(mentity.location)
605 else if mentity isa MPropDef then
606 article.source_link = v.tpl_showsource(mentity.location)
607 end
608 # article.subtitle = mentity.html_declaration
609 # FIXME diff hack
610 if mentity isa MProperty then
611 # intro title
612 var ns = mentity.intro.mclassdef.mmodule.html_namespace
613 var section = new TplSection("intro")
614 var title = new Template
615 title.add "Introduction in "
616 title.add ns
617 section.title = title
618 section.summary_title = "Introduction"
619 var intro = mentity.intro.tpl_article
620 intro.source_link = v.tpl_showsource(mentity.intro.location)
621 section.add_child intro
622 parent.add_child section
623 else
624 article.content = mentity.tpl_definition
625 parent.add_child article
626 end
627 end
628 end
629
630 redef class ConcernsArticle
631 redef fun render(v, doc, page, parent) do
632 # FIXME diff hack
633 var title = "concerns"
634 if page.mentity isa MProperty then title = "Concerns"
635 parent.add_child new TplArticle.
636 with_content(title, "Concerns", concerns.to_tpl)
637 end
638 end
639
640 redef class DefinitionArticle
641 redef fun render(v, doc, page, parent) do
642 var article: TplArticle
643 var mentity = self.mentity
644 # FIXME hideous hacks...
645 if mentity isa MModule then
646 article = mentity.tpl_article
647 article.subtitle = mentity.html_declaration
648 article.content = mentity.tpl_definition
649 else if mentity isa MClass then
650 article = make_mclass_article(v, page)
651 else if mentity isa MClassDef then
652 article = make_mclassdef_article(v, page)
653 article.source_link = v.tpl_showsource(mentity.location)
654 else if mentity isa MPropDef and page.mentity isa MClass then
655 article = make_mpropdef_article(v, doc, page)
656 else
657 article = mentity.tpl_article
658 article.subtitle = mentity.html_declaration
659 if mentity isa MPropDef then
660 article.source_link = v.tpl_showsource(mentity.location)
661 end
662 if not mentity isa MVirtualTypeProp then
663 # article.content = mentity.tpl_comment
664 end
665 end
666 for child in children do
667 child.render(v, doc, page, article)
668 end
669 parent.add_child article
670 end
671
672 # FIXME avoid diff while preserving TplArticle compatibility.
673
674 private fun make_mclass_article(v: RenderHTMLPhase, page: MEntityPage): TplArticle do
675 var article = mentity.tpl_article
676 article.subtitle = mentity.html_namespace
677 article.content = null
678 return article
679 end
680
681 private fun make_mclassdef_article(v: RenderHTMLPhase, page: MEntityPage): TplArticle do
682 var mclassdef = mentity.as(MClassDef)
683 var article = mentity.tpl_article
684 if mclassdef.is_intro and mclassdef.mmodule != page.mentity then
685 article = mentity.tpl_short_article
686 end
687 var title = new Template
688 title.add "in "
689 title.add mclassdef.mmodule.html_namespace
690 article.subtitle = title
691 return article
692 end
693
694 private fun make_mpropdef_article(v: RenderHTMLPhase, doc: DocModel, page: MEntityPage): TplArticle
695 do
696 var mpropdef = mentity.as(MPropDef)
697 var mprop = mpropdef.mproperty
698 var article = new TplArticle(mprop.nitdoc_id)
699 var title = new Template
700 title.add mprop.tpl_icon
701 title.add "<span id='{mpropdef.nitdoc_id}'></span>"
702 if mpropdef.is_intro then
703 title.add mprop.html_link
704 title.add mprop.intro.tpl_signature
705 else
706 var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url
707 var def_url = "{cls_url}#{mprop.nitdoc_id}"
708 var lnk = new TplLink.with_title(def_url, mprop.html_name,
709 "Go to introduction")
710 title.add "redef "
711 title.add lnk
712 end
713 article.title = title
714 article.title_classes.add "signature"
715 article.summary_title = "{mprop.html_name}"
716 article.subtitle = mpropdef.html_namespace
717 if mpropdef.mdoc_or_fallback != null then
718 article.content = mpropdef.mdoc_or_fallback.tpl_comment
719 end
720 # TODO move in its own phase? let's see after doc_template refactoring.
721 # Add linearization
722 var all_defs = new HashSet[MPropDef]
723 for local_def in local_defs(page.as(MClassPage), mprop) do
724 all_defs.add local_def
725 var smpropdef = local_def
726 while not smpropdef.is_intro do
727 smpropdef = smpropdef.lookup_next_definition(
728 doc.mainmodule, smpropdef.mclassdef.bound_mtype)
729 all_defs.add smpropdef
730 end
731 end
732 var lin = all_defs.to_a
733 doc.mainmodule.linearize_mpropdefs(lin)
734 if lin.length > 1 then
735 var lin_article = new TplArticle("{mpropdef.nitdoc_id}.lin")
736 lin_article.title = "Inheritance"
737 var lst = new TplList.with_classes(["list-unstyled", "list-labeled"])
738 for smpropdef in lin do
739 lst.add_li smpropdef.tpl_inheritance_item
740 end
741 lin_article.content = lst
742 article.add_child lin_article
743 end
744 return article
745 end
746
747 # Filter `page.mpropdefs` for this `mpropertie`.
748 #
749 # FIXME compatability with current templates.
750 private fun local_defs(page: MClassPage, mproperty: MProperty): HashSet[MPropDef] do
751 var mpropdefs = new HashSet[MPropDef]
752 for mpropdef in page.mpropdefs do
753 if mpropdef.mproperty == mproperty then
754 mpropdefs.add mpropdef
755 end
756 end
757 return mpropdefs
758 end
759 end
760
761 redef class IntrosRedefsListArticle
762 redef fun render(v, doc, page, parent) do
763 if mentities.is_empty then return
764 var title = list_title
765 # FIXME diff hack
766 var id = "intros"
767 if title == "Redefines" then id = "redefs"
768 var article = new TplArticle.with_title("{mentity.nitdoc_id}.{id}", title)
769 var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
770 for mentity in mentities do
771 list.add_li mentity.tpl_list_item
772 end
773 article.content = list
774 parent.add_child article
775 end
776 end
777
778 # FIXME compatibility with doc_templates.
779 redef class ImportationListSection
780 redef fun render(v, doc, page, parent) do
781 var section = new TplSection.with_title("dependencies", "Dependencies")
782 for child in children do
783 child.render(v, doc, page, section)
784 end
785 parent.add_child section
786 end
787 end
788
789 # FIXME compatibility with doc_templates.
790 redef class InheritanceListSection
791 redef fun render(v, doc, page, parent) do
792 var section = new TplSection.with_title("inheritance", "Inheritance")
793 for child in children do
794 child.render(v, doc, page, section)
795 end
796 parent.add_child section
797 end
798 end
799
800 # FIXME compatibility with doc_templates.
801 redef class HierarchyListArticle
802 redef fun render(v, doc, page, parent) do
803 if mentities.is_empty then return
804 var title = list_title
805 var id = list_title.to_lower
806 var article = new TplArticle.with_title(id, title)
807 var list = new TplList.with_classes(["list-unstyled", "list-definition"])
808 for mentity in mentities do
809 list.elts.add mentity.tpl_list_item
810 end
811 article.content = list
812 parent.add_child article
813 end
814 end
815
816 redef class GraphArticle
817 redef fun render(v, doc, page, parent) do
818 var output_dir = v.ctx.output_dir
819 var path = output_dir / id
820 var path_sh = path.escape_to_sh
821 var file = new FileWriter.open("{path}.dot")
822 file.write(dot)
823 file.close
824 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 ; \}")
825 var fmap = new FileReader.open("{path}.map")
826 var map = fmap.read_all
827 fmap.close
828
829 var article = new TplArticle("graph")
830 var alt = ""
831 # FIXME diff hack
832 # if title != null then
833 # article.title = title
834 # alt = "alt='{title.html_escape}'"
835 # end
836 article.css_classes.add "text-center"
837 var content = new Template
838 var name_html = id.html_escape
839 content.add "<img src='{name_html}.png' usemap='#{name_html}' style='margin:auto' {alt}/>"
840 content.add map
841 article.content = content
842 parent.add_child article
843 end
844 end