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