tests: add base_with.nit
[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 "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 TplTopMenu(html_url)
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 topmenu.add_link new TplLink("index.html", "Overview")
204 topmenu.add_link new TplLink("search.html", "Index")
205 end
206
207 # Build page sidebar if any.
208 fun init_sidebar(v: RenderHTMLPhase, doc: DocModel) do
209 sidebar = new TplSidebar
210 end
211
212 # Build page content template.
213 fun init_content(v: RenderHTMLPhase, doc: DocModel) do end
214 end
215
216 redef class OverviewPage
217 redef var html_url = "index.html"
218
219 redef fun init_title(v, doc) do
220 title = "Overview"
221 if v.ctx.opt_custom_title.value != null then
222 title = v.ctx.opt_custom_title.value.to_s
223 end
224 end
225
226 # TODO this should be done in StructurePhase.
227 redef fun init_content(v, doc) do
228 # intro text
229 var section = new TplSection.with_title("overview", title)
230 var article = new TplArticle("intro")
231 if v.ctx.opt_custom_intro.value != null then
232 article.content = v.ctx.opt_custom_intro.value.to_s
233 end
234 section.add_child article
235 # Projects list
236 var mprojects = doc.model.mprojects.to_a
237 var sorter = new MConcernRankSorter
238 sorter.sort mprojects
239 var ssection = new TplSection.with_title("projects", "Projects")
240 for mproject in mprojects do
241 var sarticle = mproject.tpl_article
242 sarticle.subtitle = mproject.tpl_declaration
243 sarticle.content = mproject.tpl_definition
244 var mdoc = mproject.mdoc_or_fallback
245 if mdoc != null then
246 sarticle.content = mdoc.tpl_short_comment
247 end
248 ssection.add_child sarticle
249 end
250 section.add_child ssection
251 self.add_section section
252 end
253
254 redef fun init_sidebar(v, doc) do sidebar = new TplSidebar
255 end
256
257 redef class SearchPage
258 redef var html_url = "search.html"
259 redef fun init_title(v, doc) do title = "Index"
260 redef fun init_sidebar(v, doc) do end
261
262 # TODO this should be done in StructurePhase.
263 redef fun init_content(v, doc) do
264 var tpl = new TplSearchPage("search_all")
265 var section = new TplSection("search")
266 # title
267 tpl.title = "Index"
268 # modules list
269 for mmodule in modules_list(v, doc) do
270 tpl.modules.add mmodule.tpl_link
271 end
272 # classes list
273 for mclass in classes_list(v, doc) do
274 tpl.classes.add mclass.tpl_link
275 end
276 # properties list
277 for mproperty in mprops_list(v, doc) do
278 var m = new Template
279 m.add mproperty.intro.tpl_link
280 m.add " ("
281 m.add mproperty.intro.mclassdef.mclass.tpl_link
282 m.add ")"
283 tpl.props.add m
284 end
285 section.add_child tpl
286 self.add_section section
287 end
288
289 # Extract mmodule list to display (sorted by name)
290 private fun modules_list(v: RenderHTMLPhase, doc: DocModel): Array[MModule] do
291 var sorted = new Array[MModule]
292 for mmodule in doc.model.mmodule_importation_hierarchy do
293 if mmodule.is_fictive or mmodule.is_test_suite then continue
294 sorted.add mmodule
295 end
296 v.name_sorter.sort(sorted)
297 return sorted
298 end
299
300 # Extract mclass list to display (sorted by name)
301 private fun classes_list(v: RenderHTMLPhase, doc: DocModel): Array[MClass] do
302 var sorted = doc.mclasses.to_a
303 v.name_sorter.sort(sorted)
304 return sorted
305 end
306
307 # Extract mproperty list to display (sorted by name)
308 private fun mprops_list(v: RenderHTMLPhase, doc: DocModel): Array[MProperty] do
309 var sorted = doc.mproperties.to_a
310 v.name_sorter.sort(sorted)
311 return sorted
312 end
313 end
314
315 redef class MEntityPage
316 redef var html_url is lazy do return mentity.nitdoc_url
317 redef fun init_title(v, doc) do title = mentity.nitdoc_name
318 redef fun init_content(v, doc) do add_section root.start_rendering(v, doc, self)
319 end
320
321 # FIXME all clases below are roughly copied from `doc_pages` and adapted to new
322 # doc phases. This is to preserve the compatibility with the current
323 # `doc_templates` module.
324
325 redef class MGroupPage
326 redef fun init_topmenu(v, doc) do
327 super
328 var mproject = mentity.mproject
329 if not mentity.is_root then
330 topmenu.add_link new TplLink(mproject.nitdoc_url, mproject.nitdoc_name)
331 end
332 topmenu.add_link new TplLink(html_url, mproject.nitdoc_name)
333 end
334
335 redef fun init_sidebar(v, doc) do
336 super
337 var mclasses = new HashSet[MClass]
338 mclasses.add_all intros
339 mclasses.add_all redefs
340 if mclasses.is_empty then return
341 var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
342
343 var sorted = mclasses.to_a
344 v.name_sorter.sort(sorted)
345 for mclass in sorted do
346 list.add_li tpl_sidebar_item(mclass)
347 end
348 sidebar.boxes.add new TplSideBox.with_content("All classes", list)
349 end
350
351 private fun tpl_sidebar_item(def: MClass): TplListItem do
352 var classes = def.intro.tpl_css_classes.to_a
353 if intros.has(def) then
354 classes.add "intro"
355 else
356 classes.add "redef"
357 end
358 var lnk = new Template
359 lnk.add new TplLabel.with_classes(classes)
360 lnk.add def.tpl_link
361 return new TplListItem.with_content(lnk)
362 end
363 end
364
365 redef class MModulePage
366 redef fun init_topmenu(v, doc) do
367 super
368 var mproject = mentity.mproject
369 topmenu.add_link new TplLink(mproject.nitdoc_url, mproject.nitdoc_name)
370 topmenu.add_link new TplLink(mentity.nitdoc_url, mentity.nitdoc_name)
371 end
372
373 # Class list to display in sidebar
374 redef fun init_sidebar(v, doc) do
375 # TODO filter here?
376 super
377 var mclasses = new HashSet[MClass]
378 mclasses.add_all mentity.filter_intro_mclasses(v.ctx.min_visibility)
379 mclasses.add_all mentity.filter_redef_mclasses(v.ctx.min_visibility)
380 if mclasses.is_empty then return
381 var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
382
383 var sorted = mclasses.to_a
384 v.name_sorter.sort(sorted)
385 for mclass in sorted do
386 list.add_li tpl_sidebar_item(mclass)
387 end
388 sidebar.boxes.add new TplSideBox.with_content("All classes", list)
389 end
390
391 private fun tpl_sidebar_item(def: MClass): TplListItem do
392 var classes = def.intro.tpl_css_classes.to_a
393 if def.intro_mmodule == self.mentity then
394 classes.add "intro"
395 else
396 classes.add "redef"
397 end
398 var lnk = new Template
399 lnk.add new TplLabel.with_classes(classes)
400 lnk.add def.tpl_link
401 return new TplListItem.with_content(lnk)
402 end
403 end
404
405 redef class MClassPage
406
407 redef fun init_title(v, doc) do
408 title = "{mentity.nitdoc_name}{mentity.tpl_signature.write_to_string}"
409 end
410
411 redef fun init_topmenu(v, doc) do
412 super
413 var mproject = mentity.intro_mmodule.mgroup.mproject
414 topmenu.add_link new TplLink("{mproject.nitdoc_url}", "{mproject.nitdoc_name}")
415 topmenu.add_link new TplLink(html_url, mentity.nitdoc_name)
416 end
417
418 redef fun init_sidebar(v, doc) do
419 super
420 var by_kind = new PropertiesByKind.with_elements(mclass_inherited_mprops(v, doc))
421 var summary = new TplList.with_classes(["list-unstyled"])
422
423 by_kind.sort_groups(v.name_sorter)
424 for g in by_kind.groups do tpl_sidebar_list(g, summary)
425 sidebar.boxes.add new TplSideBox.with_content("All properties", summary)
426 end
427
428 private fun tpl_sidebar_list(mprops: PropertyGroup[MProperty], summary: TplList) do
429 if mprops.is_empty then return
430 var entry = new TplListItem.with_content(mprops.title)
431 var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
432 for mprop in mprops do
433 list.add_li tpl_sidebar_item(mprop)
434 end
435 entry.append list
436 summary.elts.add entry
437 end
438
439 private fun tpl_sidebar_item(mprop: MProperty): TplListItem do
440 var classes = mprop.intro.tpl_css_classes.to_a
441 if not mprop_is_local(mprop) then
442 classes.add "inherit"
443 var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url
444 var def_url = "{cls_url}#{mprop.nitdoc_id}"
445 var lnk = new TplLink(def_url, mprop.nitdoc_name)
446 var mdoc = mprop.intro.mdoc_or_fallback
447 if mdoc != null then lnk.title = mdoc.short_comment
448 var item = new Template
449 item.add new TplLabel.with_classes(classes)
450 item.add lnk
451 return new TplListItem.with_content(item)
452 end
453 if mpropdefs.has(mprop.intro) then
454 classes.add "intro"
455 else
456 classes.add "redef"
457 end
458 var lnk = new Template
459 lnk.add new TplLabel.with_classes(classes)
460 lnk.add mprop.tpl_anchor
461 return new TplListItem.with_content(lnk)
462 end
463
464 private fun mclass_inherited_mprops(v: RenderHTMLPhase, doc: DocModel): Set[MProperty] do
465 var res = new HashSet[MProperty]
466 var local = mentity.local_mproperties(v.ctx.min_visibility)
467 for mprop in mentity.inherited_mproperties(doc.mainmodule, v.ctx.min_visibility) do
468 if local.has(mprop) then continue
469 #if mprop isa MMethod and mprop.is_init then continue
470 if mprop.intro.mclassdef.mclass.name == "Object" and
471 (mprop.visibility == protected_visibility or
472 mprop.intro.mclassdef.mmodule.name != "kernel") then continue
473 res.add mprop
474 end
475 res.add_all local
476 return res
477 end
478
479 private fun mprop_is_local(mprop: MProperty): Bool do
480 for mpropdef in mprop.mpropdefs do
481 if self.mpropdefs.has(mpropdef) then return true
482 end
483 return false
484 end
485 end
486
487 redef class MPropertyPage
488 redef fun init_title(v, doc) do
489 title = "{mentity.nitdoc_name}{mentity.tpl_signature.write_to_string}"
490 end
491
492 redef fun init_topmenu(v, doc) do
493 super
494 var mmodule = mentity.intro_mclassdef.mmodule
495 var mproject = mmodule.mgroup.mproject
496 var mclass = mentity.intro_mclassdef.mclass
497 topmenu.add_link new TplLink("{mproject.nitdoc_url}", "{mproject.nitdoc_name}")
498 topmenu.add_link new TplLink("{mclass.nitdoc_url}", "{mclass.nitdoc_name}")
499 topmenu.add_link new TplLink(html_url, mentity.nitdoc_name)
500 end
501 end
502
503 redef class DocComposite
504 # Render this DocComposite as HTML.
505 #
506 # FIXME needed to maintain TplSection compatibility.
507 fun render(v: RenderHTMLPhase, doc: DocModel, page: MEntityPage, parent: TplSectionElt) is abstract
508 end
509
510 redef class DocRoot
511
512 # Start the rendering from root.
513 #
514 # FIXME needed to maintain TplSection compatibility.
515 fun start_rendering(v: RenderHTMLPhase, doc: DocModel, page: MEntityPage): TplSection do
516 var section = new TplSection("top")
517 var mentity = page.mentity
518 section.title = mentity.nitdoc_name
519 section.subtitle = mentity.tpl_declaration
520 # FIXME ugly hack to avoid diff
521 if mentity isa MGroup and mentity.is_root then
522 section.title = mentity.mproject.nitdoc_name
523 section.subtitle = mentity.mproject.tpl_declaration
524 else if mentity isa MClass then
525 section.title = "{mentity.nitdoc_name}{mentity.tpl_signature.write_to_string}"
526 else if mentity isa MProperty then
527 section.title = "{mentity.nitdoc_name}{mentity.intro.tpl_signature.write_to_string}"
528 section.subtitle = mentity.tpl_namespace
529 section.summary_title = mentity.nitdoc_name
530 end
531 render(v, doc, page, section)
532 return section
533 end
534
535 redef fun render(v, doc, page, parent) do
536 for child in children do
537 child.render(v, doc, page, parent)
538 end
539 end
540 end
541
542 redef class ConcernSection
543 redef fun render(v, doc, page, parent) do
544 var section = new TplSection(mentity.nitdoc_id)
545 var mentity = self.mentity
546 # FIXME hideous hacks to avoid diff
547 if page.mentity isa MModule and mentity isa MModule then
548 render_concern_mmodule(page, section, mentity)
549 else if page.mentity isa MClass and mentity isa MModule then
550 render_concern_other(page, section, mentity)
551 else if page.mentity isa MProperty and mentity isa MModule then
552 render_concern_other(page, section, mentity)
553 end
554 for child in children do
555 child.render(v, doc, page, section)
556 end
557 parent.add_child section
558 end
559
560 private fun render_concern_mmodule(page: MEntityPage, section: TplSection, mmodule: MModule) do
561 var title = new Template
562 if mmodule == page.mentity then
563 title.add "in "
564 section.summary_title = "in {mmodule.nitdoc_name}"
565 else
566 title.add "from "
567 section.summary_title = "from {mmodule.nitdoc_name}"
568 end
569 title.add mmodule.tpl_namespace
570 section.title = title
571 end
572
573 private fun render_concern_other(page: MEntityPage, section: TplSection, mmodule: MModule) do
574 var title = new Template
575 title.add "in "
576 title.add mmodule.tpl_namespace
577 section.title = title
578 section.summary_title = "in {mmodule.nitdoc_name}"
579 end
580 end
581
582 redef class IntroArticle
583 redef fun render(v, doc, page, parent) do
584 var article = new TplArticle("intro")
585 var mentity = self.mentity
586 if mentity isa MModule then
587 article.source_link = v.tpl_showsource(mentity.location)
588 else if mentity isa MClassDef then
589 article.source_link = v.tpl_showsource(mentity.location)
590 else if mentity isa MPropDef then
591 article.source_link = v.tpl_showsource(mentity.location)
592 end
593 # article.subtitle = mentity.tpl_declaration
594 # FIXME diff hack
595 if mentity isa MProperty then
596 # intro title
597 var ns = mentity.intro.mclassdef.mmodule.tpl_namespace
598 var section = new TplSection("intro")
599 var title = new Template
600 title.add "Introduction in "
601 title.add ns
602 section.title = title
603 section.summary_title = "Introduction"
604 var intro = mentity.intro.tpl_article
605 intro.source_link = v.tpl_showsource(mentity.intro.location)
606 section.add_child intro
607 parent.add_child section
608 else
609 article.content = mentity.tpl_definition
610 parent.add_child article
611 end
612 end
613 end
614
615 redef class ConcernsArticle
616 redef fun render(v, doc, page, parent) do
617 # FIXME diff hack
618 var title = "concerns"
619 if page.mentity isa MProperty then title = "Concerns"
620 parent.add_child new TplArticle.
621 with_content(title, "Concerns", concerns.to_tpl)
622 end
623 end
624
625 redef class DefinitionArticle
626 redef fun render(v, doc, page, parent) do
627 var article: TplArticle
628 var mentity = self.mentity
629 # FIXME hideous hacks...
630 if mentity isa MModule then
631 article = mentity.tpl_article
632 article.subtitle = mentity.tpl_declaration
633 article.content = mentity.tpl_definition
634 else if mentity isa MClass then
635 article = make_mclass_article(v, page)
636 else if mentity isa MClassDef then
637 article = make_mclassdef_article(v, page)
638 article.source_link = v.tpl_showsource(mentity.location)
639 else if mentity isa MPropDef and page.mentity isa MClass then
640 article = make_mpropdef_article(v, doc, page)
641 else
642 article = mentity.tpl_article
643 article.subtitle = mentity.tpl_declaration
644 if mentity isa MPropDef then
645 article.source_link = v.tpl_showsource(mentity.location)
646 end
647 if not mentity isa MVirtualTypeProp then
648 # article.content = mentity.tpl_comment
649 end
650 end
651 for child in children do
652 child.render(v, doc, page, article)
653 end
654 parent.add_child article
655 end
656
657 # FIXME avoid diff while preserving TplArticle compatibility.
658
659 private fun make_mclass_article(v: RenderHTMLPhase, page: MEntityPage): TplArticle do
660 var article = mentity.tpl_article
661 article.subtitle = mentity.tpl_namespace
662 article.content = null
663 return article
664 end
665
666 private fun make_mclassdef_article(v: RenderHTMLPhase, page: MEntityPage): TplArticle do
667 var mclassdef = mentity.as(MClassDef)
668 var article = mentity.tpl_article
669 if mclassdef.is_intro and mclassdef.mmodule != page.mentity then
670 article = mentity.tpl_short_article
671 end
672 var title = new Template
673 title.add "in "
674 title.add mclassdef.mmodule.tpl_namespace
675 article.subtitle = title
676 return article
677 end
678
679 private fun make_mpropdef_article(v: RenderHTMLPhase, doc: DocModel, page: MEntityPage): TplArticle
680 do
681 var mpropdef = mentity.as(MPropDef)
682 var mprop = mpropdef.mproperty
683 var article = new TplArticle(mprop.nitdoc_id)
684 var title = new Template
685 title.add mprop.tpl_icon
686 title.add "<span id='{mpropdef.nitdoc_id}'></span>"
687 if mpropdef.is_intro then
688 title.add mprop.tpl_link
689 title.add mprop.intro.tpl_signature
690 else
691 var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url
692 var def_url = "{cls_url}#{mprop.nitdoc_id}"
693 var lnk = new TplLink.with_title(def_url, mprop.nitdoc_name,
694 "Go to introduction")
695 title.add "redef "
696 title.add lnk
697 end
698 article.title = title
699 article.title_classes.add "signature"
700 article.summary_title = "{mprop.nitdoc_name}"
701 article.subtitle = mpropdef.tpl_namespace
702 if mpropdef.mdoc_or_fallback != null then
703 article.content = mpropdef.mdoc_or_fallback.tpl_comment
704 end
705 # TODO move in its own phase? let's see after doc_template refactoring.
706 # Add linearization
707 var all_defs = new HashSet[MPropDef]
708 for local_def in local_defs(page.as(MClassPage), mprop) do
709 all_defs.add local_def
710 var smpropdef = local_def
711 while not smpropdef.is_intro do
712 smpropdef = smpropdef.lookup_next_definition(
713 doc.mainmodule, smpropdef.mclassdef.bound_mtype)
714 all_defs.add smpropdef
715 end
716 end
717 var lin = all_defs.to_a
718 doc.mainmodule.linearize_mpropdefs(lin)
719 if lin.length > 1 then
720 var lin_article = new TplArticle("{mpropdef.nitdoc_id}.lin")
721 lin_article.title = "Inheritance"
722 var lst = new TplList.with_classes(["list-unstyled", "list-labeled"])
723 for smpropdef in lin do
724 lst.add_li smpropdef.tpl_inheritance_item
725 end
726 lin_article.content = lst
727 article.add_child lin_article
728 end
729 return article
730 end
731
732 # Filter `page.mpropdefs` for this `mpropertie`.
733 #
734 # FIXME compatability with current templates.
735 private fun local_defs(page: MClassPage, mproperty: MProperty): HashSet[MPropDef] do
736 var mpropdefs = new HashSet[MPropDef]
737 for mpropdef in page.mpropdefs do
738 if mpropdef.mproperty == mproperty then
739 mpropdefs.add mpropdef
740 end
741 end
742 return mpropdefs
743 end
744 end
745
746 redef class IntrosRedefsListArticle
747 redef fun render(v, doc, page, parent) do
748 if mentities.is_empty then return
749 var title = list_title
750 # FIXME diff hack
751 var id = "intros"
752 if title == "Redefines" then id = "redefs"
753 var article = new TplArticle.with_title("{mentity.nitdoc_id}.{id}", title)
754 var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
755 for mentity in mentities do
756 list.add_li mentity.tpl_list_item
757 end
758 article.content = list
759 parent.add_child article
760 end
761 end
762
763 # FIXME compatibility with doc_templates.
764 redef class ImportationListSection
765 redef fun render(v, doc, page, parent) do
766 var section = new TplSection.with_title("dependencies", "Dependencies")
767 for child in children do
768 child.render(v, doc, page, section)
769 end
770 parent.add_child section
771 end
772 end
773
774 # FIXME compatibility with doc_templates.
775 redef class InheritanceListSection
776 redef fun render(v, doc, page, parent) do
777 var section = new TplSection.with_title("inheritance", "Inheritance")
778 for child in children do
779 child.render(v, doc, page, section)
780 end
781 parent.add_child section
782 end
783 end
784
785 # FIXME compatibility with doc_templates.
786 redef class HierarchyListArticle
787 redef fun render(v, doc, page, parent) do
788 if mentities.is_empty then return
789 var title = list_title
790 var id = list_title.to_lower
791 var article = new TplArticle.with_title(id, title)
792 var list = new TplList.with_classes(["list-unstyled", "list-definition"])
793 for mentity in mentities do
794 list.elts.add mentity.tpl_list_item
795 end
796 article.content = list
797 parent.add_child article
798 end
799 end
800
801 redef class GraphArticle
802 redef fun render(v, doc, page, parent) do
803 var output_dir = v.ctx.output_dir
804 var path = output_dir / id
805 var path_sh = path.escape_to_sh
806 var file = new FileWriter.open("{path}.dot")
807 file.write(dot)
808 file.close
809 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 ; \}")
810 var fmap = new FileReader.open("{path}.map")
811 var map = fmap.read_all
812 fmap.close
813
814 var article = new TplArticle("graph")
815 var alt = ""
816 # FIXME diff hack
817 # if title != null then
818 # article.title = title
819 # alt = "alt='{title.html_escape}'"
820 # end
821 article.css_classes.add "text-center"
822 var content = new Template
823 var name_html = id.html_escape
824 content.add "<img src='{name_html}.png' usemap='#{name_html}' style='margin:auto' {alt}/>"
825 content.add map
826 article.content = content
827 parent.add_child article
828 end
829 end